Skip to content

Latest commit

 

History

History
980 lines (706 loc) · 32.5 KB

File metadata and controls

980 lines (706 loc) · 32.5 KB

Migration

From version 9 to 10

Version 10 brings Storybook React Native in sync with Storybook core v10, introducing improved Metro configuration and a simplified API.

Update Storybook dependencies to 10.x

You need to update all Storybook dependencies to version 10.x. This includes:

  • storybook package (core)
  • @storybook/react package
  • @storybook/react-native package
  • All @storybook/addon-ondevice-* packages

Note: You can check the correct version by looking at the peerDependencies. Please refer to the core Storybook migration guide for more details on the breaking changes in Storybook core v10.

Example package.json after upgrade:

{
  "devDependencies": {
    "@storybook/react-native": "^10.0.0",
    "@storybook/react": "^10.0.0",
    "@storybook/addon-ondevice-controls": "^10.0.0",
    "@storybook/addon-ondevice-actions": "^10.0.0",
    "@storybook/addon-ondevice-backgrounds": "^10.0.0",
    "@storybook/addon-ondevice-notes": "^10.0.0",
    "storybook": "^10.0.0"
  }
}

Update your metro config

The withStorybook metro wrapper has been significantly simplified in v10. The key changes are:

  1. BREAKING: Named import required - withStorybook is now a named export instead of a default export
  2. Import path unified - In v9, withStorybookConfig (from metro/withStorybookConfig) was a preview of the simplified API. In v10, this is now the standard behavior when importing withStorybook from metro/withStorybook
  3. onDisabledRemoveStorybook is removed - When enabled: false, Storybook is automatically removed from the bundle (no separate flag needed)
  4. Simpler defaults - Works out of the box with sensible defaults

Before (v9):

If you were using the preview withStorybookConfig (recommended approach in v9):

const { withStorybookConfig } = require('@storybook/react-native/metro/withStorybookConfig');

module.exports = withStorybookConfig(defaultConfig);

Or if you were using withStorybook with the old API (default export):

const withStorybook = require('@storybook/react-native/metro/withStorybook'); // ❌ Default export

module.exports = withStorybook(defaultConfig, {
  enabled: process.env.STORYBOOK_ENABLED === 'true',
  onDisabledRemoveStorybook: true, // This option no longer exists in v10
  configPath: path.resolve(__dirname, './.rnstorybook'),
});

After (v10):

const { withStorybook } = require('@storybook/react-native/metro/withStorybook'); // ✅ Named export

// Basic usage - works out of the box with defaults
module.exports = withStorybook(defaultConfig);

// Or with options
module.exports = withStorybook(defaultConfig, {
  // When false, automatically removes Storybook from bundle
  enabled: process.env.EXPO_PUBLIC_STORYBOOK_ENABLED === 'true',
  configPath: path.resolve(__dirname, './.rnstorybook'),
});

Key improvements:

  • BREAKING: Must use named import: const { withStorybook } = require(...) instead of default import
  • withStorybookConfig functionality is now the default behavior of withStorybook
  • When enabled: false, Storybook packages are automatically stubbed out (no need for onDisabledRemoveStorybook)
  • Default configPath is ./.rnstorybook

Simplify your App.tsx (or Expo Router routes)

In v10, you can now directly import and export Storybook without worrying about bundle size or conditional imports. The metro config automatically handles everything.

Before (v9):

You couldn't safely import Storybook at the top level because it would be included in your production bundle, even when disabled. Then even if you used the onDisabledRemoveStorybook option you would still need to conditionally import Storybook in your app code to not cause a crash.

// App.tsx
let AppEntryPoint = App;

if (process.env.EXPO_PUBLIC_STORYBOOK_ENABLED === 'true') {
  // Conditional import to avoid bundling Storybook in production
  AppEntryPoint = require('./.rnstorybook').default;
}

export default AppEntryPoint;

After (v10):

Now you can safely import Storybook at the top level - metro will automatically remove it when enabled: false:

// App.tsx
import StorybookUI from './.rnstorybook'; // ✅ Safe! Metro stubs this out when enabled: false
import { Text, View } from 'react-native';

const isStorybook = process.env.EXPO_PUBLIC_STORYBOOK_ENABLED === 'true';

// this could be your app entrypoint
const AppComponent = () => {
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>Hello World</Text>
    </View>
  );
};

