본문 바로가기
카테고리 없음

MUI custom-palette 를 동적으로 생성 & tailwind, Material UI 테마(theme) 의 색상 동기화(sync)

by 찬찬2 2024. 8. 5.

빠른 개발을 위해 스타일 관련 라이브러리는 tailwind, 컴포넌트는 MUI 를 사용하려고 한다.

 

그런데, MUI 의 color system 과 tailwind 의 colors 는 조금 다르다.

 

예를 들어 "Teal" 500 의 컬러 코드를 보면 MUI 는  #009688, tailwind 는 #14B8A6 인 것을 볼 수 있다.

 

이와 같이 색상 코드가 서로 일치하지 않기 때문에 MUI 컴포넌트와 tailwind 의 스타일이 섞인 형태인 경우 디자인 시안과 결과물이 다를 수 밖에 없다.

 

tailwind 의 사용 빈도가 MUI 보다 상대적으로 높기 때문에 MUI 의 색상(primary, accent, warn...)을 tailwind 에 맞추기로 하였다.

 

아래는 SCSS 로  tailwind 의 컬러 코드를 $region-themes 변수에 담고 있다. 그리고 동적으로 custom-palette 를 구현하기 위해 $primary-hs, $primary-go 에 각각 primary 컬러코드가 다르게 담겨있다.

 

 

/* Setting SCSS variables */
$primary-hs: (
  50:  #f0fdfa,
  100: #ccfbf1,
  200: #99f6e4,
  300: #5eead4,
  400: #2dd4bf,
  500: #14b8a6,
  600: #0d9488,
  700: #0f766e,
  800: #115e59,
  900: #134e4a,
  950: #042f2e,
  DEFAULT: #0d9488,
  contrast: (
    50: #052e16,
    100: #052e16,
    200: #052e16,
    300: #052e16,
    400: #052e16,
    500: #052e16,
    600: #052e16,
    700: #FFFFFF,
    800: #FFFFFF,
    900: #FFFFFF,
    950: #FFFFFF,
    DEFAULT: #FFFFFF
  )
);
$primary-go: (
  50: #eef2ff,
  100: #e0e7ff,
  200: #c7d2fe,
  300: #a5b4fc,
  400: #818cf8,
  500: #6366f1,
  600: #4f46e5,
  700: #4338ca,
  800: #3730a3,
  900: #312e81,
  950: #1e1b4b,
  DEFAULT: #4f46e5,
  contrast: (
    50: #1e1b4b,
    100: #2a2938,
    200: #1e1b4b,
    300: #1e1b4b,
    400: #1e1b4b,
    500: #FFFFFF,
    600: #FFFFFF,
    700: #FFFFFF,
    800: #FFFFFF,
    900: #FFFFFF,
    950: #FFFFFF,
    DEFAULT: #FFFFFF
  )
);

$accent: (
  50:  #fafafa,
  100: #f5f5f5,
  200: #e5e5e5,
  300: #d4d4d4,
  400: #a3a3a3,
  500: #737373,
  600: #525252,
  700: #404040,
  800: #262626,
  900: #171717,
  950: #0a0a0a,
  DEFAULT: #525252,
  contrast: (
    50: #1e1b4b,
    100: #1e1b4b,
    200: #1e1b4b,
    300: #1e1b4b,
    400: #1e1b4b,
    500: #FFFFFF,
    600: #FFFFFF,
    700: #FFFFFF,
    800: #FFFFFF,
    900: #FFFFFF,
    950: #FFFFFF,
    DEFAULT: #FFFFFF
  )
);
$warn: (
  50:  #fef2f2,
  100: #fee2e2,
  200: #fecaca,
  300: #fca5a5,
  400: #f87171,
  500: #ef4444,
  600: #dc2626,
  700: #b91c1c,
  800: #991b1b,
  900: #7f1d1d,
  950: #450a0a,
  DEFAULT: #ef4444,
  contrast: (
    50: #450a0a,
    100: #450a0a,
    200: #450a0a,
    300: #450a0a,
    400: #450a0a,
    500: #fef2f2,
    600: #FFFFFF,
    700: #FFFFFF,
    800: #FFFFFF,
    900: #FFFFFF,
    950: #FFFFFF,
    DEFAULT: #FFFFFF
  )
);

