Chakra UI는 컬러테마를 적용하는 것이 매우 간단하다는 큰 장점이 있다. 단순히 라이트모드와 다크모드만을 지원하는 것이 아니라, 테마에 맞는 다양한 컬러를 적용할 수 있어 사용자에게 더욱 풍부한 경험을 제공할 수 있다.
컬러테마를 적용하기 위해 Chakra UI에서 제공하는 extendTheme 함수를 사용할 것이다. 이 함수를 사용하면 기본적인 Chakra UI 테마에 추가적인 컬러를 정의할 수 있다.
//theme.ts
import { extendTheme } from "@chakra-ui/react";
const config = {
initialColorMode: "light",
useSystemColorMode: false,
};
const theme = extendTheme({
config,
colors: {
purple: {
light: "#7F5AD5",
dark: "#C7A8F7",
},
teal: {
light: "#319795",
dark: "#81E6D9",
},
cyan: {
light: "#00B5D8",
dark: "#9DECF9",
},
},
});
위와 같이 config를 정의하고 colors 객체 안에 필요한 컬러들을 추가로 정의해 준다. 이렇게 정의한 테마는 ChakraProvider 컴포넌트를 통해 어플리케이션 전역에서 사용할 수 있다.
//_app.tsx
import { ChakraProvider } from "@chakra-ui/react";
import { RecoilRoot } from "recoil";
function App() {
return (
<ChakraProvider theme={theme}>
<RecoilRoot>
{/* 어플리케이션 컴포넌트 */}
</RecoilRoot>
</ChakraProvider>
);
}
그리고 헤더와 같이 특정 컴포넌트에서 컬러를 변경해야 하는 경우, useEffect를 사용하여 컬러 값을 받아와 적용할 수 있다. 이때 useColorModeValue 훅을 사용하여 라이트모드와 다크모드에서 각각 다른 컬러 값을 반환할 수 있다.
//Header.tsx
import { useColorModeValue } from "@chakra-ui/react";
import { useRecoilValue, useEffect, useState } from "react";
import { colorThemeAtom, returnColors } from "../atoms/colorThemeAtom";
function Header() {
const colorTheme = useRecoilValue(colorThemeAtom);
const [lightColor, setLightColor] = useState("");
const [darkColor, setDarkColor] = useState("");
const relativeColor = useColorModeValue(lightColor, darkColor);
useEffect(() => {
const [lc, dc, hbc] = returnColors(colorTheme);
setLightColor(lc);
setDarkColor(dc);
}, [colorTheme]);
return (
<Box bgColor={relativeColor}>
{/* 헤더 내용 */}
</Box>
);
}
위와 같이 useRecoilValue를 통해 colorTheme 값을 가져오고, returnColors 함수를 통해 필요한 컬러 값을 받아온다. 이렇게 받아온 컬러 값을 useColorModeValue 훅에 넘겨서 라이트모드와 다크모드에서 각각 다른 컬러 값을 반환하게 하고 이를 Box컴포넌트의 bgColor로 설정한다.
returnColors 함수를 작성해야 한다. 이 함수는 colorTheme 인자를 받아서 각각의 컬러 모드(light/dark)에 해당하는 LightColor, DarkColor, HeaderBackgroundColor 값을 리턴한다.
//utilFn.ts
const returnColors = (colorTheme: string): [string, string, string] => {
switch (colorTheme) {
case "purple":
return ["purple.light", "purple.dark", "purple.900"];
case "teal":
return ["teal.light", "teal.dark", "teal.900"];
case "cyan":
return ["cyan.light", "cyan.dark", "cyan.900"];
default:
return ["purple.light", "purple.dark", "purple.900"];
}
};
이제, Header 컴포넌트에서 위에서 작성한 로직을 사용해서 색상을 변경할것이다.
const Header: React.FC = () => {
const colorTheme = useRecoilValue(colorThemeAtom);
const [lightColor, setLightColor] = useState("");
const [darkColor, setDarkColor] = useState("");
const relativeColor = useColorModeValue(lightColor, darkColor);
useEffect(() => {
const [lc, dc, hbc] = returnColors(colorTheme);
setLightColor(lc);
setDarkColor(dc);
}, [colorTheme]);
return (
<Box
as="header"
bgColor={relativeColor}
transition="all 0.2s ease-out"
>
{/* 헤더 내용 */}
</Box>
);
};
Header 컴포넌트에서 useRecoilValue 훅으로 colorTheme을 받아와서, 이 값을 returnColors 함수로 넘겨서 LightColor, DarkColor, HeaderBackgroundColor 값을 가져온다. 그리고 이 값을 useState 훅으로 관리해서 useColorModeValue 훅으로 얻어진 relativeColor에 할당한다.
마지막으로, 이 relativeColor 값을 bgColor 속성으로 할당하여 Header 컴포넌트의 색상을 변경한다.