export default function App() {
  return isStorybook ? <StorybookUI /> : <AppComponent />;
}

The key difference: the top-level import is now safe! Metro automatically stubs out the .rnstorybook import when enabled: false, removing all Storybook code from your production bundle.

Or even simpler, with Expo Router, you can create a dedicated route and now not worry about conditional inline requires.

// app/storybook.tsx
export { default } from '../.rnstorybook';

How it works:

The metro config (enabled flag) automatically handles bundle inclusion:

  • When enabled: true - Storybook is included in the bundle
  • When enabled: false - The .rnstorybook import is automatically stubbed out as an empty module, and all Storybook dependencies are removed

Key benefits:

  • ✅ Import Storybook anywhere without bundle size concerns
  • ✅ Works seamlessly with Expo Router - just create a /storybook route
  • ✅ No more worrying about top-level imports bloating your production bundle
  • ✅ Metro handles all the complexity automatically

Regenerate your requires file

After updating dependencies and configuration, regenerate your .rnstorybook/storybook.requires.ts file:

yarn storybook-generate

Or if you have the generate call in your metro config (recommended), just restart metro:

yarn start --reset-cache

Summary of breaking changes

  1. Metro config API changes:

    • BREAKING: withStorybook is now a named export - use const { withStorybook } = require(...) instead of default import
    • withStorybookConfig from metro/withStorybookConfig is removed
    • Use withStorybook from metro/withStorybook instead (the simplified API is now standard)
    • onDisabledRemoveStorybook option removed (automatic when enabled: false)
  2. Default config folder:

    • Confirmed as ./.rnstorybook (to avoid conflicts with web Storybook)
  3. Storybook core updated to v10:

  4. Simplified app entry:

    • Custom switcher components no longer needed for bundle optimization
    • Metro config handles conditional inclusion automatically

From version 8 to 9

Update Storybook dependencies to 9.x

You need to update all Storybook dependencies to version 9.x. This includes:

  • storybook package

Note: You can check the correct version by looking at the peerDependencies. Please refer to the core Storybook migration guide for more details on the breaking changes of this package.

  • @storybook/addon-ondevice-* packages

Update your .storybook folder

For better compatibility with projects that includes both Storybook and Storybook React Native, the default configuration folder for Storybook React Native has been renamed from .storybook/ to .rnstorybook/.

Regenerate your requires file

Regenerate your .rnstorybook/storybook.requires.ts file by running yarn storybook-generate.

From version 7.6.x to 8.3.x

In this version of storybook we've reworked the UI using some community react native packages. We've also overhauled the theme to match the web version.

Dependencies

Update all storybook dependencies to 8.3.5 or newer.

For example you may end up with something like this

// package.json
{
  "devDependencies": {
    "@storybook/react-native": "^8.3.5",
    "@storybook/react": "^8.3.5",
    "@storybook/addon-ondevice-controls": "^8.3.5",
    "@storybook/addon-ondevice-actions": "^8.3.5",
    "@storybook/addon-ondevice-backgrounds": "^8.3.5",
    "@storybook/addon-ondevice-notes": "^8.3.5"
  }
}

Add the new required dependencies to your project.

Expo:

npx expo install react-native-reanimated react-native-gesture-handler @gorhom/bottom-sheet react-native-svg

RN Cli:

npm install react-native-reanimated react-native-gesture-handler @gorhom/bottom-sheet react-native-svg

Make sure you use versions of those packages supported by your version of expo/react-native

Regenerate your requires file

Regenerate your .storybook/storybook.requires.ts file by running yarn storybook-generate.

You should see a new updateView function in the file.

Update your metro config

// metro.config.js
const path = require('path');
const withStorybook = require('@storybook/react-native/metro/withStorybook');

module.exports = withStorybook(config, {
  // set to false to disable storybook specific settings
  // you can use a env variable to toggle this
  enabled: true,
  // path to your storybook config folder
  configPath: path.resolve(__dirname, './.storybook'),
});

For a full list of options, see the withStorybook documentation.

From version 6.5.x to 7.6.x

In this version of storybook we've a lot of changes to the internals of react native storybook to make it more compatible with core storybook libraries. This means compatibility with the new v7 store and the api changes that comes with that.

Here are some of the other improvements:

  • New storage option that lets you choose what storage solution you want to use (async storage/mmkv etc).
  • Support for main.ts
  • Dynamic imports enabled by the unstable_allowRequireContext option in metro config.
    • you only need to generate your requires file when main.ts changes.
  • Error boundaries for stories so your app shouldn't crash when a story throws an error.
  • Improved markdown renderer for notes addon.
  • Simpler setup for auto args.

Note

You should follow a different set of changes if you need to support storiesOf, see 6.5.x to 7.6.x with storiesOf support

Dependencies

Update all storybook dependencies to 7.6.10 or newer.

For example you may end up with something like this

{
  "@storybook/react-native": "^7.6.10",
  "@storybook/addon-ondevice-actions": "^7.6.10",
  "@storybook/addon-ondevice-backgrounds": "^7.6.10",
  "@storybook/addon-ondevice-controls": "^7.6.10",
  "@storybook/addon-ondevice-notes": "^7.6.10"
}

Regenerate your requires file

Regenerate your storybook.requires file by running yarn storybook-generate.

It should now generate a storybook.requires.ts file instead of a storybook.requires.js file.

This provides the type for the new view export.

Update .storybook/index.js

Update .storybook/index.js to use the new getStorybookUI function on the view exported from storybook.requires.ts. You can also change this file to be called .storybook/index.tsx.

You should also now pass a storage object to the getStorybookUI function. This is used to persist the selected story between reloads.

// .storybook/index.tsx
import { view } from './storybook.requires';
import AsyncStorage from '@react-native-async-storage/async-storage';

const StorybookUIRoot = view.getStorybookUI({
  storage: {
    getItem: AsyncStorage.getItem,
    setItem: AsyncStorage.setItem,
  },
});

export default StorybookUIRoot;

Metro config

Update your metro.config.js to enable the unstable_allowRequireContext option and you can now remove the sbmodern resolver if you have it.

Note

The unstable_allowRequireContext option requires at least react native 0.72

If you are using expo and you don't have a metro config file you can create one by running npx expo customize metro.config.js.

You can also add here the generate function to automatically update the storybook.requires.ts file when you start metro.

You only need to regenerate this file now when main.js updates since requireContext allows us to use dynamic imports.

Expo

// metro.config.js
const path = require('path');
const { getDefaultConfig } = require('expo/metro-config');

const { generate } = require('@storybook/react-native/scripts/generate');

generate({
  configPath: path.resolve(__dirname, './.storybook'),
});

/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname);

config.transformer.unstable_allowRequireContext = true;

config.resolver.sourceExts.push('mjs');

module.exports = config;

React Native CLI

const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
const path = require('path');

const { generate } = require('@storybook/react-native/scripts/generate');

generate({
  // update ./.storybook to your storybook folder
  configPath: path.resolve(__dirname, './.storybook'),
});

const defaultConfig = getDefaultConfig(__dirname);

/**
 * Metro configuration
 * https://facebook.github.io/metro/docs/configuration
 *
 * @type {import('metro-config').MetroConfig}
 */
const config = {
  transformer: {
    unstable_allowRequireContext: true,
  },
  resolver: {
    sourceExts: [...defaultConfig.resolver.sourceExts, 'mjs'],
  },
};

module.exports = mergeConfig(defaultConfig, config);

You can now also remove anything from package.json scripts which would run generate before running storybook.

Types

We've removed the types from @storybook/react-native and now you should import them from @storybook/react. This is to remove duplication and increase compatibility with core storybook libraries.

Heres an example story in version 7:

import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';

const meta = {
  component: Button,
  argTypes: {
    onPress: { action: 'pressed the button' },
  },
} satisfies Meta<typeof Button>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Basic: Story = {
  args: {
    text: 'Press me!',
  },
};

You can now also update main.js to main.ts and use the StorybookConfig type. This is one of the only types we export from @storybook/react-native in this version.

// .storybook/main.ts
import type { StorybookConfig } from '@storybook/react-native';

const main: StorybookConfig = {
  stories: ['../components/**/*.stories.?(ts|tsx|js|jsx)'],
  addons: [
    '@storybook/addon-ondevice-notes',
    '@storybook/addon-ondevice-controls',
    '@storybook/addon-ondevice-backgrounds',
    '@storybook/addon-ondevice-actions',
  ],
};

export default main;

To update preview.js to preview.tsx you can use the Preview type from @storybook/react

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

const preview: Preview = {
	decorators: []
  parameters: {}
};

export default preview;

doctools

If you are manually adding doctools to do auto args you can now remove this code since its automatically added now. To make it work you still need babel-plugin-react-docgen-typescript though.

