Skip to content

feat: CSF Factories (CSF Next) support#826

Draft
dannyhw wants to merge 24 commits intonextfrom
dannyhw/feat/csf-factories
Draft

feat: CSF Factories (CSF Next) support#826
dannyhw wants to merge 24 commits intonextfrom
dannyhw/feat/csf-factories

Conversation

@dannyhw
Copy link
Member

@dannyhw dannyhw commented Dec 15, 2025

Summary

10.3.0-canary-20260301145716

Adds support for CSF Next, the new Storybook configuration and story authoring format available experimentally in Storybook 10.

CSF Next replaces the traditional export default meta / export const Story pattern with a definePreview() / defineMain() / meta.story() API that provides full type safety, composability, and better IDE support.

Core changes

  • definePreview() support — Re-exports definePreview from @storybook/react and adds resolveAnnotations() in Start.tsx to unwrap the opaque Preview object that definePreview() produces. We extract .input (the user's plain config) rather than using .composed, which includes web-specific core annotations that depend on a browser environment not available on-device.
  • defineMain() support — Adds a typed defineMain() helper exported from @storybook/react-native/node for type-safe main config.
  • StorybookConfig type refinement — Moved to types/config.ts, now uses Preset type for addons instead of loose string/object union.
  • Improved type annotations — Replaces any[] with ModuleExports[] and unknown throughout Start.tsx.

Examples and tests

  • Adds .factories.stories.tsx variants for all existing example stories demonstrating the factories API
  • Adds .factories.test.tsx portable story tests for factories stories
  • Adds .rnstorybook-nofactories/ config directory to test both config styles side-by-side
  • Updates metro.config.js and App.tsx to support switching between factories and non-factories configs

How the factories API looks

preview.tsx (before):

import type { Preview } from '@storybook/react-native';

const preview: Preview = {
  parameters: { /* ... */ },
};
export default preview;

preview.tsx (after):

import { definePreview } from '@storybook/react-native';

export default definePreview({
  addons: [],
  parameters: { /* ... */ },
});

Stories (before):

const meta = { component: Button } satisfies Meta<typeof Button>;
export default meta;
export const Primary: StoryObj<typeof meta> = { args: { label: 'Click' } };

Stories (after):

const meta = config.meta({ component: Button });
export const Primary = meta.story({ args: { label: 'Click' } });

Test plan

  • pnpm build completes successfully
  • pnpm test passes — both factories and non-factories story tests
  • Run expo example with factories config — stories render correctly
  • Run expo example with non-factories config — stories render correctly
  • definePreview() config is properly unwrapped (parameters, decorators, etc. are applied)
  • defineMain() provides type checking for main config

@changeset-bot
Copy link

changeset-bot bot commented Feb 27, 2026

🦋 Changeset detected

Latest commit: cdfe8ba

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/react-native-ui Patch
@storybook/react-native-ui-lite Patch
@storybook/react-native-ui-common Patch
@storybook/react-native-theming Patch
@storybook/addon-ondevice-actions Patch
@storybook/addon-ondevice-backgrounds Patch
@storybook/addon-ondevice-controls Patch
@storybook/addon-ondevice-notes 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

…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.
@dannyhw dannyhw marked this pull request as ready for review February 27, 2026 22:16
@dannyhw dannyhw changed the title feat: csf factories feat: csf next support Feb 27, 2026
- 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.
@dannyhw dannyhw changed the title feat: csf next support feat: CSF Factories (CSF Next) support Feb 28, 2026
@dannyhw dannyhw marked this pull request as draft March 1, 2026 16:27
@dannyhw
Copy link
Member Author

dannyhw commented Mar 1, 2026

current issues:
anything that tries to read meta/preview can sometimes get nothing because of how we now have .input and .composed instead of plain objects

dannyhw added 6 commits March 1, 2026 17:13
- 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.
@dannyhw
Copy link
Member Author

dannyhw commented Mar 1, 2026

update: added a react native define preview so we get compose preview, story etc without issues and more inline with storybook/react

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.

1 participant