Giter Site home page Giter Site logo

Comments (2)

yoojinsuah avatar yoojinsuah commented on August 14, 2024

문제: 기존에 정의되어있는 color 타입에 맞춰서 덮어쓰는 것은 가능하지만, 새로운 값을 넣어서 쓰는 것이 안된다
스크린샷 2023-09-26 오후 4 04 07
위 예시에서 Hex값을 다른 값으로 덮어쓰는 것은 가능하지만
스크린샷 2023-09-26 오후 4 06 52
위 예시처럼 새로운 프로퍼티를 넣었을 때 타입지원을 받을 수 없다

해결해야 합니다. 타입스크립트 공부좀 해야겠습니다...

from react-libraries.

yoojinsuah avatar yoojinsuah commented on August 14, 2024

기존의 테마 설정 방법

  1. emotion.d.ts 파일을 만들어서 Theme 타입을 선언한다. 기본적으로 Theme은 빈 객체 타입이며, 우리는 여기에 MusmaTheme을 상속해준 뒤 사용합니다. Emotion - Define a theme
import '@emotion/react'

import { MusmaTheme } from './musma/theme'

declare module '@emotion/react' {
  // eslint-disable-next-line @typescript-eslint/no-empty-interface
  export interface Theme extends MusmaTheme {}
}

  1. 프로젝트에서 사용할 테마는 아래와 같이 이미 정의된 기본값인 DefaultTheme을 불러와서, 커스텀 하고 싶은 부분을 덮어쓰는 형태로 사용한다. 아래 예시(대동)와 같이 theme 변수를 만들어서 MusmaProvider 에 전달합니다. 전달하지 않으면 디자인시스템에 정의되어있는 기본값을 사용합니다.