-import { extractArgTypes } from "@storybook/react/dist/modern/client/docs/extractArgTypes";
-import { addArgTypesEnhancer, addParameters } from "@storybook/react-native";
-import { enhanceArgTypes } from "@storybook/core/docs-tools";

-addArgTypesEnhancer(enhanceArgTypes);
-addParameters({
-  docs: {
-    extractArgTypes,
-  },
-});

(optional) react-native-server

In version 7 it wasn’t possible to update @storybook/react-native-server as it was. Instead we’ve released a new ReactJS addon called @storybook/addon-react-native-server. With this new addon you will need to setup a ReactJS storybook with a separate storybook config. The benefit of this setup is that its possible to get a web preview of the components if your components are compatible with react-native-web.

There will shortly be a proper guide to setting this up, however the basics will be covered here.

The setup is the same as @storybook/addon-react-native-web but with the reactNativeServerOptions property in the config file.

First install necessary packages

yarn add -D @storybook/addon-react-native-web @storybook/addon-essentials storybook @storybook/react-webpack5 @storybook/react babel-plugin-react-native-web react-native-web @storybook/addon-react-native-server

With expo you should also add @expo/metro-runtime.

Update package.json scripts

"storybook:web": "storybook dev -p 6006 -c .storybook-web",
"build-storybook": "storybook build -c .storybook-web"

Create .storybook-web config folder

Add a main.ts

// .storybook-web/main.ts
import type { StorybookConfig } from '@storybook/react-webpack5';

type ServerStorybookConfig = StorybookConfig & {
  reactNativeServerOptions: { host: string; port: number };
};

const main: ServerStorybookConfig = {
  stories: ['../components/**/*.stories.?(ts|tsx|js|jsx)'],
  addons: [
    '@storybook/addon-essentials',
    '@storybook/addon-react-native-web',
    '@storybook/addon-react-native-server',
  ],
  framework: {
    name: '@storybook/react-webpack5',
    options: {},
  },

  reactNativeServerOptions: {
    // for android you should use your local ip address here
    host: 'localhost',
    port: 7007,
  },

  docs: {
    autodocs: 'tag',
  },
};

export default main;

Add a preview.tsx

// .storybook-web/preview.tsx
import type { Preview } from '@storybook/react';

const preview: Preview = {
  decorators: [],
  parameters: {
    actions: { argTypesRegex: '^on[A-Z].*' },
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/,
      },
    },
  },
};
export default preview;

In your .storybook/index.tsx file where you call view.getStorybookUI make sure you enable Web sockets and match the host and port config from your .storybook-web/main.ts.

import { view } from './storybook.requires';
import AsyncStorage from '@react-native-async-storage/async-storage';

const StorybookUIRoot = view.getStorybookUI({
  storage: {
    getItem: AsyncStorage.getItem,
    setItem: AsyncStorage.setItem,
  },
  enableWebsockets: true,
  host: 'localhost',
  port: 7007,
});

export default StorybookUIRoot;

Now just make sure you run storybook:web before running your React Native Storybook and you should be able to sync up your stories between web and your mobile devices.

6.5.x to 7.6.x with storiesOf support

Storybook v7 doesn't support storiesOf in the same way as v6, but there is a compatibility mode that allows you to continue using storiesOf whilst you migrate your stories.

Warning

By opting into this compatibility mode you will lose out on some features of v7. We highly recommend moving to CSF stories.

StoriesOf will be removed in v8 along with knobs and testing on those deprecated features will be limited.

Update dependencies

Update all storybook dependencies to 7.6.10 or newer.

For example you may end up with something like this

{
  "@storybook/react-native": "^7.6.10",
  "@storybook/addon-ondevice-actions": "^7.6.10",
  "@storybook/addon-ondevice-backgrounds": "^7.6.10",
  "@storybook/addon-ondevice-controls": "^7.6.10",
  "@storybook/addon-ondevice-notes": "^7.6.10"
}

Update your package.json scripts

To opt in you can pass --v6-store to sb-rn-get-stories in the generate script.

{
  "scripts": {
    "storybook-generate": "sb-rn-get-stories --v6-store"
  }
}

You should also now import storiesOf from @storybook/react-native/V6 this is necessary so that certain code paths don't run in v7 mode.

Regenerate your requires file

Now that you've updated the script you can regenerate your storybook.requires.js file by running yarn storybook-generate.

