팔레트를 정의하면 해당 컬러를 Material-UI의 컴포넌트에서 활용 가능하다. MUI 테마에 색상 코드를 적용시킬 것이다.
Material-UI의 텍스트 스타일을 정의하여 테마에 적용시킬 것이다.
1. 프로젝트에서 필요한 색상과 텍스트 스타일들을 정의
2. 전역적으로 테마를 적용할 MUI Theme 설정 커스텀 파일을 정의
3. _app.tsx에 해당 컴포넌트로 감싸기
import { PaletteOptions } from '@mui/material';
const Palette = (): PaletteOptions => {
return {
primary: {
main: '#FF6415',
dark: '',
},
secondary: {
main: '#E3BA8A',
dark: '',
},
background: {
default: '#FFFFFFF',
paper: '',
},
error: {
main: '#FF4545',
dark: '',
},
info: {
main: '#1A1A1A',
dark: '',
},
grey: {
50: '#FCFCFC',
100: '#EFEFEF',
200: '#DFDFDF',
300: '#B7B7B7',
400: '#949494',
500: '#777777',
600: '#555555',
700: '#3F3F3F',
800: '#2A2A2A',
900: '#1A1A1A',
},
};
};
export default Palette;
해당 프로젝트에서 쓰이는 다양한 색들을 분류하여 MUI Theme에서 사용할 색상코드 정의 함수를 정의한다. (참고: 팔레트의 return type은 PaletteOptions)
정의하면서 활용할 타입 지정을 해준다.
import { TypographyVariantsOptions } from '@mui/material';
export type ThemeMode = 'light' | 'dark';
// 다크 모드 구현을 위해 테마 모드 정의
export type FontFamily = // 사용할 모든 폰트들
| 'PretendardExtraBold'
| 'PretendardBold'
| 'PretendardSemiBold'
| 'PretendardMedium'
| 'PretendardRegular';
export interface CustomTypographyVariantsOptions
extends TypographyVariantsOptions {
fontWeightSemiBold: number;
fontWeightExtraBold: number;
}
CustomTypographyVariatnsOptions 타입은 TypographyVariantsOptions 인터페이스를 상속하였다.
=> mode: ThemeMode, fontFamily: FontFamily, palette: PaletteOptions와 같은 인자들은 TypographyVariantsOptions에 이미 정의되어 있기 때문에 상속을 통해 사용
import { PaletteOptions } from '@mui/material';
import {
CustomTypographyVariantsOptions,
FontFamily,
ThemeMode,
} from '~/types/theme';
const Typography = (
mode: ThemeMode, // 다크 모드를 위해
fontFamily: FontFamily, // text의 폰트를 위해
palette: PaletteOptions // 정의한 팔레트를 활용해 text 색깔을 위해
): CustomTypographyVariantsOptions => ({
// 텍스트 스타일 설정
htmlFontSize: 16,
fontFamily,
fontWeightRegular: 100,
fontWeightMedium: 200,
fontWeightSemiBold: 300,
fontWeightBold: 400,
fontWeightExtraBold: 500,
// Title1
h1: {
fontFamily: 'PretendardBold',
fontWeight: 600,
fontSize: '24px',
color: mode === 'light' ? palette.grey?.[900] : palette.grey?.[50],
},
// Title2
h2: {
fontFamily: 'PretendardBold',
fontWeight: 600,
fontSize: '22px',
color: mode === 'light' ? palette.grey?.[900] : palette.grey?.[50],
},
// Title3
h3: {
fontFamily: 'PretendardBold',
fontWeight: 600,
fontSize: '20px',
color: mode === 'light' ? palette.grey?.[900] : palette.grey?.[50],
},
// Title4
h4: {
fontFamily: 'PretendardBold',
fontWeight: 600,
fontSize: '18px',
color: mode === 'light' ? palette.grey?.[900] : palette.grey?.[50],
},
// Title5
h5: {
fontFamily: 'PretendardBold',
fontWeight: 600,
fontSize: '16px',
color: mode === 'light' ? palette.grey?.[900] : palette.grey?.[50],
},
// Body1
body1: {
fontFamily: 'PretendardMedium',
fontSize: '15px',
color: mode === 'light' ? palette.grey?.[900] : palette.grey?.[50],
},
// Body2
body2: {
fontFamily: 'PretendardMedium',
fontSize: '14px',
color: mode === 'light' ? palette.grey?.[900] : palette.grey?.[50],
},
// Body3
subtitle1: {
fontFamily: 'PretendardMedium',
fontSize: '13px',
fontWeight: 600,
color: mode === 'light' ? palette.grey?.[900] : palette.grey?.[50],
},
// Body4
subtitle2: {
fontFamily: 'PretendardMedium',
fontSize: '12px',
fontWeight: 500,
color: mode === 'light' ? palette.grey?.[900] : palette.grey?.[50],
},
// Body5
caption: {
fontFamily: 'PretendardMedium',
fontSize: '11px',
fontWeight: 500,
color: mode === 'light' ? palette.grey?.[900] : palette.grey?.[50],
},
overline: {
lineHeight: 1.66,
color: mode === 'light' ? palette.grey?.[900] : palette.grey?.[50],
},
button: {
fontFamily: 'PretendardRegular',
textTransform: 'capitalize',
color: mode === 'light' ? palette.grey?.[900] : palette.grey?.[50],
},
});
export default Typography;
MUI Theme에서 사용할 text style을 정의하는 함수를 다음과 같이 정의해준다.
h1, h2, h3, h4, h5: 각각 제목에 해당하는 텍스트 스타일을 정의합니다. 폰트 크기, 폰트 두께, 색상 등을 지정할 수 있습니다.
body1, body2: 본문에 해당하는 텍스트 스타일을 정의합니다. 폰트 크기, 폰트 두께, 색상 등을 지정할 수 있습니다.
subtitle1, subtitle2: 소제목에 해당하는 텍스트 스타일을 정의합니다. 폰트 크기, 폰트 두께, 색상 등을 지정할 수 있습니다.
caption: 캡션에 해당하는 텍스트 스타일을 정의합니다. 폰트 크기, 폰트 두께, 색상 등을 지정할 수 있습니다.
overline: 오버라인에 해당하는 텍스트 스타일을 정의합니다. 줄 높이(line height)와 색상 등을 지정할 수 있습니다.
button: 버튼에 해당하는 텍스트 스타일을 정의합니다. 폰트 패밀리, 대문자/소문자 변환, 색상 등을 지정할 수 있습니다.
이렇게 정의된 텍스트 스타일은 MUI의 테마 객체에 적용되어 사용될 수 있습니다.
import React, { useMemo } from 'react';
import {
CssBaseline,
StyledEngineProvider,
ThemeProvider,
PaletteOptions,
} from '@mui/material';
import { Theme, createTheme } from '@mui/material/styles';
import { CustomTypographyVariantsOptions } from '~/types/theme';
import useConfig from '~/hooks/useConfig';
import Palette from './palette';
import Typography from './typography';
// MUI Theme 설정 커스텀 파일
const ThemeCustomization = ({ children }: React.PropsWithChildren) => {
const { mode, fontFamily } = useConfig();
// Palette 함수를 호출해 테마 객체 생성
const palette: PaletteOptions = useMemo<PaletteOptions>(
() => Palette(),
[mode]
);
// Typography 함수를 호출해 typography 객체 생성
// (mode, fontFamil, palette 값 전달)
const typography: CustomTypographyVariantsOptions =
useMemo<CustomTypographyVariantsOptions>(
() => Typography(mode, fontFamily, palette),
[mode, fontFamily, palette]
);
// createTheme 함수를 호출해 MUI 테마 전체 설정하는 객체 생성
// (앞에서 정의한 palette, typography 전달)
const theme: Theme = useMemo(
() => createTheme({ palette, typography }),
[palette, typography]
);
return (
/**
* MUI 에서 Styled-Component 문법을 사용하기 위해 StyledEngineProvider 를 감싸줌
* injectFirst prop을 설정하여 MUI를 최우선으로 스타일이 적용
* MUI 보다 먼저 최상단에 주입되어야함
*/
<StyledEngineProvider injectFirst>
// 앞서 생성한 테마 적용 => 하위 컴포넌트에서 해당 테마를 사용
<ThemeProvider theme={theme}>
<CssBaseline />
{children}
</ThemeProvider>
</StyledEngineProvider>
);
};
export default ThemeCustomization;
const App = ({ Component, pageProps }: AppProps) => {
return (
<Provider store={store}>
<QueryClientProvider client={queryClient}>
<ConfigProvider>
<ThemeCustomization> // 정의한 컴포넌트 감싸기
<GlobalStyle />
<DynamicLayout>
<Component {...props} />
</DynamicLayout>
<ReactQueryDevtools initialIsOpen={false} />
</ThemeCustomization>
</ConfigProvider>
</QueryClientProvider>
</Provider>
);
}
_app.tsx 파일에서 ThemeCustomization 컴포넌트를 감싸준다.