-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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
WIP: CSF factories #30197
base: next
Are you sure you want to change the base?
WIP: CSF factories #30197
Conversation
…ries' into kasper/csf-factories
…ries' into kasper/csf-factories
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.
20 file(s) reviewed, 19 comment(s)
Edit PR Review Bot Settings | Greptile
const [previewFileUrl, ...previewAnnotationURLs] = [...previewAnnotations, previewOrConfigFile] | ||
.filter(Boolean) | ||
.map((path) => processPreviewAnnotation(path, projectRoot)); |
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.
logic: Destructuring could fail if previewAnnotations and previewOrConfigFile are both empty arrays after filtering. Add a check to handle this case.
const preview = await import('${previewFileUrl}'); | ||
const csfFactoryPreview = Object.values(preview).find(module => { | ||
return 'isCSFFactoryPreview' in module | ||
}); |
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.
logic: Object.values() and find() could return undefined. Need type checking and error handling for when no CSF factory preview is found.
const configs = await Promise.all([${previewAnnotationURLs | ||
.map( | ||
(previewAnnotation, index) => | ||
// Prefer the updated module from an HMR update, otherwise import the original module | ||
`hmrPreviewAnnotationModules[${index}] ?? import('${previewAnnotation}')` | ||
) | ||
.join(',\n')}]) | ||
return composeConfigs(configs); | ||
return composeConfigs([...configs, preview]); |
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.
logic: preview is used in composeConfigs even when csfFactoryPreview is found, which could cause conflicts. Should only include preview in non-factory case.
@@ -27,11 +27,12 @@ export const testStory = ( | |||
return async (context: TestContext & TaskContext & { story: ComposedStoryFn }) => { | |||
const composedStory = composeStory( | |||
story, | |||
meta, | |||
'isCSFFactory' in story ? (meta as any).annotations : meta, |
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.
style: Type casting to 'any' should be avoided. Consider creating proper type definitions for CSF factories to maintain type safety.
{ initialGlobals: (await getInitialGlobals?.()) ?? {} }, | ||
undefined, | ||
exportName | ||
); | ||
|
||
if (composedStory === undefined || skipTags?.some((tag) => composedStory.tags.includes(tag))) { |
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.
logic: Optional chaining on skipTags is unnecessary since it's a required parameter
const div = document.createElement('div'); | ||
document.body.appendChild(div); | ||
|
||
await CSF3InputFieldFilled.run({ canvasElement: div }); | ||
|
||
const input = screen.getByTestId('input') as HTMLInputElement; | ||
expect(input.value).toEqual('Hello world!'); | ||
|
||
document.body.removeChild(div); |
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.
style: Test cleanup could fail if test errors before removeChild. Consider using try/finally
import { Button } from './Button'; | ||
|
||
// eslint-disable-next-line storybook/default-exports | ||
const config = defineConfig({ args: { children: 'TODO: THIS IS NOT WORKING YET' } }); |
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.
logic: TODO comment indicates unfinished/broken functionality. This should be resolved before merging.
}); | ||
|
||
export const CSF2StoryWithParamsAndDecorator = meta.story({ | ||
render: (args: any) => { |
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.
style: Using any
type here loses type safety. Consider using proper Button component prop types.
code/renderers/react/src/preview.tsx
Outdated
readonly meta = <TComponent extends ComponentType<any>, TMetaArgs extends Args>( | ||
meta: ComponentAnnotations<TRenderer, any> & { component: TComponent; args: TMetaArgs } | ||
) => { |
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.
logic: The meta method accepts any for TRenderer annotations but then casts to TMetaArgs. This could lead to type safety issues. Consider constraining the any type.
code/renderers/react/src/preview.tsx
Outdated
public meta: Meta<TRenderer, TArgs>, | ||
public config: PreviewConfig<TRenderer> | ||
) { | ||
Object.assign(this, annotations); |
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.
style: Using Object.assign to copy all properties from annotations could lead to property collisions with the class's own methods/properties. Consider explicit property copying instead.
View your CI Pipeline Execution ↗ for commit 30511e9.
☁️ Nx Cloud last updated this comment at |
Package BenchmarksCommit: The following packages have significant changes to their size or dependencies:
|
Before | After | Difference | |
---|---|---|---|
Dependency count | 36 | 36 | 0 |
Self size | 17 KB | 20 KB | 🚨 +3 KB 🚨 |
Dependency size | 13.83 MB | 13.84 MB | 🚨 +119 B 🚨 |
Bundle Size Analyzer | Link | Link |
@storybook/core
Before | After | Difference | |
---|---|---|---|
Dependency count | 53 | 53 | 0 |
Self size | 19.08 MB | 21.46 MB | 🚨 +2.38 MB 🚨 |
Dependency size | 14.43 MB | 14.43 MB | 0 B |
Bundle Size Analyzer | Link | Link |
@storybook/experimental-nextjs-vite
Before | After | Difference | |
---|---|---|---|
Dependency count | 153 | 152 | 🎉 -1 🎉 |
Self size | 232 KB | 231 KB | 🎉 -622 B 🎉 |
Dependency size | 44.70 MB | 28.88 MB | 🎉 -15.82 MB 🎉 |
Bundle Size Analyzer | Link | Link |
@storybook/nextjs
Before | After | Difference | |
---|---|---|---|
Dependency count | 592 | 592 | 0 |
Self size | 472 KB | 472 KB | 🎉 -622 B 🎉 |
Dependency size | 83.35 MB | 83.78 MB | 🚨 +422 KB 🚨 |
Bundle Size Analyzer | Link | Link |
@storybook/react-native-web-vite
Before | After | Difference | |
---|---|---|---|
Dependency count | 114 | 105 | 🎉 -9 🎉 |
Self size | 43 KB | 42 KB | 🎉 -1 KB 🎉 |
Dependency size | 18.22 MB | 18.46 MB | 🚨 +238 KB 🚨 |
Bundle Size Analyzer | Link | Link |
@storybook/react-vite
Before | After | Difference | |
---|---|---|---|
Dependency count | 87 | 87 | 0 |
Self size | 13 KB | 13 KB | 0 B |
Dependency size | 16.03 MB | 16.45 MB | 🚨 +423 KB 🚨 |
Bundle Size Analyzer | Link | Link |
@storybook/react-webpack5
Before | After | Difference | |
---|---|---|---|
Dependency count | 323 | 323 | 0 |
Self size | 6 KB | 6 KB | 🎉 -27 B 🎉 |
Dependency size | 42.41 MB | 42.83 MB | 🚨 +422 KB 🚨 |
Bundle Size Analyzer | Link | Link |
storybook
Before | After | Difference | |
---|---|---|---|
Dependency count | 54 | 54 | 0 |
Self size | 22 KB | 22 KB | 0 B |
Dependency size | 33.51 MB | 35.89 MB | 🚨 +2.38 MB 🚨 |
Bundle Size Analyzer | Link | Link |
sb
Before | After | Difference | |
---|---|---|---|
Dependency count | 55 | 55 | 0 |
Self size | 1 KB | 1 KB | 0 B |
Dependency size | 33.53 MB | 35.91 MB | 🚨 +2.38 MB 🚨 |
Bundle Size Analyzer | Link | Link |
@storybook/cli
Before | After | Difference | |
---|---|---|---|
Dependency count | 396 | 396 | 0 |
Self size | 496 KB | 496 KB | 🎉 -165 B 🎉 |
Dependency size | 75.43 MB | 77.81 MB | 🚨 +2.38 MB 🚨 |
Bundle Size Analyzer | Link | Link |
@storybook/codemod
Before | After | Difference | |
---|---|---|---|
Dependency count | 276 | 276 | 0 |
Self size | 612 KB | 612 KB | 0 B |
Dependency size | 65.32 MB | 67.70 MB | 🚨 +2.38 MB 🚨 |
Bundle Size Analyzer | Link | Link |
@storybook/core-webpack
Before | After | Difference | |
---|---|---|---|
Dependency count | 1 | 3 | 🚨 +2 🚨 |
Self size | 16 KB | 16 KB | 0 B |
Dependency size | 28 KB | 2.40 MB | 🚨 +2.37 MB 🚨 |
Bundle Size Analyzer | Link | Link |
create-storybook
Before | After | Difference | |
---|---|---|---|
Dependency count | 112 | 112 | 0 |
Self size | 1.11 MB | 1.11 MB | 0 B |
Dependency size | 42.64 MB | 45.03 MB | 🚨 +2.38 MB 🚨 |
Bundle Size Analyzer | Link | Link |
@storybook/preset-preact-webpack
Before | After | Difference | |
---|---|---|---|
Dependency count | 2 | 4 | 🚨 +2 🚨 |
Self size | 5 KB | 5 KB | 0 B |
Dependency size | 44 KB | 2.41 MB | 🚨 +2.37 MB 🚨 |
Bundle Size Analyzer | Link | Link |
@storybook/preset-react-webpack
Before | After | Difference | |
---|---|---|---|
Dependency count | 191 | 191 | 0 |
Self size | 24 KB | 24 KB | 0 B |
Dependency size | 33.49 MB | 33.91 MB | 🚨 +422 KB 🚨 |
Bundle Size Analyzer | Link | Link |
@storybook/preset-server-webpack
Before | After | Difference | |
---|---|---|---|
Dependency count | 18 | 20 | 🚨 +2 🚨 |
Self size | 10 KB | 10 KB | 0 B |
Dependency size | 1.48 MB | 3.85 MB | 🚨 +2.37 MB 🚨 |
Bundle Size Analyzer | Link | Link |
@storybook/preset-svelte-webpack
Before | After | Difference | |
---|---|---|---|
Dependency count | 101 | 103 | 🚨 +2 🚨 |
Self size | 14 KB | 14 KB | 0 B |
Dependency size | 10.40 MB | 12.77 MB | 🚨 +2.37 MB 🚨 |
Bundle Size Analyzer | Link | Link |
@storybook/react
Before | After | Difference | |
---|---|---|---|
Dependency count | 6 | 6 | 0 |
Self size | 932 KB | 1.35 MB | 🚨 +422 KB 🚨 |
Dependency size | 24 KB | 24 KB | 0 B |
Bundle Size Analyzer | Link | Link |
Build: Fix sandbox annotations for CSF4 example
This reverts commit 5d05b3c.
Closes #
What I did
Checklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Manual testing
This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!
Documentation
MIGRATION.MD
Checklist for Maintainers
When this PR is ready for testing, make sure to add
ci:normal
,ci:merged
orci:daily
GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found incode/lib/cli-storybook/src/sandbox-templates.ts
Make sure this PR contains one of the labels below:
Available labels
bug
: Internal changes that fixes incorrect behavior.maintenance
: User-facing maintenance tasks.dependencies
: Upgrading (sometimes downgrading) dependencies.build
: Internal-facing build tooling & test updates. Will not show up in release changelog.cleanup
: Minor cleanup style change. Will not show up in release changelog.documentation
: Documentation only changes. Will not show up in release changelog.feature request
: Introducing a new feature.BREAKING CHANGE
: Changes that break compatibility in some way with current major version.other
: Changes that don't fit in the above categories.🦋 Canary release
This pull request has been released as version
0.0.0-pr-30197-sha-3753cde1
. Try it out in a new sandbox by runningnpx [email protected] sandbox
or in an existing project withnpx [email protected] upgrade
.More information
0.0.0-pr-30197-sha-3753cde1
kasper/csf-factories
3753cde1
1736194364
)To request a new release of this pull request, mention the
@storybookjs/core
team.core team members can create a new canary release here or locally with
gh workflow run --repo storybookjs/storybook canary-release-pr.yml --field pr=30197
Greptile Summary
Based on the provided files and changes, here's a concise summary of the CSF factories pull request:
Introduces CSF (Component Story Format) factories to provide a more structured and type-safe way to define Storybook configurations and stories.
defineConfig
andmeta.story()
pattern for type-safe story definitions in/code/renderers/react/src/preview.tsx
processCSFFile
to detect and handle CSF4 factory format viaisCSFFactoryPreview
flagThe changes provide better type safety and structure while maintaining backward compatibility with existing CSF formats. The implementation appears solid but requires careful testing around project annotation overrides and factory pattern adoption.