It should now have the updated @storybook/react-native/V6 import in it.

Update .storybook/index.js

Update the import in .storybook/index.js from @storybook/react-native to @storybook/react-native/V6. You can also change this file to be called .storybook/index.tsx.

You should also make sure to add the storage prop to the getStorybookUI call. This lets you opt into using a different storage solution like mmkv or if you put async storage there it will continue to work as it did before.

// .storybook/index.tsx
import './storybook.requires';
import { getStorybookUI } from '@storybook/react-native/V6';
import AsyncStorage from '@react-native-async-storage/async-storage';

const StorybookUIRoot = getStorybookUI({
  storage: {
    getItem: AsyncStorage.getItem,
    setItem: AsyncStorage.setItem,
  },
});

export default StorybookUIRoot;

Update your stories

Where ever you use storiesOf you should now import it from @storybook/react-native/V6.

import { storiesOf } from '@storybook/react-native/V6';
import { text } from '@storybook/addon-knobs';
import { withKnobs } from '@storybook/addon-ondevice-knobs';
import React from 'react';
import { Button } from './AnotherButton';

storiesOf('Another Button', module)
  .addDecorator(withKnobs)
  .add('another button example', () => <Button text={text('text', 'test2')} onPress={() => null} />)
  .add('again', () => <Button text={text('text', 'text2')} onPress={() => null} />);

Types

If you're using typescript you may notice that for v7 we've removed the types in @storybook/react-native. Thats part of an effort to re-use more code, you should now import them from @storybook/react instead.

From version 5.3.x to 6.5.x

Additional dependencies

To make storybook more compatible with core storybook libraries we are using some new dependencies. You will need to add these to your project.

yarn add -D @storybook/react-native @storybook/core/common @react-native-async-storage/async-storage react-native-safe-area-context react-dom

Controls (the new knobs)

To use the controls addon you will need these dependencies

yarn add -D @storybook/addon-ondevice-controls @storybook/addons @storybook/addon-controls @react-native-community/datetimepicker @react-native-community/slider

Actions

To use the actions addon you will need these dependencies

yarn add -D @storybook/addon-ondevice-actions @storybook/addon-actions

.storybook folder

Rename the storybook folder to .storybook

Update your index.js file

In 6.5 we use a script to generate your imports for stories and addons. This uses the new main.js file to generate the storybook.requires.js file. This file is then imported into the index.js file.

Remove the configure call, story imports and addon imports and reduce the index file to have this content. The most important thing is to import the storybook.requires file.

Also if your Storybook folder is called storybook you should change it to .storybook .

// .storybook/index.js
import { getStorybookUI } from '@storybook/react-native';
import './storybook.requires';

const StorybookUIRoot = getStorybookUI({
  // options go here
});

export default StorybookUI;

Add a main.js and preview.js

In your .storybook folder add the main.js and preview.js files.

In the stories field of your main.js file update the regex to work for your project.

In the addons field list the addons you want to use, these must be compatible with React Native Storybook. Addons made for React Native are usually prefixed with addon-ondevice.

// .storybook/main.js
module.exports = {
  stories: ['../components/**/*.stories.?(ts|tsx|js|jsx)'],
  addons: [
    '@storybook/addon-ondevice-controls',
    '@storybook/addon-ondevice-actions',
    '@storybook/addon-ondevice-backgrounds',
  ],
};

Move any global decorators and parameters your have to preview.js , if you don’t have any then just export an empty array for decorators and an empty object for parameters.

// .storybook/preview.js
import { View } from 'react-native';

export const decorators = [
  // Using a decorator to apply padding for every story
  (StoryFn) => (
    <View style={{ flex: 1, padding: 8 }}>
      <StoryFn />
    </View>
  ),
];

export const parameters = {
  my_param: 'anything',
};

Scripts in package.json

In storybook 6.5 there are some new binaries that generate your story imports and one that watches for new files.

You can add these scripts to your package.json file.

{
  "scripts": {
    "storybook-generate": "sb-rn-get-stories",
    "storybook-watch": "sb-rn-watcher"
  }
}

You'll want to run the generate script whenever you add a new story file. Alternatively you can keep the watcher running.

There are some options you can pass to the both these scripts. You can see them by running yarn sb-rn-get-stories --help and sb-rn-watcher --help.

  .description('Getter and watcher for react native storybook')
  .option(
    '-c, --config-path <path>',
    'The path to your config folder relative to your project-dir',
    './.storybook'
  )
  .option('-a, --absolute', 'Use absolute paths for story imports');

Update your metro config

We use the sbmodern resolver field in order to resolve the modern version of storybook packages. Doing this removes the polyfills that ship in commonjs modules and fixes multiple long standing issues such as the promises never resolving bug and more (caused by corejs promises polyfill).

Expo

First create metro config file if you don't have it yet.

npx expo customize metro.config.js

Then add sbmodern to the start of the resolver.resolverMainFields list.

// metro.config.js

const { getDefaultConfig } = require('expo/metro-config');

--module.exports = getDefaultConfig(__dirname);
++const defaultConfig = getDefaultConfig(__dirname);

++defaultConfig.resolver.resolverMainFields.unshift('sbmodern');

++module.exports = defaultConfig;

React native

module.exports = {
  /* existing config */
  resolver: {
    resolverMainFields: ['sbmodern', 'react-native', 'browser', 'main'],
  },
};

Convert your stories to CSF

Whilst storiesOf will still work it is now deprecated so we recommend that you convert your stories to CSF.

There is a codemod for your convenience which should automatically make the code changes for you (make sure to update the glob to fit your files):

npx storybook@next migrate storiesof-to-csf --glob="src/**/*.stories.tsx"

Replace the storiesOf API with a default export that defines the title and component of your stories. Replace the add method with named exports that define each story. If you have any parameters or decorators, you can add them to the default export or to stories.

// Before
storiesOf('Button', module)
  .addParameters({ myParam: "anything" })
  .addDecorator((Story)=> <Wrapper>{Story}</Wrapper>)
  .add('primary', () => <Button primary label="Button" />)
  .add('secondary', () => <Button label="Button" />);

// After
export default {
  title: 'Button',
  component: Button,

  // for all stories in this file
  parameters: {  myParam: "anything" },
};

export const Primary = { args: { primary: true, label: "button" } };

export const Secondary = {
  // this gives the property "label" the default value "button"
  args: { label: "button" }

  // for just this story
  decorators: [(Story) => (<Wrapper><Story/></Wrapper>)],
  parameters: {myParam: "something else"}
};

Theming

The theme structure in Storybook 6.5 provides much more granular control over more of the Storybook UI, including addons, this unfortunately makes it difficult to provide backwards compatibility. If you were previously using a custom theme you will now need to migrate it to the new theme.

The themeable values are comprehensively listed in the Theme type in theme.ts.

Below the old theme keys are listed against a comparable key in the new theme, although bear in mind that there are many more aspects of the UI that can be themed now, this is just to help get you started:

  • backgroundColor: backgroundColor
  • storyListBackgroundColor: panel.backgroundColor
  • listItemTextColor: storyList.storyTextColor
  • listItemActiveColor: storyList.storySelectedBackgroundColor
  • listItemActiveTextColor: storyList.storySelectedTextColor
  • headerTextColor: storyList.headerTextColor
  • labelColor: inputs.labelTextColor
  • borderColor: panel.borderColor, navigation.borderColor, inputs.text.borderColor, inputs.radio.borderColor, inputs.swatch.borderColor
  • previewBorderColor: The preview no longer has a border and uses an elevation shadow instead
  • buttonTextColor: tabs.inactiveTextColor, button.primary.textColor, button.secondary.textColor
  • buttonActiveTextColor: tabs.activeTextColor
  • secondaryLabelColor: inputs.slider.valueTextColor

Test ids for tabs

The tabs were renamed to Sidebar, Canvas and Addons. So the test ids for the tabs are now:

BottomMenu.Sidebar, BottomMenu.Canvas, BottomMenu.Addons

And their text was updated to SIDEBAR, CANVAS, ADDONS.

The server

The server is a package called @storybook/react-native-server and its an optional companion app that lets you control the React Native Storybook UI thats on your device via a web UI.

In this version the configuration for that was changes slightly.

Now to configure the server you'll add a .storybook_server folder with a main.js. In this file you should put the same stories regex that you have in your .storybook/main.js file.

module.exports = {
  stories: ['../components/**/*.stories.?(ts|tsx|js|jsx)'],
  env: () => ({}),
  addons: ['@storybook/addon-essentials'],
};

Then in package.json you'll need a new script

"start-server": "react-native-storybook-server"

For more information about this please read this blog post.