Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@storybook/addon-ondevice-backgrounds

storybookjs334.8kMIT8.6.4TypeScript support: included

A react-native storybook addon to show different backgrounds for your preview

addon, background, react, storybook

readme

Storybook for React Native

[!IMPORTANT]
This readme is for v8, for v7 docs see the v7.6 docs.

With Storybook for React Native you can design and develop individual React Native components without running your app.

If you are migrating from 7.6 to 8.3 you can find the migration guide here

For more information about storybook visit: storybook.js.org

[!NOTE]
@storybook/react-native requires atleast 8.3.1, if you install other storybook core packages they should be ^8.3.1 or newer.

picture of storybook

Table of contents

Getting Started

New project

There is some project boilerplate with @storybook/react-native and @storybook/addon-react-native-web both already configured with a simple example.

For expo you can use this template with the following command

# With NPM
npx create-expo-app --template expo-template-storybook AwesomeStorybook

For react native cli you can use this template

npx react-native init MyApp --template react-native-template-storybook

Existing project

Run init to setup your project with all the dependencies and configuration files:

npx storybook@latest init

The only thing left to do is return Storybook's UI in your app entry point (such as App.tsx) like this:

export { default } from './.storybook';

Then wrap your metro config with the withStorybook function as seen below

If you want to be able to swap easily between storybook and your app, have a look at this blog post

If you want to add everything yourself check out the the manual guide here.

Additional steps: Update your metro config

We require the unstable_allowRequireContext transformer option to enable dynamic story imports based on the stories glob in main.ts. We can also call the storybook generate function from the metro config to automatically generate the storybook.requires.ts file when metro runs.

Expo

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

npx expo customize metro.config.js

Then wrap your config in the withStorybook function as seen below.

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

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

module.exports = withStorybook(config, {
  // Set to false to remove storybook specific options
  // you can also use a env variable to set this
  enabled: true,
  // Path to your storybook config
  configPath: path.resolve(__dirname, './.storybook'),

  // Optional websockets configuration
  // Starts a websocket server on the specified port and host on metro start
  // websockets: {
  //   port: 7007,
  //   host: 'localhost',
  // },
});

React native

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

/**
 * Metro configuration
 * https://reactnative.dev/docs/metro
 *
 * @type {import('metro-config').MetroConfig}
 */
const config = {};
// set your own config here 👆

const finalConfig = mergeConfig(defaultConfig, config);

module.exports = withStorybook(finalConfig, {
  // Set to false to remove storybook specific options
  // you can also use a env variable to set this
  enabled: true,
  // Path to your storybook config
  configPath: path.resolve(__dirname, './.storybook'),

  // Optional websockets configuration
  // Starts a websocket server on the specified port and host on metro start
  // websockets: {
  //   port: 7007,
  //   host: 'localhost',
  // },
});

Reanimated setup

Make sure you have react-native-reanimated in your project and the plugin setup in your babel config.

// babel.config.js
plugins: ['react-native-reanimated/plugin'],

Writing stories

In storybook we use a syntax called CSF that looks like this:

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

const meta = {
  component: MyButton,
} satisfies Meta<typeof MyButton>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Basic: Story = {
  args: {
    text: 'Hello World',
    color: 'purple',
  },
};

You should configure the path to your story files in the main.ts config file from the .storybook folder.

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

const main: StorybookConfig = {
  stories: ['../components/**/*.stories.?(ts|tsx|js|jsx)'],
  addons: [],
};

export default main;

Decorators and Parameters

For stories you can add decorators and parameters on the default export or on a specifc story.

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

const meta = {
  title: 'Button',
  component: Button,
  decorators: [
    (Story) => (
      <View style={{ alignItems: 'center', justifyContent: 'center', flex: 1 }}>
        <Story />
      </View>
    ),
  ],
  parameters: {
    backgrounds: {
      values: [
        { name: 'red', value: '#f00' },
        { name: 'green', value: '#0f0' },
        { name: 'blue', value: '#00f' },
      ],
    },
  },
} satisfies Meta<typeof Button>;

export default meta;

For global decorators and parameters, you can add them to preview.tsx inside your .storybook folder.

// .storybook/preview.tsx
import type { Preview } from '@storybook/react';
import { withBackgrounds } from '@storybook/addon-ondevice-backgrounds';

const preview: Preview = {
  decorators: [
    withBackgrounds,
    (Story) => (
      <View style={{ flex: 1, color: 'blue' }}>
        <Story />
      </View>
    ),
  ],
  parameters: {
    backgrounds: {
      default: 'plain',
      values: [
        { name: 'plain', value: 'white' },
        { name: 'warm', value: 'hotpink' },
        { name: 'cool', value: 'deepskyblue' },
      ],
    },
  },
};

export default preview;

Addons

The cli will install some basic addons for you such as controls and actions. Ondevice addons are addons that can render with the device ui that you see on the phone.

Currently the addons available are:

Install each one you want to use and add them to the main.ts addons list as follows:

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

const main: StorybookConfig = {
  // ... rest of config
  addons: [
    '@storybook/addon-ondevice-notes',
    '@storybook/addon-ondevice-controls',
    '@storybook/addon-ondevice-backgrounds',
    '@storybook/addon-ondevice-actions',
  ],
};

export default main;

Using the addons in your story

For details of each ondevice addon you can see the readme:

Hide/Show storybook

Storybook on react native is a normal React Native component that can be used or hidden anywhere in your RN application based on your own logic.

You can also create a separate app just for storybook that also works as a package for your visual components. Some have opted to toggle the storybook component by using a custom option in the react native developer menu.

withStorybook wrapper

withStorybook is a wrapper function to extend your Metro config for Storybook. It accepts your existing Metro config and an object of options for how Storybook should be started and configured.

// metro.config.js
const { getDefaultConfig } = require('expo/metro-config');
const withStorybook = require('@storybook/react-native/metro/withStorybook');

const defaultConfig = getDefaultConfig(__dirname);

module.exports = withStorybook(defaultConfig, {
  enabled: true,
  // See API section below for available options
});

Options

enabled

Type: boolean, default: true

Determines whether the options specified are applied to the Metro config. This can be useful for project setups that use Metro both with and without Storybook and need to conditionally apply the options. In this example, it is made conditional using an environment variable:

// metro.config.js
const { getDefaultConfig } = require('expo/metro-config');
const withStorybook = require('@storybook/react-native/metro/withStorybook');

const defaultConfig = getDefaultConfig(__dirname);

module.exports = withStorybook(defaultConfig, {
  enabled: process.env.WITH_STORYBOOK,
  // ... other options
});

onDisabledRemoveStorybook

Type: boolean, default: false

If onDisabledRemoveStorybook true and enabled is false, the storybook package will be removed from the build. This is useful if you want to remove storybook from your production build.

useJs

Type: boolean, default: false

Generates the .storybook/storybook.requires file in JavaScript instead of TypeScript.

configPath

Type: string, default: path.resolve(process.cwd(), './.storybook')

The location of your Storybook configuration directory, which includes main.ts and other project-related files.

websockets

Type: { host: string?, port: number? }, default: undefined

If specified, create a WebSocket server on startup. This allows you to sync up multiple devices to show the same story and arg values connected to the story in the UI.

websockets.host

Type: string, default: 'localhost'

The host on which to run the WebSocket, if specified.

websockets.port

Type: number, default: 7007

The port on which to run the WebSocket, if specified.

getStorybookUI options

You can pass these parameters to getStorybookUI call in your storybook entry point:

{
    initialSelection?: string | Object (undefined)
        -- initialize storybook with a specific story.  eg: `mybutton--largebutton` or `{ kind: 'MyButton', name: 'LargeButton' }`
    storage?: Object (undefined)
        -- {getItem: (key: string) => Promise<string | null>;setItem: (key: string, value: string) => Promise<void>;}
        -- Custom storage to be used instead of AsyncStorage
    onDeviceUI?: boolean;
        -- show the ondevice ui
    enableWebsockets?: boolean;
        -- enable websockets for the storybook ui
    query?: string;
        -- query params for the websocket connection
    host?: string;
        -- host for the websocket connection
    port?: number;
        -- port for the websocket connection
    secured?: boolean;
        -- use secured websockets
    shouldPersistSelection?: boolean;
        -- store the last selected story in the device's storage
    theme: Partial<Theme>;
        -- theme for the storybook ui
}

Using stories in unit tests

Storybook provides testing utilities that allow you to reuse your stories in external test environments, such as Jest. This way you can write unit tests easier and reuse the setup which is already done in Storybook, but in your unit tests. You can find more information about it in the portable stories section.

Contributing

