nasheomirro / react-polymorphed

A set of types to help easily create fast polymorphic components.
MIT License
24 stars 3 forks source link

Storybook and args in polymorphic component #9

Closed alekseykurylev closed 9 months ago

alekseykurylev commented 9 months ago

Storybook does not display the argument table if the component is polymorphic. Perhaps someone has faced a similar problem and knows how to solve it. I use the option with supporting forwardRef.

image

nasheomirro commented 9 months ago

I don't know much about Storybook cause I've never used it before, so probably not the best person to answer but I did skim the docs a bit and got a project started and was able to make polymorphic components work.

One thing I noticed is that it doesn't account for changes in components or their types and only react to when stories get changed, I'm not sure if that's a bug or not on their end. Also, it seems that the auto generation with the [autodocs] tag only happens when we first run npm run storybook, I do not know if this is inteded.

I got the above issue when I ran this the first time, it was pretty confusing cause it doesn't seem to react to changes except when I modified the stories and it only partially shows the correct props (probably cause I haven't read the docs at all). But once I restarted the process it was able to generate the documentation correctly. I also noticed this with regular components as well so the problem doesn't seem to be specific to react-polymorphed.

So before I start Storybook, I create the components first and set up their stories, then I run npm run storybook and it now correctly shows the generated documentation. Closing this issue for now cause I don't think it's a problem with the library, Hope this helps!

alekseykurylev commented 9 months ago

I don't know much about Storybook cause I've never used it before, so probably not the best person to answer but I did skim the docs a bit and got a project started and was able to make polymorphic components work.

One thing I noticed is that it doesn't account for changes in components or their types and only react to when stories get changed, I'm not sure if that's a bug or not on their end. Also, it seems that the auto generation with the [autodocs] tag only happens when we first run npm run storybook, I do not know if this is inteded.

I got the above issue when I ran this the first time, it was pretty confusing cause it doesn't seem to react to changes except when I modified the stories and it only partially shows the correct props (probably cause I haven't read the docs at all). But once I restarted the process it was able to generate the documentation correctly. I also noticed this with regular components as well so the problem doesn't seem to be specific to react-polymorphed.

So before I start Storybook, I create the components first and set up their stories, then I run npm run storybook and it now correctly shows the generated documentation. Closing this issue for now cause I don't think it's a problem with the library, Hope this helps!

Have you used PolyRefFunction?

alekseykurylev commented 9 months ago

@nasheomirro

If the component uses React.forwardRef then storybook correctly accepts args from the component

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {...

telegram-cloud-photo-size-2-5384539772908852699-y

If the component uses PolyRefFunction then storybook sees the args of the component as excluded (Omit)

const polyRef = React.forwardRef as PolyRefFunction;
const Button = polyRef<"button", ButtonProps>((props, ref) => {...

telegram-cloud-photo-size-2-5384539772908852700-y

Is it possible to add similar typing as React.forwardRef?

nasheomirro commented 9 months ago

I see.. I think it's because polymorphic components are generic, the any that you see there should've been whatever props the as component has but if it isn't being invoked then the polymorphic component doesn't know what as is yet, so when they try to get the props with typeof Button, the generic T which is used to infer as, is treated as React.ElementType<any> and grabbing the props of that type results in any.

The need for the Omit is because the library removes the props of the as component that has the same keys as the polymorphic component's own props, in this case it is ButtonPropDefs and other props (somehow only the keyof ButtonPropDefs is shown but its still working correctly idk), but the props should still be correct.

But yeah, Storybook expects a non-generic component to be passed it seems, and polymorphic components should be generic. I'm still not sure what you want to achieve here, but if you just want to turn it into a non-generic component then a quick in arguably quirky way to do that is something like:

export type NonGeneric<C extends PolyForwardComponent<any, any>> = C extends PolyForwardComponent<infer T, infer P>
  ? ForwardRefExoticComponent<P & { as?: React.ElementType } & RefAttributes<T>>
  : never;

// and to use it we do:
const meta: Meta<NonGeneric<typeof Button>> = {
  component: Button as NonGeneric<typeof Button>,
  // ...
}