Skip to content

feat: CSF Factories (CSF Next) support - #919

Open
kasperpeulen wants to merge 28 commits into
nextfrom
kasper/csf-factories
Open

feat: CSF Factories (CSF Next) support#919
kasperpeulen wants to merge 28 commits into
nextfrom
kasper/csf-factories

Conversation

@kasperpeulen

Copy link
Copy Markdown
Member

Issue: supersedes #826 (same branch content, brought up to date with next)

What I did

Fresh PR of @dannyhw's CSF Factories (CSF Next) work from #826, which had drifted ~6 months behind next (74 commits) and accumulated merge conflicts. All 24 of Danny's original commits are preserved; on top of them sit one merge commit resolving the conflicts against current next and one follow-up chore commit.

Danny's work (see #826 for the full description):

  • RN-specific definePreview() wrapping storybook/internal/csf, injecting the RN entry-preview annotations and render function, with compat shims so prepareStories can read meta.title/includeStories/excludeStories and stories expose a lazy Component and a play that stays undefined when unset
  • Typed defineMain() exported from @storybook/react-native/node
  • .factories.stories.tsx variants of all example stories plus portable-story tests, and a .rnstorybook-nofactories/ config so both CSF styles run side by side

Merge resolution highlights:

  • Start.tsx / preview.ts: took next's refactored versions (extracted getReactNativeProjectAnnotations, StoryEntry type, web workarounds); the factories logic lives in definePreview.tsx / entry-preview.ts
  • index.ts: kept the types/config.ts split and definePreview exports, with StorybookConfig updated to next's newer shape (deviceAddons, deprecated addons) — this drops the addons: Preset[] refinement from feat: CSF Factories (CSF Next) support #826 in favor of next's deliberate Addon union + deviceAddons split
  • prepareStories.ts: next's TS6-friendly typing plus the factories-aware story-name resolution and typeof story.play === 'function' detection
  • .rnstorybook-nofactories/main.ts: migrated from the deprecated addons field to deviceAddons and regenerated its stale storybook.requires.ts

How to test

pnpm install
pnpm build
pnpm check:types   # passes
pnpm lint          # passes
pnpm format:check  # passes
pnpm test          # passes (one pre-existing flake: Actions.test.tsx times out under parallel load, passes in isolation)

Verified against the expo example running via expo start (web target), with the factories config as the default .rnstorybook:

  • all .factories stories are indexed and render (Actions, Text Input, Deep Controls, Backgrounds, Notes, Hidden Controls, plus the Factories Edge Cases group)
  • ondevice-actions logs onPress from a factories story
  • ondevice-controls binds to a factories story's args and live-edits them (canvas updates immediately)
  • sb-rn-get-stories generates correctly for both the factories and nofactories configs

Not yet covered here: an on-device (simulator) run — the jest portable-story tests and the web target exercise the same composition path, but a native run is worth doing before merging. One observation, present for both classic and factories stories (so unrelated to this PR): the controls panel doesn't refresh when switching stories and only binds correctly after a reload.

  • Does this need a new example in examples/expo-example? Already included (factories story variants + nofactories config).
  • Does this need an update to the documentation? Yes, once the API is considered stable enough to advertise — CSF Next is still a preview feature in core.

dannyhw and others added 26 commits December 15, 2025 00:02
…andling

Add storybook as devDependency to all workspace packages so pnpm hoists
a single copy, fixing duplicate action events caused by two separate
module instances each registering their own listener.

Sanitize RN synthetic events in action payloads only on the WebSocket
channel where async transport causes event pool recycling. Remove the
unnecessary patch from the local sync channel.

Remove early-return guards from addon panels so hooks are called
unconditionally, fixing React rules-of-hooks violations.
- Changed annotations parameter type from any[] to ModuleExports[] in resolveAnnotations and getProjectAnnotations functions.
- Introduced a PreviewObject interface and isPreviewObject type guard for better handling of preview objects.
- Updated storyEntries type to use Record<string, unknown> instead of any for improved type clarity.
- Updated storyEntries and normalizedStories types to use unknown instead of Record<string, unknown> for improved type flexibility.
- Added '@storybook/react-native-theming' as a dependency for theming capabilities.
- Updated ActionLogger to use styled components for count text based on the current theme.
- Refactored Inspect component to utilize themed text styles for various data types, enhancing visual consistency and readability.
- Removed *.lerna_backup from .gitignore.
- Improved clarity in CLAUDE.md by consolidating testing tool commands and adding a new section on sending events to the channel server.
- Streamlined the agent-device section for better readability.
- Removed redundant architecture overview section to focus on key concepts.
Resolves conflicts between the CSF factories work (#826) and six months of
drift on next:

- Start.tsx, preview.ts: take next's refactored versions (extracted
  getReactNativeProjectAnnotations, StoryEntry type, web workarounds);
  the factories logic lives in definePreview.tsx/entry-preview.ts
- index.ts: keep the types/config.ts split and definePreview exports,
  with StorybookConfig updated to next's newer shape (deviceAddons,
  deprecated addons)
- prepareStories.ts: next's TS6-friendly typing plus the factories-aware
  play detection (typeof story.play === 'function')
- package.json: next's dependency versions plus type-fest (used by
  definePreview types); dropped the addons: Preset[] refinement in favor
  of next's deliberate Addon union + deviceAddons split
- pnpm-lock.yaml: taken from next, to be regenerated by install
- pnpm-lock.yaml picks up the type-fest dependency
- .rnstorybook-nofactories/main.ts migrates from the deprecated addons
  field to deviceAddons, matching the factories config
- regenerate its storybook.requires.ts with the current generator
  template (was stale from before the merge)
@kasperpeulen
kasperpeulen requested a review from dannyhw as a code owner August 31, 2026 11:58
@changeset-bot

changeset-bot Bot commented Aug 31, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 8bd7fdc

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
@storybook/react-native Patch
@storybook/addon-ondevice-actions Patch
@storybook/addon-ondevice-backgrounds Patch
@storybook/addon-ondevice-controls Patch
@storybook/addon-ondevice-notes Patch
@storybook/react-native-theming Patch
@storybook/react-native-ui-common Patch
@storybook/react-native-ui-lite Patch
@storybook/react-native-ui Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@dannyhw

dannyhw commented Aug 31, 2026

Copy link
Copy Markdown
Member

👀

@dannyhw

dannyhw commented Sep 6, 2026

Copy link
Copy Markdown
Member

I think theres still the question of what we should do for users that have @storybook/react-native-web-vite and react native storybook together. Which preview do they import from and should we provide a suggested way to alias?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants