Storybook

[ Storybook ] Storybook의 args, parameters

행복주의자 2025. 3. 29. 22:41

# args

- 컴포넌트가 어떻게 렌더링되어야 하는지에 대해 하나의 자바스크립트 객체로 정의를 해놓은 것

- 컴포넌트의 props, slot, style, input 등 다양한 속성값을 지정하는데 사용되는 객체

- 컴포넌트의 다양한 상태를 시각적으로 테스트하고 문서화할 수 있다.

 

## 특징

1. 동적 속성 : 스토리북의 UI에서 속성값을 실시간으로 변경 가능. 컴포넌트의 다양한 상태를 쉽게 확인

2. 재사용성 : 여러 스토리에서 동일한 args를 재사용 가능. 코드중복을 줄이고 일관성 유지가능

import { Button } from './Button';

export default {
  component: Button,
};

export const Primary = {
  args: {
    primary: true,
    label: 'Button',
  },
};

export const PrimaryLongName = {
  args: {
    ...Primary.args, // 재사용
    label: 'Primary with a really long name',
  },
};

 

 

## args 객체

- args는 story, component, global 레벨로 정의할 수 있다.

 

1. story 레벨에서의 args

: 해당 story만 적용된다.

import { Button } from './Button';

export default {
  component: Button,
};

// story
export const Primary = {
  args: { // story level에서의 args
    primary: true,
    label: 'Button',
  },
};

// story
export const PrimaryLongName = {
  args: { // story level에서의 args
    ...Primary.args,
    label: 'Primary with a really long name',
  },
};

 

 

2. Component 레벨에서의 args

: 해당 컴포넌트에 속해있는 모든 story에 적용된다.

import { Button } from './Button';

// 하나의 component
export default {
  component: Button,
  args: { // component level에서의 args
    primary: true, // 모든 Button story들은 현재 default값이 primary
  }
};

// story
export const Primary = {
  args: { // story level에서의 args
    primary: true,
    label: 'Button',
  },
};

// story
export const PrimaryLongName = {
  args: { // story level에서의 args
    ...Primary.args,
    label: 'Primary with a really long name',
  },
};

 

 

3. Global 레벨에서의 args

: 특정 컴포넌트가 아닌, 모든 컴포넌트의 story에 적용된다.

export default {
  // 컴포넌트 상관없이 모든 스토리에 적용된다.
  args: { theme: 'light' },
};

 

 

 

하나의 예시로 Button 컴포넌트를 만들어보자.

Button.stories.ts

import type { Meta, StoryObj } from "@storybook/react";

import { Button } from "./Button";

// component
const meta = {
  title: "Example/Button",
  component: Button,
  parameters: {
    layout: "centered",
  },
  tags: ["autodocs"],
  argTypes: {
    backgroundColor: { control: "color" },
  },
  args: { onClick: () => alert('storybook zzang') }, // 해당 컴포넌트의 args
} satisfies Meta<typeof Button>;

export default meta;
type Story = StoryObj<typeof meta>;

// story
export const Primary: Story = {
  args: {  // 해당 story의 args
    primary: true,
    label: "Primay Button",
  },
};

// story
export const Secondary: Story = {
  args: { // 해당 story의 args
    label: "Secondary Button",
  },
};

// story
export const Large: Story = {
  args: { // 해당 story의 args
    size: "large",
    label: "Large Button",
  },
};

// story
export const Small: Story = {
  args: { // 해당 story의 args
    size: "small",
    label: "Small Button",
  },
};

 

 

Button.tsx

import "./button.css";

export interface ButtonProps {
  primary?: boolean;
  backgroundColor?: string;
  size?: "small" | "medium" | "large";
  label: string;
  onClick?: () => void;
}

export const Button = ({
  primary = false,
  size = "medium",
  backgroundColor,
  label,
  ...props
}: ButtonProps) => {
  const mode = primary
    ? "storybook-button--primary"
    : "storybook-button--secondary";
  return (
    <button
      type="button"
      className={["storybook-button", `storybook-button--${size}`, mode].join(
        " "
      )}
      style={{ backgroundColor }}
      {...props}
    >
      {label}
    </button>
  );
};

실제로 props로 args에 담겨있던 값들이 넘어온다.

 

Storybook에 생성된 폴더는 아래와 같다.

 

Docs에 들어가보면 tags의 ["autodocs"]값으로 자동으로 생성된 문서를 볼 수 있다.

 

 

component 레벨에서의 args로 onClick: () => alert('storybook zzang')을 전달하여

Button의 모든 story에 적용돼 어떤 story를 클릭해도 아래와 같은 alert함수가 실행된다.

 

 

 

Primary story에는

args 객체에 priary값은 true, label은 "Primary button"을 넘겨 아래와 같이 렌더링되었고,

Secondary story에는

args 객체에 label은 "Secondary button"을 넘겨 아래와 같이 렌더링되었다.

이렇게 각 args의 값에 따라 컴포넌트 렌더링이 된다.

 

 

# Parameters

- story, addon을 구성하는데 사용되는 정적 metadata.

- args와 마찬가지로 story, component, global 레벨로 정의할 수 있다.

 

import { Button } from './Button';

// component
export default {
  component: Button,
  parameters: {  // component 레벨의 parameters
    backgrounds: {
      default: 'dark',
    },
  },
};

// story
export const OnDark = {
  parameters: { // story 레벨의 parameters
    backgrounds: {
      default: 'dark',
    },
  },
};

story level의 parameters는 project level, component level의 parameters를 override한다.

그리고, component level의 parameters는 project level의 parameters를 override한다.

즉, 우선순위가 story > component > project 순이다.

 

위 코드를 보면 OnDark story의 parameters가 component 레벨의 parameters의 값을 덮어씌운다.

따라서 그대로 backgrounds 컬러가 dark로 렌더링된다.

 

## 사용가능한 paramters

- Storybook은 몇 개의 paramters만 사용가능하다.

  • layout
    • 타입: 'centered' | 'fullscreen' | 'padded'
    • 기본값: 'padded'
    • story의 배치방법
      • centered: 스토리를 캔버스 중앙에 배치합니다.
      • padded: (기본값) 스토리에 패딩을 추가합니다.
      • fullscreen: 패딩 없이 스토리를 그대로 표시합니다.
  • options
    • project level에서만 사용 가능
  • options.storySort
    • 스토리가 Storybook UI에서 표시되는 순서를 지정