Configuration
main.ts
The main.ts
file is your primary configuration entry point, located in the .storybook
directory.
import { StorybookConfig } from '@storybook/react-native';
const main: StorybookConfig = {
stories: [
// Simple glob pattern
'../components/**/*.stories.?(ts|tsx|js|jsx)',
// Directory configuration with title prefix
{
directory: '../packages/ui',
titlePrefix: 'UI',
files: '**/*.stories.?(ts|tsx|js|jsx)',
},
],
addons: [
'@storybook/addon-ondevice-controls',
'@storybook/addon-ondevice-backgrounds',
'@storybook/addon-ondevice-actions',
'@storybook/addon-ondevice-notes',
],
};
export default main;
Options
stories
: Array of story patterns or configuration objectsdirectory
: Base directory for storiestitlePrefix
: Optional prefix for story titlesfiles
: Glob pattern for story files
addons
: Array of addon packages to includereactNative.playFn
: Enable/disable story play functions
preview.tsx
The preview.tsx
file configures the story rendering environment and global parameters.
import { Preview } from '@storybook/react';
import { View } from 'react-native';
import { withBackgrounds } from '@storybook/addon-ondevice-backgrounds';
const preview: Preview = {
decorators: [
// Global wrapper for all stories
(Story) => (
<View style={{ padding: 8 }}>
<Story />
</View>
),
// backgrounds addon decorator
withBackgrounds,
],
parameters: {
// story sorting configuration, should only be configured in preview file.
options: {
storySort: {
method: 'alphabetical',
includeNames: true,
order: ['Components', 'Examples'],
},
},
// UI Configuration
hideFullScreenButton: false,
noSafeArea: false,
// Background Configuration
backgrounds: {
default: 'light',
values: [
{ name: 'light', value: 'white' },
{ name: 'dark', value: '#333' },
],
},
// your own parameters
my_param: 'anything',
},
};
export default preview;
Notable Parameters
Other than story sort the other parameters can be overwritten per story.
parameters.options.storySort
: Story sorting configurationparameters.hideFullScreenButton
: Toggle fullscreen button visibilityparameters.noSafeArea
: Disable safe area insetsparameters.backgrounds
: Background addon configuration
index.tsx
The entry point file configures the Storybook UI and runtime behavior.
import { view } from './storybook.requires';
import AsyncStorage from '@react-native-async-storage/async-storage';
const StorybookUIRoot = view.getStorybookUI({
// UI Configuration
onDeviceUI: true,
shouldPersistSelection: true,
// Theme Customization
theme: {
// theme documentation coming soon, for now use types to understand the available options
},
// Story Selection
initialSelection: {
kind: 'Components/Button',
name: 'Primary',
},
// Storage Configuration
storage: {
getItem: AsyncStorage.getItem,
setItem: AsyncStorage.setItem,
},
// Websocket Options
enableWebsockets: false,
host: 'localhost',
port: 7007,
secured: false,
query: '',
});
export default StorybookUIRoot;
Available Options
-
UI Options
onDeviceUI
: Enable/disable on-device UI (default: true)shouldPersistSelection
: Persist last viewed story (default: true)
-
Theme Options
theme
: Customize UI theme and branding
-
Story Selection
initialSelection
: Set initial story to display- String format:
'kind--story'
- Object format:
{ kind: string, name: string }
- String format:
-
Storage Options
storage
: Implementation for story persistencegetItem
: Function to retrieve stored valuessetItem
: Function to store values
-
Websocket Options
enableWebsockets
: Enable remote control (default: false)host
: Websocket host (default: 'localhost')port
: Websocket port (default: 7007)secured
: Use WSS protocol (default: false)query
: Additional query parameters
Metro Configuration
The metro.config.js
file needs to be wrapped with the withStorybook
function to enable Storybook features and auto-generation of required files. The wrapper works without any options as it has sensible defaults.
const { getDefaultConfig } = require('expo/metro-config');
const withStorybook = require('@storybook/react-native/metro/withStorybook');
const config = getDefaultConfig(__dirname);
module.exports = withStorybook(config, {
// Optional configuration object - all options have defaults and can be omitted like withStorybook(config)
enabled: true, // Enable/disable Storybook (defaults to true)
configPath: './.rnstorybook', // Path to Storybook config folder (defaults to ./.rnstorybook)
useJs: false, // Use JS instead of TS for config files (defaults to false)
onDisabledRemoveStorybook: false, // Remove Storybook from bundle when disabled (defaults to false)
websockets: {
port: 7007, // WebSocket server port (defaults to 7007)
host: 'localhost', // WebSocket server host (defaults to localhost)
},
});
Important Notes About Disabling Storybook
The enabled
and onDisabledRemoveStorybook
options only affect how Metro bundles Storybook:
- When
enabled: false
, Metro won't generate thestorybook.requires
file - When
enabled: false
andonDisabledRemoveStorybook: true
, Metro will also remove Storybook from your bundle
However, you must also ensure your app doesn't render the Storybook UI component when Storybook is disabled. This typically means conditionally rendering Storybook based on the same condition you use for the enabled
option:
// Example of coordinating metro config with UI rendering
const STORYBOOK_ENABLED = process.env.STORYBOOK_ENABLED === 'true';
// metro.config.js
module.exports = withStorybook(config, { enabled: STORYBOOK_ENABLED });
// App.tsx
export default function App() {
if (STORYBOOK_ENABLED) {
return <StorybookUIRoot />;
}
return <MainApp />;
}
storybook.requires.ts
This is an auto-generated file created by the build process when you use withStorybook
in your metro config. Unlike the other configuration files, you should never modify this file directly as it's regenerated during builds.
The file handles:
- Loading stories based on patterns in
main.ts
- Registering configured addons
- Setting up preview configuration
- Managing global Storybook state
- Hot module reloading support
Here's a simplified example of what gets generated:
import { start, updateView } from '@storybook/react-native';
// Addon registration from main.ts
import '@storybook/addon-ondevice-controls/register';
import '@storybook/addon-ondevice-backgrounds/register';
// Story loading based on main.ts patterns
const normalizedStories = [
{
directory: './components',
files: '**/*.stories.?(ts|tsx|js|jsx)',
importPathMatcher: /\.stories\.[tj]sx?$/,
req: require.context('../components', true, /\.stories\.[tj]sx?$/),
},
];
// Preview configuration
const annotations = [require('./preview'), require('@storybook/react-native/preview')];
// Global state management
if (!global.view) {
global.view = start({
annotations,
storyEntries: normalizedStories,
});
} else {
updateView(global.view, annotations, normalizedStories);
}
export const view = global.view;
The file is essential for Storybook to work but requires no manual setup - it's handled automatically by the build process through the withStorybook
metro configuration.