We welcome contributions to Storybook!

  • 📥 Pull requests and 🌟 Stars are always welcome.
  • Read our contributing guide to get started, or find us on Discord and look for the react-native channel.

Looking for a first issue to tackle?

  • We tag issues with Good First Issue when we think they are well suited for people who are new to the codebase or OSS in general.
  • Talk to us, we'll find something to suits your skills and learning interest.

Examples

Here are some example projects to help you get started

changelog

v6.5.0-rc.9

What's Changed

Full Changelog: https://github.com/storybookjs/react-native/compare/v6.5.0-rc.8...v6.5.0-rc.9

v6.5.0-rc.8

What's Changed

Full Changelog: https://github.com/storybookjs/react-native/compare/v6.5.0-rc.7...v6.5.0-rc.8

v6.5.0-rc.7

What's Changed

Full Changelog: https://github.com/storybookjs/react-native/compare/v6.5.0-rc.6...v6.5.0-rc.7

v6.5.0-rc.6

What's Changed

New Contributors

Full Changelog: https://github.com/storybookjs/react-native/compare/v6.5.0-rc.5...v6.5.0-rc.6

v6.5.0-rc.5

What's Changed

Full Changelog: https://github.com/storybookjs/react-native/compare/v6.5.0-rc.4...v6.5.0-rc.5

v6.5.0-rc.4

What's Changed

Full Changelog: https://github.com/storybookjs/react-native/compare/v6.5.0-rc.3...v6.5.0-rc.4

v6.5.0-rc.3

What's Changed

Full Changelog: https://github.com/storybookjs/react-native/compare/v6.5.0-rc.2...v6.5.0-rc.3

v6.5.0-rc.2

What's Changed

Full Changelog: https://github.com/storybookjs/react-native/compare/v6.5.0-rc.1...v6.5.0-rc.2

v6.5.0-rc.1

What's Changed

New Contributors

Full Changelog: https://github.com/storybookjs/react-native/compare/v6.5.0-rc.0...v6.5.0-rc.1

v6.5.0-rc.0

Adds template file for npx sb@next init --type react_native

Full Changelog: https://github.com/storybookjs/react-native/compare/v6.0.1-beta.12...v6.5.0-rc.0

v6.0.1-beta.12

  • auto title generation now works
  • number control doesn't crash when default is undefined
  • render function args type now correctly matches with your component props
  • Orient the OnDeviceUI correctly for RTL locales by @jonathanj

v6.0.1-beta.11

What's Changed

Breaking:

  • storybook dependencies must now be 6.5.14 and above since new fixes were included in this version that are required for this to work
  • backgrounds are now using the new config format to match the web (see below)
    parameters: {
      backgrounds: {
        default: 'warm',
        values: [
          { name: 'warm', value: 'hotpink' },
          { name: 'cool', value: 'deepskyblue' },
        ],
      },
    },

Full Changelog: https://github.com/storybookjs/react-native/compare/v6.0.1-beta.10...v6.0.1-beta.11

v6.0.1-beta.10

What's Changed

New Contributors

Full Changelog: https://github.com/storybookjs/react-native/compare/v6.0.1-beta.9...v6.0.1-beta.10

v6.0.1-beta.9

What's Changed

Big changes in this release.

this includes

  • support for the story store changes introduced in 6.4
  • compatibility with storybook v6.5
  • CSF3
  • HMR/Fast refresh now works properly!!!
  • More code re-used from storybook core apis
  • fix for a bug in the tab bar animation

Largely made possible by help from @shilman and @tmeasday on the 6.5 branch.

note: there was a temporary polyfill added to include the global document object whilst changes are made in storybook to allow for a parameterised preview and store. This shouldn't require any changes from the user and is temporary.

Breaking:

  • There is now a new peer dependency on react-dom due to some code re-use around the preview.

This should hopefully be removed soon, though it shouldn't impact your development other than adding react dom to your dev dependencies. Hopefully this is an acceptable compromise for finally having 6.4/6.5 support.

commits

Full Changelog: https://github.com/storybookjs/react-native/compare/v6.0.1-beta.8...v6.0.1-beta.9

v5.3.27

  • fix: deprecated dimensions remove listener removed

Full Changelog: https://github.com/storybookjs/react-native/compare/v5.3.26...v5.3.27

v6.0.1-beta.8

What's Changed

New Contributors

Full Changelog: https://github.com/storybookjs/react-native/compare/v6.0.1-beta.7...v6.0.1-beta.8