$region-themes: (
  hs: (
    selector: ".theme-hs",
    primary: $primary-hs,
    accent: $accent,
    warn: $warn,
    background: #EAF0F0
    ),
  go: (
    selector: ".theme-go",
    primary: $primary-go,
    accent: $accent,
    warn: $warn,
    background: #EDECF4
  )
);

 

아래는 위 변수를 MUI 에 적용하는 코드이다.

 

@use "sass:map";
@use '@angular/material' as mat;
@use "region-themes" as regionThemes;
@include mat.core();
@include mat.all-component-themes((
  color: null,
  density: 0,
  typography: mat.define-typography-config(
    $font-family: 'Pretendard, sans-serif',
    $body-1: mat.define-typography-level(14px, 18px, 400),
    $button: mat.define-typography-level(14px, 18px, 400),
  )
));


@each $name, $theme in regionThemes.$region-themes {
  $palettes: ();
  @each $name in (primary, accent, warn) {
    $palette: mat.define-palette(map.get($theme, $name));
    $palette: map.merge($palette, (
      default: map.get(map.get($theme, $name), DEFAULT),
      lighter: map.get(map.get($theme, $name), 100),
      darker: map.get(map.get($theme, $name), 700),
      text: map.get(map.get($theme, $name), DEFAULT),
      default-contrast: map.get(map.get(map.get($theme, $name), contrast), DEFAULT),
      lighter-contrast: map.get(map.get(map.get($theme, $name), contrast), 100),
      darker-contrast: map.get(map.get(map.get($theme, $name), contrast), 700)
    ));

    $palettes: map.merge($palettes, (#{$name}: $palette));
  }
  $light-theme: mat.define-light-theme((
    color: $palettes
  ));

  // Generate the theme styles and scope them to the selector
  #{map.get($theme, selector)} .light,
  #{map.get($theme, selector)}.light {
    @include mat.all-component-colors($light-theme);

    --primary-600: #{map-get(map.get($theme, primary), 600)};
    --primary-500: #{map-get(map.get($theme, primary), 500)};
    --primary-600-hover: #{map-get(map.get($theme, primary), 50)};
    --accent: #{map-get(map.get($theme, accent), 500)};
    --main-title: #{map-get(map.get($theme, accent), 500)};
    --sub-title: #{map-get(map.get($theme, accent), 500)};
    --description: #{map-get(map.get($theme, accent), 500)};
    --bg-primary: #{map-get($theme, background)};
  }
}

:root {
  --warn: #ef4444; // red-500
  --success: #22c55e; // green-500
}

 

이제 MUI custom-palette 에 tailwind 의 Teal 과 Indigo 팔레트가  적용되었다. 상황에 따라 만약 body 요소에 "theme-hs light" 또는 "theme-go light" class name 을 붙여주면 된다.

 

로그인 버튼의 배경색을 보면, 오른쪽과 같이 변수에 의해 색상이 정의되어있고, 그 변수는 theme-hs light 에 의해 동적으로 생성된 것을 볼 수 있다.

 

tailwind 도 MUI 와 똑같이 class name 에 따라 동적으로 브랜드 컬러(primary)가 바뀌어 줘야 한다. 그러기 위해서는 tailwind.config.js 파일에서 아래와 같이 설정(extend)하면 된다.

 

const colors = require('tailwindcss/colors');

module.exports = {
  content : ['./apps/**/*.{html,scss,ts}', './libs/**/*.{html,scss,ts}'],
  important : true,
  theme: {
    extend: {
      colors: {
        'primary-600': 'var(--primary-600)',
        'primary-500': 'var(--primary-500)',
        'accent': 'var(--accent)',
        'main-title': 'var(--main-title)',
        'sub-title': 'var(--sub-title)',
        'description': 'var(--description)',
        'bg-primary': 'var(--bg-primary)',
        'success': 'var(--success)',
        'warn': 'var(--warn)',
      }
    },
  },
  plugins: [],
}

 

적용된 모습을 보면,

 

 

기존 tailwind color 에 위 변수가 추가된 모습을 볼 수 있다.

댓글