const theme = {
  ...DefaultTheme,
  colors: {
    ...DefaultTheme.colors,
    primary: {
      lighter: '#1FA2FF',
      light: '#006CE8',
      main: '#013F6B',
      dark: '#013F6B',
      darker: '#003E6A',
    },
    blue: {
      lighter: '#1FA2FF',
      light: '#006CE8',
      main: '#084C9C',
      dark: '#013F6B',
      darker: '#003E6A',
    },
...생략...
}

const App = () => {
  return (
    <I18nextProvider i18n={i18n}>
      <MusmaProvider theme={theme}> //--> props로 theme를 전달
        <ApolloClientProvider>
          <QueryClientProvider>
            <Toaster />
            <Suspense fallback={<LoadingScreen type="fallback" />}>
              <RouterProvider router={AppRouter} />
            </Suspense>
          </QueryClientProvider>
        </ApolloClientProvider>
      </MusmaProvider>
    </I18nextProvider>
  )
}

변경 후

1. 다중 테마를 사용하지 않는 경우

위에서 처럼 emotion.d.ts 파일을 만든 뒤, createTheme 함수에 DefaultTheme를 인자로 전달해 theme 객체를 생성합니다.
또는 DefaultTheme과 함께 덮어쓰고 싶은 프로퍼티를 전달해 커스터마이징 합니다.

// 기본 테마를 사용하거나
const theme = createTheme(DefaultTheme)
// 원하는 값을 덮어쓴다
const theme2 =  = createTheme({
  colors: {
    ...DefaultTheme.colors,
    black: { main: 'black', light: 'yellow', dark: 'green', darker: 'blue', lighter: 'white' },
  },
})

MusmaProvider에 전달할 때는 defaultTheme 속성에 Props로 전달해야 합니다

const rootElement = document.getElementById('root')

if (rootElement) {
  createRoot(rootElement).render(
    <MusmaProvider defaultTheme={theme}>
      <ToastContextProvider position="top-right" limit={3} newestOnTop>
        <BrowserRouter>
          <Routes>
            <Route element={<Component />} path="" />
            <Route element={<div>여기서도 토스트 팝업이 잘 뜨는지 봐주십쇼</div>} path="toast" />
          </Routes>
        </BrowserRouter>
      </ToastContextProvider>
    </MusmaProvider>,
  )
}

2. 다중 테마를 사용해야하는 경우

  1. emotion.d.ts 파일에 위와 같이 Theme을 선언해주되, 새롭게 추가할 프로퍼티의 타입을 추가한다. 여기서는 새로운 색상 세트인 palette 프로퍼티의 타입을 선언했습니다. 기존의 colors 프로퍼티는 key의 이름을 blue, black, gray 등 특정 색상과 직접 연결되는 이름으로 정해두었기 때문에 멀티 테마 기능에 적합하지 않습니다.(예를 들어 검은색인 텍스트가 다크모드에서는 흰색으로 나와야한다면, 텍스트 색상을 black.main으로 사용할 경우 라이트 모드에서만 유의미한 이름이 됩니다. 그보다는 priamry, secondary 와 같이 간접적인 이름이 나을듯합니다)
import type { MusmaTheme } from 'src/theme'
import '@emotion/react'

declare module '@emotion/react' {
  // eslint-disable-next-line @typescript-eslint/no-empty-interface
  export interface Theme extends MusmaTheme {
    palette: {
      primary: {
        lighter: string
        light: string
        main: string
        dark: string
        darker: string
      }
      secondary: {
        lighter: string
        light: string
        main: string
        dark: string
        darker: string
      }
      warning: {
        lighter: string
        light: string
        main: string
        dark: string
        darker: string
      }
    }
  }
}
  1. createTheme 함수를 이용해서 필요한 만큼 테마 객체를 만든다. 이때 위에서 정의한 palette 타입의 객체를 인자로 전달해준다.
const theme1 = createTheme({
  palette: {
    primary: {
      lighter: '#DFE7EB',
      light: '#D9E1E5',
      main: '#D0D5DD',
      dark: '#C4D2E0',
      darker: '#BAC7D5',
    },
    secondary: {
      lighter: '#F2F8FB',
      light: '#118EE5',
      main: '#036DB7',
      dark: '#025996',
      darker: '#003E6A',
    },
    warning: {
      lighter: '#FD9009',
      light: '#FFAB43',
      main: '#FD9009',
      dark: '#E76F00',
      darker: '#D86900',
    },
  },
})

const theme2 = createTheme({
  palette: {
    primary: {
      lighter: '#FD9009',
      light: '#FFAB43',
      main: '#FD9009',
      dark: '#E76F00',
      darker: '#D86900',
    },
    secondary: {
      lighter: '#DFE7EB',
      light: '#D9E1E5',
      main: '#D0D5DD',
      dark: '#C4D2E0',
      darker: '#BAC7D5',
    },
    warning: {
      lighter: '#F2F8FB',
      light: '#118EE5',
      main: '#036DB7',
      dark: '#025996',
      darker: '#003E6A',
    },
  },
})
  1. MusmaProvider에 defaultTheme과 함께 themeOptions를 전달한다. themeOptions는 내부적으로 컨텍스트를 통해 하위 컴포넌트에서 접근할 수 있게되며, 앱 실행중 테마를 변경할 때 사용됩니다.
const themeOptions = [
  { label: 'first', value: theme1 },
  { label: 'second', value: theme2 },
]

const rootElement = document.getElementById('root')

if (rootElement) {
  createRoot(rootElement).render(
    <MusmaProvider defaultTheme={theme1} themeOptions={themeOptions}>
      <ToastContextProvider position="top-right" limit={3} newestOnTop>
        <BrowserRouter>
          <Routes>
            <Route element={<Component />} path="" />
            <Route element={<div>여기서도 토스트 팝업이 잘 뜨는지 봐주십쇼</div>} path="toast" />
          </Routes>
        </BrowserRouter>
      </ToastContextProvider>
    </MusmaProvider>,
  )
}
2023-11-08.1.59.29.mov

from react-libraries.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.