개인적으로 styled-components 좀 좋아한다. 잘만 만들면 재사용성이 꽤나 높기 때문에 (잘! 만들면..)
그래서 storybook 테스팅을 진행하며 styled-components를 적용하는 법을 정리해보려고 한다.
Styled-components 환경 설정
1. styled-components 설치
npm install styled-components
2. addon-themes 설치
(다른 방법도 있다고 하던데 addon을 쓰는 쪽이 편해보여서 이렇게 진행)
npx storybook@latest add @storybook/addon-themes
3. preview.ts 파일 수정
위의 두 라이브러리 설치를 마치면 preview.ts 파일 코드가 자동으로 업데이트된다.
import type { Preview } from "@storybook/react";
import { createGlobalStyle, ThemeProvider } from 'styled-components';
import { withThemeFromJSXProvider } from '@storybook/addon-themes';
/* TODO: update import for your custom theme configurations */
import { lightTheme, darkTheme } from '../path/to/themes';
/* TODO: replace with your own global styles, or remove */
const GlobalStyles = createGlobalStyle`
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
`;
const preview: Preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
decorators: [withThemeFromJSXProvider({
themes: {
light: lightTheme,
dark: darkTheme,
},
defaultTheme: 'light',
Provider: ThemeProvider,
GlobalStyles,
})]
};
export default preview;
parameters 부분을 제외하고는 전부 새롭게 추가된 내용이다.
여기서 TODO 부분들을 원하는 커스텀 방향에 맞게 바꿔준다.
① GlobalStyles 커스텀
styles 폴더에 global.ts 파일을 분리하여 모듈화했다.
import { createGlobalStyle } from "styled-components";
export const GlobalStyles = createGlobalStyle`
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
padding: 0;
margin: 0;
font-family: 'Pretendard';
}
body {
font-size: 1rem;
}
a { cursor: pointer; text-decoration: none; }
button { cursor: pointer }
p { margin: 0 }
...
`;
프로젝트 전반에서 공통적으로 사용할 스타일링을 지정해준다.
② themes 커스텀
themes는 global 보다는 조금 부분적인 단위
주로 하위에 colors, media 등을 정의하는 것 같다.
import { DefaultTheme } from "styled-components";
export const theme: DefaultTheme = {
colors: {
...
},
};
💻 수정된 preview.ts 파일
import type { Preview } from "@storybook/react";
import { ThemeProvider } from "styled-components";
import { withThemeFromJSXProvider } from "@storybook/addon-themes";
import { theme } from "../src/styles/themes";
import { GlobalStyles } from "../src/styles/global";
const preview: Preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
decorators: [
withThemeFromJSXProvider({
themes: {
theme,
},
defaultTheme: "theme",
Provider: ThemeProvider,
GlobalStyles,
}),
],
};
export default preview;
styled-components로 컴포넌트 UI 스타일링
이전 게시물에서 만들어 둔 CommonBtn의 스타일링을 styled-components로 바꿔볼 것이다.
🔎 CommonBtn.styles.tsx
import styled, { css } from "styled-components";
export const ButtonContainer = styled.button<{ disabled?: boolean }>`
background-color: ${({ theme }) => theme.colors.Lime[200]};
color: ${({ theme }) => theme.colors.Lime[900]};
font-weight: 700;
border: none;
border-radius: 20px;
padding: 10px 30px;
${({ disabled }) =>
disabled &&
css`
background-color: ${({ theme }) => theme.colors.Gray[100]};
color: ${({ theme }) => theme.colors.Gray[600]};
cursor: auto;
`}
`;
theme에 정의해둔 color를 쉽게 빼서 쓸 수 있다. (디자인 시스템 굿굿)
disabled일 때의 스타일을 별개로 지정해줬다.
🔎 CommonBtn.tsx
import { ButtonContainer } from "./CommonBtn.styles";
interface Props {
children: string;
disabled?: boolean;
onClick: () => void;
}
export default function CommonBtn({ children, disabled, onClick }: Props) {
return (
<ButtonContainer disabled={disabled} onClick={onClick}>
{children}
</ButtonContainer>
);
}
🔎 CommonBtn.stories.ts
import { fn } from "@storybook/test";
import CommonBtn from "./CommonBtn";
import { Meta } from "@storybook/react";
const meta: Meta<typeof CommonBtn> = {
title: "CommonBtn",
component: CommonBtn,
parameters: {
layout: "centered", // 중앙 배치
},
tags: ["autodocs"], // 문서 자동 생성
argTypes: {
children: { control: "text" },
disabled: { control: "boolean" },
onClick: { action: "clicked" },
},
args: {
children: "BUTTON",
disabled: false,
onClick: fn(),
},
};
export default meta;
export const Primary = {};
export const Disable = {
args: {
disabled: true,
},
};
🎨 결과 Docs
'Storybook' 카테고리의 다른 글
Storybook 스토리 파일 생성 방법 (0) | 2024.06.07 |
---|---|
Storybook 컴포넌트 패키지 배포 (with Chromatic) (0) | 2024.05.27 |
storybook onchange 이벤트 테스트 (0) | 2024.05.20 |
storybook으로 버튼 컴포넌트 만들기 (0) | 2024.04.09 |
Storybook이란? | 사용하는 이유 (0) | 2024.04.09 |