Skip to content

feat: built-in on-device actions by default, deprecate addon-ondevice-actions - #959

Draft
dannyhw wants to merge 4 commits into
nextfrom
dannyhw/feat/builtin-actions
Draft

dannyhw wants to merge 4 commits into
nextfrom
dannyhw/feat/builtin-actions

Conversation

@dannyhw

@dannyhw dannyhw commented Nov 7, 2026 •

Copy link
Copy Markdown
Member

What

The on-device Actions panel is now built into @storybook/react-native and enabled by default. @storybook/addon-ondevice-actions becomes a deprecated compatibility stub. This follows the backgrounds work in #848.

To opt out:

// .rnstorybook/main.ts
features: {
  ondeviceActions: false,
},

@storybook/react-native

  • The Actions implementation (ActionLogger component and container, actionStore) lives in src/actions/. registerActionsAddon() is in actions/register.tsx.
  • start() registers it when globalThis.FEATURES?.ondeviceActions !== false, right after setChannel and the backgrounds registration.
  • Features.ondeviceActions is documented as on by default (@default true; set false to disable).
  • fast-deep-equal is added to dependencies. It is the only extra dependency.
  • Tests:
    • actionStore tests moved from the addon package.
    • feature.test.ts: start() registers by default, and with other features set, but not when ondeviceActions: false.
    • register.test.tsx: runs against the real storybook/manager-api. Calling the stub's register registers nothing; after the built-in registers and loadAddons runs, there is exactly one Actions panel; and the dev warning fires once.
    • Jest changes: @storybook/icons was added to the jest transform patterns so the real manager-api loads. The older start() test mocks gained register: jest.fn().

@storybook/addon-ondevice-actions (stub)

  • register() (and register.js) registers nothing and does not touch the built-in addon. In __DEV__ it logs one console.warn saying the addon is built into @storybook/react-native and that the package can be removed from deviceAddons and uninstalled. The exported API (register) is unchanged.
  • The duplicated source, tests and jest/sucrase setup are deleted.
  • Dependencies are dropped. @storybook/react-native (^11.0.0-next.1) is now the only peer dependency.
  • tsc still emits dist/index.js, which is what register.js requires.
  • The README is rewritten: the package is deprecated, the panel is built in, and how to migrate.

Because the stub never registers, the earlier "package and flag together" override path, its warning and its test are gone.

Examples

  • examples/expo-example/.rnstorybook no longer lists the package or sets the flag, so it uses the built-in panel by default. storybook.requires.ts is regenerated.
  • .rnstorybook-nofactories, expo-router-example, expo-new-wrapper-example and repack-example still list @storybook/addon-ondevice-actions, so the stub path stays exercised.

Docs and changesets

  • MIGRATION.md (10 → 11) has a new "Actions is built into @storybook/react-native" section, and the package is removed from its v11 dependency example.
  • The feature-flags table, configuration/actions.md (now: on by default, how to turn it off, migration), addons/index.md, manual-setup.md, cli-configuration.md and configuration/index.md are updated.
  • Both READMEs, template/cli/main.ts and the writing-stories skill no longer install or list the package.
  • Changesets: major for both @storybook/react-native and @storybook/addon-ondevice-actions. They are in the same fixed group, and this matches how other v11 breaking changes were recorded (e.g. require-device-addons).

Testing

pnpm build, pnpm test, pnpm lint, pnpm format:check and check:types all pass, for both @storybook/react-native and the stub.

On device, I tested expo-example on an iOS 26.4 simulator with the story ActionExample/Actions/Basic. In both runs I pressed the button twice before first opening the panel, then closed it, pressed once more and reopened it.

  • Built-in by default (.rnstorybook, package not listed):
    • one Actions tab, with all three onPress entries.
  • Stub still listed (EXPO_PUBLIC_NO_FACTORIES=true, .rnstorybook-nofactories, which imports @storybook/addon-ondevice-actions/register):
    • one Actions tab, with all three onPress entries.
    • Metro logged the deprecation warning exactly once.

Screenshots (local): ~/pr-evidence/builtin-actions/default-2-reopened.png and ~/pr-evidence/builtin-actions/stub-2-reopened.png.

Android: dev build on an Android 15 (API 35) emulator

expo-example dev build (expo prebuild + gradlew app:assembleDebug, arm64) on a temporary Pixel 9 AVD (google_apis arm64 image), with Metro on 8081 and the channel server on 7007. I used the same ActionExample/Actions/Basic flow, and counted storybook/actions/action-event messages with a websocket listener on the channel server.

  • Built-in by default (.rnstorybook): pressed twice with the panel closed, then opened it. There's one Actions tab (the tabs are Actions, Backgrounds, Notes, Controls), and every press was listed. I closed the panel, pressed once, reopened it and selected Actions: all entries were still there, including the new one.
  • Stub still listed (.rnstorybook-nofactories): pressed twice, opened the panel (2 entries), closed it, pressed once and reopened it (3 entries). There's one Actions tab. Metro logged the addon-ondevice-actions is deprecated warning exactly once.
  • Nothing Android-specific failed, and no changes were needed.
  • Unrelated and already on next: the panel reopens on its first tab, not the last tab used.

Screenshots (local, ~/Developer/test-evidence/android-959/):

  • 01-default-first-open.png, 02-default-reopen-after-closed-presses.png, 03-default-close-fire-reopen.png
  • 04-nofactories-first-open.png, 05-nofactories-close-fire-reopen.png
  • Metro and websocket logs: metro-*.log, ws-*.log

Move the Actions panel from @storybook/addon-ondevice-actions into
@storybook/react-native, registered from start() when
features.ondeviceActions is set, following the ondeviceBackgrounds
precedent. It reuses the storybook/actions addon id, so a leftover
package entry in deviceAddons is replaced rather than duplicated, and a
development warning suggests removing it.
@changeset-bot

changeset-bot Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: cd8eb0f

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

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

The built-in Actions panel now registers unless features.ondeviceActions
is false. @storybook/addon-ondevice-actions becomes a compatibility stub
whose register is a no-op that warns once in development, so configs
that still list it get exactly one panel from @storybook/react-native.
Its duplicated source, tests and jest setup are removed.

Docs, templates, the stories skill and MIGRATION.md no longer install or
list the package.
@dannyhw dannyhw changed the title feat: built-in on-device actions addon behind ondeviceActions flag feat: built-in on-device actions by default, deprecate addon-ondevice-actions Nov 7, 2026
# Conflicts:
#	packages/ondevice-actions/package.json
#	packages/react-native/package.json
#	pnpm-lock.yaml

This branch has not been deployed

No deployments
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