channel-io / bezier-react

React components library that implements Bezier design system.
https://main--62bead1508281287d3c94d25.chromatic.com
Apache License 2.0
231 stars 47 forks source link

Fix runtime error in Slider storybook #2488

Closed nayounsang closed 2 weeks ago

nayounsang commented 3 weeks ago

Self Checklist

Related Issue

close #2312

Summary

Details

First commit - I don't like it, but using a `Template` was the solution I thought of. - The control that inputs the `array` in storybook requires `object` input. - Maybe, I can create a custom control using a `decorator`. I'm not sure because I haven't tried it yet. We also need to discuss how to use this to receive input. ```typescript const Template: StoryFn = (args) => { const processedArgs = getProcessedArgs(args) return } export const Primary = Template.bind({}) Primary.args = { width: 285, defaultValue: [5], value: undefined, disabled: false, guide: [5], min: 0, max: 10, step: 1, disableTooltip: false, } ``` - Set existing args and manipulate necessary props in the template. - I'd like to be able to manipulate specific props into the desired format in `argTypes`, but I don't know how. I couldn't find this in the docs. ```typescript const getProcessedArgs = (args: SliderProps): SliderProps => { return { ...args, value: getProcessedValue(args.value) } } const getProcessedValue = ( value: undefined | Record | number[] ) => { if (value === undefined) { return undefined } if (Array.isArray(value) && value.every((item) => typeof item === 'number')) { return value } if (typeof value === 'object' && value !== null) { return Object.values(value) } return value } ``` - The function was separated into two to prepare for props that require additional processing in the future. - If JSON is `number[]` or `undefined`, this func returns original value. - If JSON is `object`, this func returns value of object. - In other cases, it returns as is and not reflect in the storybook. - There will be stricter guards and various cases, but I think this will need to be discussed because the code structure will be dirty (and I think it still is to some extent ๐Ÿคฃ). - For example, there is logic that verifies whether an object's key is a consecutive number starting from 0.

Breaking change? (Yes/No)

No

References

changeset-bot[bot] commented 3 weeks ago

โš ๏ธ No Changeset found

Latest commit: d2d545a4a4923dfdcebe9363e5ca1a774dd87de1

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

channeltalk[bot] commented 3 weeks ago

https://desk.channel.io/#/channels/1/team_chats/groups/1237/672c86cfe898413a6268

codecov[bot] commented 3 weeks ago

Codecov Report

All modified and coverable lines are covered by tests :white_check_mark:

Project coverage is 82.27%. Comparing base (63fbd3c) to head (d2d545a). Report is 1 commits behind head on main.

