-
Notifications
You must be signed in to change notification settings - Fork 106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create / use react-docgen vite plugin to show docsPage info #299
Conversation
Doh, looks like yarn in windows isn't happy with the git reference. Might have to wait for an alpha after all... I'll try using the current alpha for now. |
Edit: was just missing a |
73aa788
to
85037af
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally LGTM. If we were going to use this long-term I would suggest that this gets its own package with tests. But I think this is temporary until we create an annotations server inside storybook. I tested it out and the results line up with the webpack version, so I think this is good to go.
name: 'react-docgen', | ||
enforce: 'pre', | ||
async transform(src: string, id: string) { | ||
if (/\.(mjs|tsx|jsx)$/.test(id)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about .js?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When using vite, it's required to use .jsx or .tsx for JSX syntax. But, I guess technically it's possible to create a react component using react.createElement()
, so it doesn't hurt to check non-jsx files too. I'll change it.
I'd be happy to help test things out once it's in a testable shape, if you guys point me to the version I would need to switch to (currently at 6.4.20). Thanks. |
All the changed code is appended to the end, so I _think_ this should be fine?
@sebastienbarre if you'd like to try this out, you can |
Thanks @IanVS Great work. This seems to be working the same way now as it was before I switched from the default Storybook builder (webpack) to Vite-builder. Now unfortunately the way it was working before... wasn't doing the trick at all for me. I was hoping for a small miracle here, and I truly appreciate the effort nonetheless. My gut feeling is that react-docgen can't solve my issue at the moment (maybe in 6.0?). To be more specific. The vast majority of my React components look like this, for better or worse (to simplify): const shapes = {
ROUNDED: 'rounded',
CIRCULAR: 'circular',
RECTANGULAR: 'rectangular',
};
const sizes = {
XS: 'xs',
SM: 'sm',
MD: 'md',
};
...
export const Button = ({ shape, size, ...props }) => {
...
// code that compares the shape prop to shapes.ROUNDED for example,
...
// code that compares the size prop to sizes.XS for example
...
};
Button.propTypes = {
shape: PropTypes.oneOf(Object.values(shapes)),
size: PropTypes.oneOf(Object.values(sizes)),
};
Button.defaultProps = {
shape: shapes.ROUNDED,
size: sizes.SM,
}; It seems like the above way to define prop types confuses Thanks a lot |
@sebastienbarre that sounds like a limitation of react-docgen. You might be able to create a custom handler, perhaps based on https://github.com/reactjs/react-docgen/blob/main/src/handlers/propTypeHandler.ts. However, we don't have a way for you to use a custom handler, yet. If you want to experiment, you should be able to edit the
That didn't take long to be proven wrong. 😆 |
I'm not sure I can follow, but this should work already in v5. if you copy the example into the playground (which runs on v6) you can see what happens:
|
Oh cool. @sebastienbarre would you be willing to open an issue (in this repo) and ideally provide a small reproduction that we can test against, to figure out what's going on here? |
Hmm, this still does not seem to be working for me. Given the Button example I provided in a different spot in this repo (i forgot where, but thats irrelevant): import {forwardRef} from 'react';
import PropTypes from 'prop-types';
import {cnb} from 'cnbuilder';
import Loader from '../Loader';
import css from './Button.module.scss';
const Button = forwardRef(
(
{
className,
testAttr,
children,
type,
variant,
size,
block,
icon,
iconPosition,
disabled,
loading,
onClick,
...attrs
},
ref
) => (
<button
ref={ref}
className={cnb(
css.root,
{[css[variant]]: variant},
{[css[size]]: size},
{[css.block]: block},
{[css[`${iconPosition}Icon`]]: Boolean(icon)},
className
)}
data-test={testAttr}
type={type}
disabled={disabled}
onClick={onClick}
{...attrs}
>
{iconPosition === 'left' &&
(loading ? (
<Loader
className={css.leftLoader}
testAttr="loader"
inline
/>
) : (
icon
))}
{children}
{iconPosition === 'right' &&
(loading ? (
<Loader
className={css.rightLoader}
testAttr="loader"
inline
/>
) : (
icon
))}
</button>
)
);
Button.propTypes = {
/** Additional class(es) to add to the component. */
className: PropTypes.string,
/** The name of the test attribute to associate to the component. */
testAttr: PropTypes.string,
/** The markup node to insert into the button. */
children: PropTypes.node.isRequired,
/** The type of button that is rendered. */
type: PropTypes.oneOf(['button', 'submit', 'reset']),
/** The variant of the button. */
variant: PropTypes.oneOf([
'primary-link',
'neutral-link',
'destructive-link',
'primary',
'secondary',
'tertiary',
'neutral',
'tertiary-neutral',
'primary-destructive',
'secondary-destructive',
'tertiary-destructive',
'neutral-destructive',
]),
/** The size of the button. */
size: PropTypes.oneOf(['sm', 'md', 'lg', 'xl', 'xxl']),
/** Whether the button should display as a block level element. */
block: PropTypes.bool,
/** A custom icon (typically one of the Icon components) to show in the button. */
icon: PropTypes.element,
/** If an icon is provided, whether it should appear on the left or right side of the button children. */
iconPosition: PropTypes.oneOf(['left', 'right']),
/** Whether the button is disabled or not. */
disabled: PropTypes.bool,
/** Whether to show a loading animation inside of the button. */
loading: PropTypes.bool,
/**
* The handler to execute when the button is clicked.
*
* @param {SyntheticEvent} evt - The React `SyntheticEvent`.
*/
onClick: PropTypes.func,
};
Button.defaultProps = {
testAttr: 'button',
type: 'button',
variant: 'primary-link',
size: 'lg',
iconPosition: 'left',
};
export default Button; This is the corresponding story: export const Default = Template.bind({});
Default.args = {
children: 'Button Label',
}; Here is the output I'm still seeing: I pasted my Button code into the playground provided above by @danez (great tool by the way, had no idea it existed) and it did produce the proper output but it's not being reflected in Storybook. I verified that I upgraded to the latest version (i even removed my node_modules and package-lock just to make sure as well) but still don't see those props :\ |
@reintroducing thanks for the report. Is there any chance you could create a repo that shows this behavior, so we can dig into it and see what's going on? I tried to reproduce it in the |
Thanks @danez for the lightning fast reply. That is indeed what I'm trying to do in Storybook. @IanVS I'm trying as we speak, but I'm having issues with
getting:
|
|
@IanVS Here you go: As you can see, the Default story only has the children, the Primary story has children and variant, but there are many other props that should be showing up. Let me know if you need anything else. EDIT: Just run |
@IanVS I did run |
@IanVS Is build-vite using react-docgen 6.0.0? Just mentioning that because 6.0.1 was released a few hours ago, and it says:
Are you maybe explicitly including something from That seems to be the case:
These seem to be in
|
I'm actually reverting this as we speak, because there was no real good reason to change the folder name. alpha.2 in a couple of minutes. EDIT: If you try now and ensure you update |
Alright, thanks a lot @danez -- we are back in business. @IanVS I created a repo that show the behavior I described: sebastienbarre-forks/storybook-builder-vite-react-docgen-repro My apologies though, my original example above was a bit too simplified. I started from the example in the
Then I slightly updated the Button story to use an object for the constants (this commit): const sizes = {
SMALL: "small",
MEDIUM: "medium",
LARGE: "large",
};
...
Button.propTypes = {
size: PropTypes.oneOf(Object.values(sizes)),
};
...
Button.defaultProps = {
size: sizes.MEDIUM,
}; As @danez kindly pointed out, this actually is already handled properly by What doesn't quite work is what I should have clarified earlier (my bad) -- our constants are in a separate file. It looks like this (this commit): In export const Size = {
EXTRA_SMALL: "extra_small",
SMALL: "small",
MEDIUM: "medium",
LARGE: "large",
EXTRA_LARGE: "extra_large",
}; and the only change to Button is to use a subset of these sizes: import { Size } from "./Size.js";
const sizes = {
SMALL: Size.SMALL,
MEDIUM: Size.MEDIUM,
LARGE: Size.LARGE,
}; Here is what it looks like now in Storybook (notice the Thank you. |
@reintroducing I've traced your issue to #312. In the meantime, you can set this in your module.exports = {
typescript: {
reactDocgen: 'react-docgen',
}
}; |
@IanVS That actually generates EDIT: I do actually see the dep is already installed, so not sure why i'm seeing that error. |
@reintroducing can you try clearing your |
@sebastienbarre I took a look at your repro, thanks for that! After the same workaround to force
I think this is probably a limitation of react-docgen, but maybe you can open a feature request there, and perhaps even contribute a PR to add support? It seems like a reasonable request to me, but @danez is the judge of course. ;) If it can't make its way into react-docgen itself, maybe it can be done in a custom handler (which as I said, we'd need to add support for here). |
Rookie mistake, I should have known better, the ole delete it and re-install it :) That totally works, thank you. |
Thanks. @danez, do you think the above example is in the realm of what |
Yes totally. I haven't looked at exactly what's going on, but to me this even looks more like a bug than a feature request. The output is not usefull at all. Usually in cases that are not supported the type should be |
Thanks @danez -- this is done in Prop types not being inferred correctly when using imported values · Issue #580 · reactjs/react-docgen |
Fixes #103
Closes #190
Fixes #2
This takes a slightly different approach from #190. Instead of using a babel transform, this creates a vite plugin, similar to the vue-docgen plugin, but based on the babel-plugin-react-docgen. This gives us the chance to rely directly on react-docgen, without needing another package in between, and it avoids being accidentally overwritten if users replace our @vitejs/plugin-react with their own config.
This new vite plugin is not configurable like the babel plugin is, but I'm not certain those configurations are necessary in the first place. If we hear from users that it's something they need, we can find a way to make them customizable, but I prefer to avoid extra options if possible.
I used one of the most recent git commits to react-docgen, since their conversion to typescript happened after their last alpha release, and it was really useful having the types. Hopefully another alpha will be released soon, so the build won't need to happen during install time (a definite drawback, but hopefully fine temporarily. react-docgen is being actively developed after a long break. \o/. Monitor reactjs/react-docgen#502 for updates).Edit: had to fall back to the alpha due to yarnpkg/berry#2578 breaking CI.
This version does not create a global list of all the docs, like the babel plugin does (
DOC_GEN_COLLECTION_NAME
). I looked through the storybook source, and it doesn't seem like anything still relies on it, so I think it's just a legacy detail for now that we can probably avoid supporting.I've updated the react example to demonstrate the use of the plugin, so feel free to check this out there.