[theme]mui palette, typography 설정

hansoom·2023년 7월 5일
0

design system

목록 보기
4/4
post-thumbnail

mui palette, typography 정의해 테마 적용시키기

  • 팔레트를 정의하면 해당 컬러를 Material-UI의 컴포넌트에서 활용 가능하다. MUI 테마에 색상 코드를 적용시킬 것이다.

  • Material-UI의 텍스트 스타일을 정의하여 테마에 적용시킬 것이다.

1. 프로젝트에서 필요한 색상과 텍스트 스타일들을 정의
2. 전역적으로 테마를 적용할 MUI Theme 설정 커스텀 파일을 정의
3. _app.tsx에 해당 컴포넌트로 감싸기

1. themes 폴더에 palette.ts파일을 생성해 다음과 같이 mui color palette를 정의

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)

1-2. themes 폴더에 typography.ts파일을 생성해 다음과 같이 텍스트 스타일을 정의

정의하면서 활용할 타입 지정을 해준다.

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을 정의하는 함수를 다음과 같이 정의해준다.

  1. h1, h2, h3, h4, h5: 각각 제목에 해당하는 텍스트 스타일을 정의합니다. 폰트 크기, 폰트 두께, 색상 등을 지정할 수 있습니다.

  2. body1, body2: 본문에 해당하는 텍스트 스타일을 정의합니다. 폰트 크기, 폰트 두께, 색상 등을 지정할 수 있습니다.

  3. subtitle1, subtitle2: 소제목에 해당하는 텍스트 스타일을 정의합니다. 폰트 크기, 폰트 두께, 색상 등을 지정할 수 있습니다.

  4. caption: 캡션에 해당하는 텍스트 스타일을 정의합니다. 폰트 크기, 폰트 두께, 색상 등을 지정할 수 있습니다.

  5. overline: 오버라인에 해당하는 텍스트 스타일을 정의합니다. 줄 높이(line height)와 색상 등을 지정할 수 있습니다.

  6. button: 버튼에 해당하는 텍스트 스타일을 정의합니다. 폰트 패밀리, 대문자/소문자 변환, 색상 등을 지정할 수 있습니다.

이렇게 정의된 텍스트 스타일은 MUI의 테마 객체에 적용되어 사용될 수 있습니다.

2. 폴더 theme안에 index.tsx 파일에 MUI Theme 설정 커스텀 파일 정의해 전체적인 application에 테마를 적용

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;

3. application의 최상위 컴포넌트인 pages 폴더의 _app.tsx에 ThemeCustomize 감싸기

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 컴포넌트를 감싸준다.

  • 전역적인 MUI 테마를 설정하고 커스터마이즈 가능
  • Styled-Component 문법 사용 가능
  • 애플리케이션 전체에서 일관된 테마를 제공하고, MUI 컴포넌트와 Styled-Component를 함께 사용 가능

0개의 댓글