v6.0.1-beta.7

What's Changed

New Contributors

Full Changelog: https://github.com/storybookjs/react-native/compare/v6.0.1-beta.5...v6.0.1-beta.7

v5.3.26

note: only notes and knobs were updated in this release so there is no new version of storybook/react-native and instead only for those two packages.

What's Changed

New Contributors

Full Changelog: https://github.com/storybookjs/react-native/compare/v5.3.25...v5.3.26

6.0.1-beta.5

  • Story navigator now more closely matches web design (#326)
  • The Number range control now shows the current value (#336)

v6.0.1-beta.1

Feature

  • export preview for extendability (#312)

Fixes

  • should persist selection by default (#311)
  • better web controls (#322)

Breaking change

radios is now radio to better match the web

  • fixed inconsistent control type for 'radio' (#309)

v6.0.1-alpha.5

Features

  • you can now specify a config location and you can change the folder name #278
    • note that this folder should still contain all the same files
    • —absolute option will use absolute imports in the requires.js file
    • paths in general should work better with the watcher and get stories script
  • choosing an initial selection is now easier and is correctly typed #274

Breaking changes (since previous alpha):

  • In main.js stories are relative from the config directory and no longer add "../", this should fix absolute paths and other bugs #278
    • make sure to update your paths if you were using v6.0.1-alpha.3
  • sbn-get-stories and sbn-watcher are now sb-rn-get-stories and sb-rn-watcher so make sure to update these if you were using v6.0.1-alpha.3
  • @react-native-async-storage/async-storage is now a peer dependency and is required
  • AsyncStorage is no longer needed as an option to getStorybookUI

v6.0.1-alpha.3

  • Build now targets ES6 so that the ondeviceUI works out of the box on react-native-web 251

v6.0.1-alpha.2

  • moved storybook.requires and storybook.tsx to .storybook/ 252
  • fix for action appearing as invalid control 246
  • Improve the message shown on the Controls tab when the story has no controls configured. 254
  • fix(scripts): reduce watcher updates and fix small path bug 261

v6.0.1-alpha.1

fixes:

  • 237 adding util dependency

v6.0.1-alpha.0

Features

Many of these features come from the web storybook so you can find more info by looking at the storybook documentation.

  • New story format CSF
  • Args
  • Knobs replaced by Controls
  • ondevice addons Notes, actions and backgrounds have all been updated to work for 6.0+
  • New declarative config style
  • Auto story detection built in. Including an optional watcher.
  • Overall simplified implementation

Bug fixes

  • Much less warnings when using controls (knobs replacement) - no longer using deprecated components.
  • Promises no longer break for the entire app when using storybook.
  • Weird storylist bottom margin is now gone

Breaking Changes

  • Knobs are no longer supported, use controls instead
  • storiesOf syntax is no longer recommended and you should move to CSF
  • You now require a main.js and preview.js file to configure storybook.
  • in order to resolve issues with polyfills that caused promises to break and much more you should change your metro config to include
    • resolverMainFields: ['sbmodern', 'main'] in the resolver field

See https://github.com/storybookjs/react-native/blob/next-6.0/v6README.md for a guide to try out this alpha

v5.3.25

Includes a fallback for when theme values fail

v5.3.24

Bug fixes

  • size of radios is inconsistent with other knobs (#118)
  • type annotation for storiesOf method (#124)
  • ondevice select knob undefined value causes key error (#111)
  • reset groupId in selectStory handler (#137)
  • fix for status bar covering stories on android+expo (#88)
  • on device knobs - number knob will convert a coma to a dot (#136)
  • some minor ui fixes

v5.3.23 (September 25, 2020)

updated links for npm

v5.3.22 (September 25, 2020)

Bug Fixes

  • server addons and update all dependencies to use storybook 5.3.20 #100
  • color picker will no longer crash the app #85
  • boolean knob no longer throws a warning #70
  • modal selector no longer causes the app to freeze/crash #74

Features

  • radios knob type added #83

5.3.20-alpha.1 (August 27, 2020)

Bug Fixes

  • server addons and update all dependencies to use storybook 5.3.20 #100

5.3.20-alpha.0 (August 19, 2020)

Features

  • radios knob type added 83

Bug Fixes

  • color picker will no longer crash the app #85
  • boolean knob no longer throws a warning #70
  • modal selector no longer causes the app to freeze/crash #74