Storybook optional props force undefined

Viewed 2308

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

1 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} />
    ) ...
Related