Additional details and impacted files ```diff @@ Coverage Diff @@ ## main #2488 +/- ## ======================================= Coverage 82.27% 82.27% ======================================= Files 143 143 Lines 2979 2979 Branches 917 913 -4 ======================================= Hits 2451 2451 Misses 497 497 Partials 31 31 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

github-actions[bot] commented 3 weeks ago

Chromatic Report

๐Ÿš€ Congratulations! Your build was successful!

yangwooseong commented 3 weeks ago
  1. ์•„๋งˆ value ์— undefined๊ฐ€ ์ดˆ๊ธฐ๊ฐ’์œผ๋กœ ๋˜์„œ object ํƒ€์ž…์œผ๋กœ ์žกํžˆ๋Š” ๊ฒŒ ์—๋Ÿฌ๊ฐ€ ๋œจ๋Š” ์›์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
image

์•„์˜ˆ controlled์™€ uncontrolled ์Šคํ† ๋ฆฌ๋ฅผ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์€ ์–ด๋–จ๊นŒ์š”? Switch ์˜ ์˜ˆ์‹œ๋ฅผ ์ฐธ๊ณ ํ•˜์‹œ๋ฉด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

controlled -> value์˜ ์ดˆ๊ธฐ๊ฐ’์„ ์ฃผ๊ณ  defaultValue ์„ args๋กœ ์ œ๊ณตํ•˜์ง€ ์•Š๊ณ  uncontrolled -> defaultValue์˜ ์ดˆ๊ธฐ๊ฐ’์„ ์ฃผ๊ณ  value ๋ฅผ args ๋กœ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š”๋‹ค

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด value๋ฅผ sanitize ํ•  ํ•„์š”๋„ ์—†์–ด์งˆ ๊ฒƒ ๊ฐ™์•„์š”!

  1. ์–ด๋–ค ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์…จ๋Š”์ง€ ๋“ค์–ด๋‚˜๋„๋ก PR ์ œ๋ชฉ์„ ๋ฐ”๊ฟ”์ฃผ์„ธ์š”. Fix runtime error in Slider storybook ์ •๋„๋ฉด ์–ด๋–จ๊นŒ์š”?
nayounsang commented 3 weeks ago

@yangwooseong

  1. ๋งค์šฐ ์ข‹์€ ์˜ˆ์‹œ๋„ค์š”! ๋‘๊ฐœ์˜ ์Šคํ† ๋ฆฌ๋กœ ๋ถ„ํ• ํ–ˆ์–ด์š”.
  2. ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๊ณ ๋ฏผ์ด ์žˆ์–ด์š”. ๊ณตํ†ต๋˜๋Š” props๋“ค์˜ ๊ฐ’์„ meta์—์„œ ์ •์˜ํ–ˆ์–ด์š”.

const meta: Meta<typeof Slider> = {
  component: Slider,
  argTypes: {
    minStepsBetweenThumbs: {
      control: {
        type: 'number',
      },
    },
    onValueChange: {
      action: 'onValueChange',
    },
    onValueCommit: {
      action: 'onValueCommit',
    },
  },
  args:{
    width: 285,
    disabled: false,
    guide: [5],
    min: 0,
    max: 10,
    step: 1,
    disableTooltip: false,
  }
}

๊ทธ ๋’ค ์Šคํ† ๋ฆฌ๋งˆ๋‹ค ๋ณ€ํ™”ํ•˜๋Š” control์ด ์žˆ์œผ๋ฉด

export const Uncontrolled = Template.bind({})
Uncontrolled.args = {
  defaultValue: [5],
}

์ถ”๊ฐ€์ ์œผ๋กœ arg๋ฅผ ์„ค์ •ํ•ด์ฃผ๋Š” ๋ฐฉ์‹์ด์—์š”. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๊ฒฝ์šฐ meta์—์„œ ์„ ์–ธํ•œ arg๊ฐ€ ์ œ์ผ ๋จผ์ €์˜ค๊ณ  ์Šคํ† ๋ฆฌ๋งˆ๋‹ค ์„ค์ •ํ•œ arg์ธ value ๋˜๋Š” defaultValue๋“ค์ด ํ›„์ˆœ์œ„๋กœ ์™€์„œ ์ œ ๋””๋ฐ”์ด์Šค์—์„  value์™€ defaultValue์˜ ๊ฒฝ์šฐ ์Šคํฌ๋กค์„ ๋‚ด๋ ค์•ผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•๋„ ๊ดœ์ฐฎ์€์ง€, ์•„๋‹ˆ๋ฉด const baseArgs:Partial<SliderProps> = {} ๋ž€ ๋ณ„๋„์˜ ๊ฐ์ฒด์— ๋‘ ์Šคํ† ๋ฆฌ ๋ชจ๋‘ ๊ณตํ†ต๋˜๋Š” props๋ฅผ ์„ค์ •ํ•˜๊ณ  ๋ณต์‚ฌํ• ์ง€, ์•„๋‹ˆ๋ฉด ๊ฐ ์Šคํ† ๋ฆฌ๋งˆ๋‹ค ํ•„์š”ํ•œ ๋ชจ๋“  arg๋“ค์„ ์„ค์ •ํ•˜๋Š”๊ฒŒ ์ข‹์„์ง€ ๊ณ ๋ฏผ์ด๋„ค์š”.

์ฐธ๊ณ ์‚ฌ์ง„(์Šคํฌ๋กค์„ ๋‚ด๋ ค์•ผ value๋ฅผ ์„ค์ • ๊ฐ€๋Šฅํ•œ ๋ชจ์Šต) image image

yangwooseong commented 3 weeks ago

ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๊ฒฝ์šฐ meta์—์„œ ์„ ์–ธํ•œ arg๊ฐ€ ์ œ์ผ ๋จผ์ €์˜ค๊ณ  ์Šคํ† ๋ฆฌ๋งˆ๋‹ค ์„ค์ •ํ•œ arg์ธ value ๋˜๋Š” defaultValue๋“ค์ด ํ›„์ˆœ์œ„๋กœ ์™€์„œ ์ œ ๋””๋ฐ”์ด์Šค์—์„  value์™€ defaultValue์˜ ๊ฒฝ์šฐ ์Šคํฌ๋กค์„ ๋‚ด๋ ค์•ผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

  1. ์Šคํฌ๋กค์ด ์ƒ๊ธฐ๋Š” ๊ฒƒ์€ ์ƒ๊ด€ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ด์š”. ๋‹ค๋งŒ Story ์ž‘์„ฑํ•  ๋–„ ํฌ๋งท์„ ๋‹ค๋ฅธ ๊ณณ๊ณผ ๋งž์ถฐ์ฃผ์‹œ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค. CSF3 ๊ณผ CSF2์˜ ์ฐจ์ด๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”. (#)
export const Primary = {
  args: {
    value: [5],
  },
} satisfies StoryObj<typeof meta>

export const Uncontrolled = {
  args: {
    defaultValue: [3, 7],
  },
} satisfies StoryObj<typeof meta>
  1. controlled ์ผ ๋•Œ๋Š” defaultValue ๋ฅผ ์ˆจ๊ธฐ๊ณ , uncontrolled ์ผ ๋•Œ๋Š” value ๋ฅผ ์ˆจ๊ธฐ๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค(#). ๋ณดํ†ต์€ ์•ˆ์ˆจ๊ฒจ๋„ ๋ฌด๋ฐฉํ•˜๊ฒ ์ง€๋งŒ ์—๋Ÿฌ๊ฐ€ ๋‚˜์„œ ์ˆจ๊ธฐ๋Š” ๊ฒŒ ๊น”๋”ํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

const meta: Meta<typeof Slider> = {
  component: Slider,
  argTypes: {
    ... // ์ƒ๋žต 
    value: {
      if: {
        exists: true,
        arg: 'value',
      },
    },
    defaultValue: {
      if: {
        exists: true,
        arg: 'defaultValue',
      },
    },
  },
}
  1. ์ปดํฌ๋„ŒํŠธ ๋ฒ„๊ทธ์ฒ˜๋Ÿผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์™ธ๋ถ€๋กœ ๋…ธ์ถœ๋˜๋Š” ๋ฒ„๊ทธ๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— changelog ์— ํฌํ•จ๋˜์ง€ ์•Š์•„๋„ ๋ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ changeset ์€ ์ง€์›Œ์ฃผ์…”๋„ ๋ฉ๋‹ˆ๋‹ค!
nayounsang commented 3 weeks ago

@yangwooseong ํ”ผ๋“œ๋ฐฑ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. 2๋ฒˆ๊ฐ™์€ ๊ฒฝ์šฐ์—” ์งˆ๋ฌธ์ด ์žˆ์–ด์š”. ํ˜„์žฌ meta์— ์„ ์–ธํ•œ ๊ณตํ†ต๋˜๋Š” arg์™€ argType์—” value์™€ defaultValue๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๊ณ  value์™€ defaultValue๋Š” Primary์™€ Uncontrolled ๊ฐ๊ฐ์˜ ์Šคํ† ๋ฆฌ์—์„œ ์ •์˜ํ•˜๊ณ  ์žˆ์–ด์š”. ์„ ์–ธ์„ ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์Šคํ† ๋ฆฌ๋ถ์ด ์ˆจ๊ธฐ๋Š” ๊ฑธ๋กœ ์•Œ๊ณ  ์žˆ์–ด์„œ์š”. ์˜ˆ๋ฅผ๋“ค์–ด Uncontorlled๋Š” arg์™€ argType์— value๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์Šคํ† ๋ฆฌ๋ถ์ด ์ˆจ๊ธฐ๊ณ  ์ œ ๋””๋ฐ”์ด์Šค์—์„œ๋„ ํ˜„์žฌ ๊ทธ๋ ‡๊ฒŒ ๋ณด์—ฌ์š”. ์ œ๊ฐ€ ์•Œ๊ธฐ๋กœ if๋Š”

    parent: { control: 'select', options: ['one', 'two', 'three'] },

    // ๐Ÿ‘‡ Only shown when `parent` arg exists
    parentExists: { if: { arg: 'parent', exists: true } },

์ด ์˜ˆ์™€ ๊ฐ™์ด ์–ด๋–ค arg์— ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ arg๋ฅผ ์กฐ๊ฑด๋ถ€๋กœ ๋žœ๋”๋งํ•˜๋Š” ๊ฑธ๋กœ ์•Œ๊ณ  ์žˆ์–ด์„œ ์งˆ๋ฌธ๋“œ๋ฆฝ๋‹ˆ๋‹ค

yangwooseong commented 3 weeks ago

@yangwooseong ํ”ผ๋“œ๋ฐฑ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

2๋ฒˆ๊ฐ™์€ ๊ฒฝ์šฐ์—” ์งˆ๋ฌธ์ด ์žˆ์–ด์š”. ํ˜„์žฌ meta์— ์„ ์–ธํ•œ ๊ณตํ†ต๋˜๋Š” arg์™€ argType์—” value์™€ defaultValue๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๊ณ 

value์™€ defaultValue๋Š” Primary์™€ Uncontrolled ๊ฐ๊ฐ์˜ ์Šคํ† ๋ฆฌ์—์„œ ์ •์˜ํ•˜๊ณ  ์žˆ์–ด์š”.

์„ ์–ธ์„ ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์Šคํ† ๋ฆฌ๋ถ์ด ์ˆจ๊ธฐ๋Š” ๊ฑธ๋กœ ์•Œ๊ณ  ์žˆ์–ด์„œ์š”. ์˜ˆ๋ฅผ๋“ค์–ด Uncontorlled๋Š” arg์™€ argType์— value๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์Šคํ† ๋ฆฌ๋ถ์ด ์ˆจ๊ธฐ๊ณ  ์ œ ๋””๋ฐ”์ด์Šค์—์„œ๋„ ํ˜„์žฌ ๊ทธ๋ ‡๊ฒŒ ๋ณด์—ฌ์š”.

์ œ๊ฐ€ ์•Œ๊ธฐ๋กœ if๋Š”


    parent: { control: 'select', options: ['one', 'two', 'three'] },

    // ๐Ÿ‘‡ Only shown when `parent` arg exists

    parentExists: { if: { arg: 'parent', exists: true } },

์ด ์˜ˆ์™€ ๊ฐ™์ด ์–ด๋–ค arg์— ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ arg๋ฅผ ์กฐ๊ฑด๋ถ€๋กœ ๋žœ๋”๋งํ•˜๋Š” ๊ฑธ๋กœ ์•Œ๊ณ  ์žˆ์–ด์„œ ์งˆ๋ฌธ๋“œ๋ฆฝ๋‹ˆ๋‹ค

์ €๋„ ๊ฐœ๋ฐœ๋ชจ๋“œ์—์„œ๋Š” ์ˆจ๊ฒจ์ง€๋Š”๋ฐ ๋ฐฐํฌ๋œ ๊ฒƒ์„ ๋ณด๋ฉด ์•ˆ์ˆจ๊ฒจ์ง€๊ณ  ๊ทธ๋Œ€๋กœ ์žˆ์–ด์„œ์š”. ์œ„์— ๋Œ“๊ธ€์— ์žˆ๋Š” ์Šคํ† ๋ฆฌ๋ถ ํ”„๋ฆฌ๋ทฐ๋ฅผ ๋ณด์‹œ๋ฉด ํ™•์ธ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค https://github.com/channel-io/bezier-react/pull/2488#issuecomment-2461723767

๋กœ์ปฌ์—์„œ ๋ฐฐํฌํ•ด์„œ ํ…Œ์ŠคํŠธ ํ•˜๋ ค๋ฉด yarn workspace @channel.io/bezier-react storybook-build ๋ช…๋ น์„ ํ™œ์šฉํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค

nayounsang commented 3 weeks ago

@yangwooseong ํ”ผ๋“œ๋ฐฑ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. 2๋ฒˆ๊ฐ™์€ ๊ฒฝ์šฐ์—” ์งˆ๋ฌธ์ด ์žˆ์–ด์š”. ํ˜„์žฌ meta์— ์„ ์–ธํ•œ ๊ณตํ†ต๋˜๋Š” arg์™€ argType์—” value์™€ defaultValue๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๊ณ  value์™€ defaultValue๋Š” Primary์™€ Uncontrolled ๊ฐ๊ฐ์˜ ์Šคํ† ๋ฆฌ์—์„œ ์ •์˜ํ•˜๊ณ  ์žˆ์–ด์š”. ์„ ์–ธ์„ ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์Šคํ† ๋ฆฌ๋ถ์ด ์ˆจ๊ธฐ๋Š” ๊ฑธ๋กœ ์•Œ๊ณ  ์žˆ์–ด์„œ์š”. ์˜ˆ๋ฅผ๋“ค์–ด Uncontorlled๋Š” arg์™€ argType์— value๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์Šคํ† ๋ฆฌ๋ถ์ด ์ˆจ๊ธฐ๊ณ  ์ œ ๋””๋ฐ”์ด์Šค์—์„œ๋„ ํ˜„์žฌ ๊ทธ๋ ‡๊ฒŒ ๋ณด์—ฌ์š”. ์ œ๊ฐ€ ์•Œ๊ธฐ๋กœ if๋Š”


    parent: { control: 'select', options: ['one', 'two', 'three'] },

    // ๐Ÿ‘‡ Only shown when `parent` arg exists

    parentExists: { if: { arg: 'parent', exists: true } },

์ด ์˜ˆ์™€ ๊ฐ™์ด ์–ด๋–ค arg์— ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ arg๋ฅผ ์กฐ๊ฑด๋ถ€๋กœ ๋žœ๋”๋งํ•˜๋Š” ๊ฑธ๋กœ ์•Œ๊ณ  ์žˆ์–ด์„œ ์งˆ๋ฌธ๋“œ๋ฆฝ๋‹ˆ๋‹ค

์ €๋„ ๊ฐœ๋ฐœ๋ชจ๋“œ์—์„œ๋Š” ์ˆจ๊ฒจ์ง€๋Š”๋ฐ ๋ฐฐํฌ๋œ ๊ฒƒ์„ ๋ณด๋ฉด ์•ˆ์ˆจ๊ฒจ์ง€๊ณ  ๊ทธ๋Œ€๋กœ ์žˆ์–ด์„œ์š”. ์œ„์— ๋Œ“๊ธ€์— ์žˆ๋Š” ์Šคํ† ๋ฆฌ๋ถ ํ”„๋ฆฌ๋ทฐ๋ฅผ ๋ณด์‹œ๋ฉด ํ™•์ธ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค #2488 (comment)

๋กœ์ปฌ์—์„œ ๋ฐฐํฌํ•ด์„œ ํ…Œ์ŠคํŠธ ํ•˜๋ ค๋ฉด yarn workspace @channel.io/bezier-react storybook-build ๋ช…๋ น์„ ํ™œ์šฉํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค

์•„! ๋ฐฐํฌํ™˜๊ฒฝ์„ ์ƒ๊ฐ ๋ชปํ–ˆ๋„ค์š”๐Ÿ˜… fixํ•œ ์ปค๋ฐ‹ ๋กœ์ปฌ์—์„œ ํ…Œ์ŠคํŠธํ–ˆ๊ณ  ์ž˜ ์ˆจ๊ฒจ์ง‘๋‹ˆ๋‹ค! ์ง€๊ธˆ ๊ธฐ์–ต๋‚œ๊ฑด๋ฐ control: false ๋กœ ํŠน์ • arg์— ๋Œ€ํ•œ ์ปจํŠธ๋กค์„ ์ˆจ๊ฒผ๋˜ ๊ฒƒ ๊ฐ™์€๋ฐ ์ €๋Ÿฐ ๋ฐฉ๋ฒ•์ด ์žˆ์—ˆ๊ตฐ์š” ๋ฐฐ์›Œ๊ฐ‘๋‹ˆ๋‹ค๐Ÿ‘