Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storybook optional props force undefined

I didn't find any answer that resolve my problem. I'm building a React Storybook with Typescript. With optional props, Storybook addon add an "undefined" option. I put a defaultProps but it doesn't take it. Do you have any solution ?

Component :

type IconType = 'outline' | 'solid'

export interface IconProps {
  name: keyof typeof icons
  size?: number
  type?: IconType
  className?: string
  fallback?:
    | boolean
    | React.ReactChild
    | React.ReactFragment
    | React.ReactPortal
    | null
}

const Icon = ({
  name,
  type = 'solid',
  className = '',
  size = 4,
  fallback = null,
}: IconProps): JSX.Element => {
  if (!name) {
    throw new Error("Can't call Icon component without name props")
  }

  const Icon = React.lazy(
    () => import(`../${type}/${icons[name]}`)
  )

  return (
    <React.Suspense fallback={fallback}>
      <Icon className={className} style={{width: size, height: size}} />
    </React.Suspense>
  )
}

Icon.defaultProps = {
  type: 'solid',
}

export default Icon

Story:

import React from 'react'
import { Story, Meta } from '@storybook/react'
import Icon, { IconProps } from '.'

export default {
  title: 'Components/Icon',
  component: Icon,
} as Meta

const Template: Story<IconProps> = (args) => <Icon {...args} />

export const Basic = Template.bind({})
Basic.args = {
  name: 'plus',
}

It shows me: enter image description here

And when I select undefined it doesn't take the defaultProps of Icon 😭

like image 958
Dorian Maliszewski Avatar asked Oct 28 '25 13:10

Dorian Maliszewski


2 Answers

I had the same problem, for me it works fine like this:

import React from 'react'
import { ComponentStory, ComponentMeta } from '@storybook/react'
import Icon, { IconProps } from '.'

export default {
  title: 'Components/Icon',
  component: Icon,
} as ComponentMeta<typeof Icon>

const Template: ComponentStory<typeof Icon> = (args: IconProps) => <Icon {...args} />

export const Basic = Template.bind({})
export const BasicArgs: IconProps = {
  name: 'plus',
}
Basic.args = BasicArgs

Also when I was trying to export and use the story somewhere else it didn't work because the type was not matching: This I was able to solve it by creating an additional typed object called BasicArgs in between and then assigning it to Basic.args in your case.

Now you can import it somewhere else and use it just like that:

import { Basic, BasicArgs } from './Icon.stories'
    
...  (
       <Basic {...BasicArgs} />
    ) ...
like image 178
Laiacy Avatar answered Oct 31 '25 03:10

Laiacy


When setting storybook text controls, it always returns type string and sometimes I need it to be undefined. One workaround I have found is to handle it in the story and override the args.

if (args.label?.length === 0) {
    args.label = undefined;
}
like image 32
Chris Avatar answered Oct 31 '25 03:10

Chris



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!