import { Meta } from '@storybook/addon-docs'; import { H1 } from '@leafygreen-ui/typography'; import BannerImage from '../.storybook/static/leafygreen-ui-banner.png';
index.tsx
<ComponentName>.styles.ts
<ComponentName>.types.ts
<ComponentName>.tsx
<ComponentName>.spec.tsx**
<ComponentName>.stories.tsx**
any subcomponent directories
**only if the stories or tests pertain specifically to the component in this directory; meaning it may not be necessary for many internal subcomponents
The folder structure should be identical for all components - whether they are considered components that are exported to npm, or subcomponents contained within those packages. In other words, all subcomponents are simply components, and they should be structured identically to reflect that.
Even if a package only has one component, it should have a subdirectory. For example, the path to the component file for Badge
would be /badge/src/Badge/Badge.tsx
. While this could be seen as clutter, it allows us to differentiate code that is relevant to the entire package from code that only pertains to the component. It is also more scalable as adding subcomponents in the future would simply involve adding a new directory, instead of having to move all files in the package.
When considering whether to break some logic / style into a subcomponent, consider -
- Does it involve logic in its style or function that is independent of what the current layer of componentization should concern?
If done correctly, every layer of componentization should only need two large categories of styles - a base set of styles, and a different set of styles for every style-determining variant prop of this component (e.g. Variant
, Size
, etc).
Subcomponentizing correctly should mean that all rendered React components or elements are contained inside the final return ( <>{...}</> )
.
There should not be a need for direct function calls inside the render function as any logic specific to a block of rendering should be broken out into a separate component. In other words, prefer return ( <><Subcomponent />{...more JSX></>)
to return ( <>{renderSubcomponent()}<...more JSX></> )
.
Having an index.tsx
file for single component directories can be considered clutter. However, this would mean our import statements for this subcomponent would have to be @leafygreen-ui/<package-name>/<SubcomponentName>/<SubcomponentName>
. Our alternative would be to place our component logic in an index.tsx
file, but that would break our pattern of standardizing across all component directories.
This approach would also be more future-proof in case we decide to allow developers to import our subcomponents directly; all exports from the subcomponents would already be controlled through the index.tsx
file in each directory.
*.stories.tsx
is the standard preferred by Storybook. While DS has used *.story.tsx
in the past, we should standardize to match the latest pattern moving forward.