react-docgen-(typescript)를 사용하여 storybook argTypes 자동 생성하기

jh·2024년 6월 28일

storybook

목록 보기
1/1
  • 이런게 있구나 하고 재미로 봐주시면 감사하겠습니다
  • vite 사용

storybook에 argTypes를 직접 입력해줘야 storybook 상에서 해당 prop에 대한 테스트가 가능하다

export default {
  title: "Button",
  component: Button,
  parameters: {
    layout: "centered",
  },
  tags: ["autodocs"],
  argTypes: {
    size: {
      control: { type: "radio" },
      description: "버튼의 높이를 조절할 수 있습니다",
      options: ["small", "medium", "large"],
    },
    variant: {
      control: { type: "radio" },
      description: "border의 여부에 따라 primary/text로 나뉩니다",
      options: ["primary", "text"],
    },
    br: {
      control: { type: "radio" },
      description: "borderRadius를 조절할 수 있습니다",
      options: ["normal", "rounded"],
    },
    disabled: {
      control: { type: "boolean" },
      description: "버튼의 클릭을 제어할 수 있습니다",
    },
  },
  args: {
    onClick: fn(),
  },
} satisfies Meta<typeof Button>

어떤 props가 존재하는지 , 해당 props를 어떤 식으로 control 할건지를 일일이 추가해줘야 했는데,
일단 IDE 상에서 해당 컴포넌트에 어떤 props가 존재하는지 미리보기가 안돼서 컴포넌트/stories.tsx를 왔다갔다 하면서 작성해야했다

휴먼 에러가 발생하기 매우 쉬운 환경이다

  • satisfies Meta<typeof Button> 이것 때문인지 props에 대한 타입 체크는 해준다(존재하지 않는 props가 있을경우 에러)

Control 전역 설정

preview.tsx 에서 argTypes를 전역으로 설정하여 일일이 각 stories에서 기입하지 않아도 공통으로 arg를 생성할 수 있다

const preview: Preview = {
  parameters: {
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
  },
  argTypes: {
    color: {
      control: "color",
    },
  },
}

storybook

나는 해당 stories.tsx 파일에 color 를 넣지 않았음에도 이렇게 color라는 control을 추가해줄 수 있다

  • 특정 파일에서 필요 없는 경우에는 제거할 수도 있다

react-docgen-typescript

컴포넌트의 Prop을 하나하나 Control로 작성하는 것은 매우 귀찮을 수 있습니다. 스토리북은 react-docgen-typescript와 react-docgen-typescript-plugin를 사용하여 컴포넌트의 Prop 타입을 Control로 자동 생성해 줄 수 있습니다. (공식 문서)

라는 내용을 봤다.

공식문서에서 설명하는 해당 라이브러리의 기능은

A simple parser for React properties defined in TypeScript instead of propTypes.

Typescript로 정의된 properties를 파싱해주는 기능을 한다고 한다

  • 그런데 이걸 storybook에서 어떻게 사용하라는거지..? 찾아보다가 storybook 공식문서에 나온 내용이 있다

storybook 공식문서

설정 후에 기존의 stories.tsx 파일에서 argTypes 부분을 다 지우고 storybook을 실행하면

결과
storybook

그대로 properties를 파싱해서 argTypes에 적용시켜준다

type Props = {
  /** 예시1 */
  a: string
  /** 예시2 */
  b?: boolean
  /** 예시3 */
  c?: () => void
}

/**
 * 컴포넌트 설명
 *
 * - 어쩌고
 * - 저쩌고
 */
const Ex = ({ a }: Props) => {
  return <div>{a}</div>
}

export default Ex

Ex storybook

이렇게 컴포넌트의 주석 또한 파싱해서 옮겨주기 때문에, argTypes의 description 기능을 사용하지 않아도 된다

기존에는 컴포넌트가 수정되면 storybook도 이에 맞게 수정해줘야 했다면, 이제는 자동으로 업데이트가 되기 때문에 하나의 SSOT를 가지게 된다고 볼 수 있다

단점이라면, 가끔 추론이 이상하게 되는 경우가 있다

  • 가끔 타입스크립트 기본 타입이 아니라 라이브러리에서 자체적으로 정의한 타입이 사용될 경우에 추론이 잘 안되는 경우가 있는 것 같다

현재 버튼에서는 pandacss recipe 생성시 자체적으로 정의된 ButtonVariantProps 를 사용하고 있다

  • 특정 recipe를 생성하면, 자동으로 recipe를 분석해서 variant에 대한 타입을 생성해준다

내부 구현은 좀 복잡하지만, 결과는

{size: 'small' | 'medium' | 'large'
 variant : 'text' | 'primary'
...
}

이런 식인데 파싱된 결과물은

storybook

내부 구현에서 사용된 ConditionalValue 라는 타입이 적용되었다

그래서 또 다른 타입 output인 ButtonVariant를 사용해서

interface ButtonVariant {
  size: "small" | "medium" | "large"
	br: "normal" | "rounded"
	variant: "primary" | "text"
}

이를 Partial로 적용했더니 정상적으로 반영되었다

0개의 댓글