The Backgrounds Addon allows you to visualize your components against different background colors. This is essential for testing component appearance in various contexts, such as light and dark themes, or ensuring proper contrast.
Installation
Install the addon
npm install -D @storybook/addon-ondevice-backgrounds
Register the addon
Add the addon to your .rnstorybook/main.ts configuration: import type { StorybookConfig } from '@storybook/react-native' ;
const main : StorybookConfig = {
addons: [ '@storybook/addon-ondevice-backgrounds' ],
};
export default main ;
Basic Usage
Define background options in your story’s parameters:
import type { Meta , StoryObj } from '@storybook/react-native' ;
import { Text , StyleSheet } from 'react-native' ;
const Card = () => (
< Text style = { styles . text } > Change background via Addons → Background </ Text >
);
const styles = StyleSheet . create ({
text: { color: 'black' },
});
const meta = {
component: Card ,
parameters: {
backgrounds: {
options: {
warm: { name: 'Warm' , value: 'hotpink' },
cool: { name: 'Cool' , value: 'deepskyblue' },
white: { name: 'White' , value: 'white' },
black: { name: 'Black' , value: 'black' },
},
},
},
} satisfies Meta < typeof Card >;
export default meta ;
type Story = StoryObj < typeof meta >;
export const Basic : Story = {};
Users can now select from the defined backgrounds using the Backgrounds panel in the Storybook UI.
Setting a Default Background
Specify which background should be active by default using globals:
import type { Meta , StoryObj } from '@storybook/react-native' ;
import { Card } from './Card' ;
const meta = {
component: Card ,
parameters: {
backgrounds: {
options: {
light: { name: 'Light' , value: '#ffffff' },
dark: { name: 'Dark' , value: '#000000' },
},
},
},
} satisfies Meta < typeof Card >;
export default meta ;
type Story = StoryObj < typeof meta >;
export const OnDarkBackground : Story = {
globals: {
backgrounds: { value: 'dark' },
},
};
Background Configuration
Options Object
The options object maps background keys to their display configuration:
parameters : {
backgrounds : {
options : {
// Key can be any string
light : {
name : 'Light Theme' , // Display name in UI
value : '#f8f9fa' // CSS color value
},
dark : {
name : 'Dark Theme' ,
value : '#1a1a1a'
},
},
},
}
Color Values
Backgrounds support all standard CSS color formats:
parameters : {
backgrounds : {
options : {
// Named colors
white : { name : 'White' , value : 'white' },
// Hex colors
gray : { name : 'Gray' , value : '#808080' },
// RGB
blue : { name : 'Blue' , value : 'rgb(0, 123, 255)' },
// RGBA (with transparency)
transparent : { name : 'Semi-transparent' , value : 'rgba(0, 0, 0, 0.5)' },
// HSL
purple : { name : 'Purple' , value : 'hsl(270, 100%, 50%)' },
},
},
}
Common Patterns
Light and Dark Themes
Test components in both light and dark modes:
import type { Meta , StoryObj } from '@storybook/react-native' ;
import { ThemedCard } from './ThemedCard' ;
const meta = {
component: ThemedCard ,
parameters: {
backgrounds: {
options: {
light: { name: 'Light Mode' , value: '#ffffff' },
dark: { name: 'Dark Mode' , value: '#121212' },
},
},
},
} satisfies Meta < typeof ThemedCard >;
export default meta ;
type Story = StoryObj < typeof meta >;
export const LightTheme : Story = {
globals: {
backgrounds: { value: 'light' },
},
};
export const DarkTheme : Story = {
globals: {
backgrounds: { value: 'dark' },
},
};
Brand Colors
Test components against your brand’s color palette:
import type { Meta , StoryObj } from '@storybook/react-native' ;
import { Logo } from './Logo' ;
const meta = {
component: Logo ,
parameters: {
backgrounds: {
options: {
brand: { name: 'Brand Primary' , value: '#0066cc' },
brandDark: { name: 'Brand Dark' , value: '#004080' },
neutral: { name: 'Neutral' , value: '#f5f5f5' },
white: { name: 'White' , value: '#ffffff' },
},
},
},
} satisfies Meta < typeof Logo >;
export default meta ;
Accessibility Testing
Test contrast ratios by viewing components on different backgrounds:
AccessibleButton.stories.tsx
import type { Meta , StoryObj } from '@storybook/react-native' ;
import { Button } from './Button' ;
const meta = {
component: Button ,
parameters: {
backgrounds: {
options: {
white: { name: 'White (#fff)' , value: '#ffffff' },
lightGray: { name: 'Light Gray (#f0f0f0)' , value: '#f0f0f0' },
mediumGray: { name: 'Medium Gray (#888)' , value: '#888888' },
darkGray: { name: 'Dark Gray (#333)' , value: '#333333' },
black: { name: 'Black (#000)' , value: '#000000' },
},
},
},
} satisfies Meta < typeof Button >;
export default meta ;
Global Configuration
Define backgrounds globally in .rnstorybook/preview.tsx to apply them to all stories:
import type { Preview } from '@storybook/react-native' ;
const preview : Preview = {
parameters: {
backgrounds: {
options: {
light: { name: 'Light' , value: '#ffffff' },
dark: { name: 'Dark' , value: '#000000' },
gray: { name: 'Gray' , value: '#f0f0f0' },
},
},
},
};
export default preview ;
Individual stories can override or extend these global backgrounds.
Overriding Per Story
Override global backgrounds for specific stories:
export const CustomBackgrounds : Story = {
parameters: {
backgrounds: {
// Completely replace global backgrounds
options: {
custom1: { name: 'Custom 1' , value: '#ff6b6b' },
custom2: { name: 'Custom 2' , value: '#4ecdc4' },
},
},
},
};
Disabling Backgrounds
Disable the backgrounds addon for specific stories:
export const NoBackgrounds : Story = {
parameters: {
backgrounds: {
disable: true ,
},
},
};
Complete Example
Here’s a comprehensive example:
BackgroundExample.stories.tsx
import type { Meta , StoryObj } from '@storybook/react-native' ;
import { Text , StyleSheet , View } from 'react-native' ;
const BackgroundDemo = () => (
< View style = { styles . container } >
< Text style = { styles . text } > Try changing the background! </ Text >
< Text style = { styles . subtext } > Use Addons → Background to switch themes </ Text >
</ View >
);
const styles = StyleSheet . create ({
container: {
padding: 20 ,
},
text: {
fontSize: 18 ,
fontWeight: 'bold' ,
color: '#333' ,
},
subtext: {
fontSize: 14 ,
color: '#666' ,
marginTop: 8 ,
},
});
const meta = {
component: BackgroundDemo ,
parameters: {
backgrounds: {
options: {
warm: { name: 'Warm' , value: 'hotpink' },
cool: { name: 'Cool' , value: 'deepskyblue' },
white: { name: 'White' , value: 'white' },
black: { name: 'Black' , value: 'black' },
},
},
},
} satisfies Meta < typeof BackgroundDemo >;
export default meta ;
type Story = StoryObj < typeof meta >;
export const Default : Story = {};
export const OnWarmBackground : Story = {
globals: {
backgrounds: { value: 'warm' },
},
};
export const OnCoolBackground : Story = {
globals: {
backgrounds: { value: 'cool' },
},
};
export const OnDarkBackground : Story = {
globals: {
backgrounds: { value: 'black' },
},
parameters: {
notes: 'Testing component visibility on dark backgrounds' ,
},
};
TypeScript Support
The Backgrounds addon is fully typed:
import type { Meta } from '@storybook/react-native' ;
interface BackgroundOption {
name : string ;
value : string ;
}
interface BackgroundsParameter {
options ?: Record < string , BackgroundOption >;
disable ?: boolean ;
}
const meta = {
parameters: {
backgrounds: {
options: {
light: { name: 'Light' , value: '#fff' },
},
} satisfies BackgroundsParameter ,
},
} satisfies Meta ;
Differences from Web Backgrounds
The React Native Backgrounds addon uses a slightly different API than the web version:
backgrounds : {
default : 'light' ,
values : [
{ name: 'light' , value: '#fff' },
{ name: 'dark' , value: '#000' },
],
}
backgrounds : {
options : {
light : { name : 'Light' , value : '#fff' },
dark : { name : 'Dark' , value : '#000' },
},
}
The web Storybook documentation may use the values array format, but the React Native addon uses the options object format shown above.
Controls Addon Test component props with different backgrounds
Web Backgrounds Docs Official web backgrounds documentation (API differs)