Controls Addon
The @storybook/addon-ondevice-controls
addon provides interactive controls for dynamically editing component props directly on your device. This allows you to experiment with different component states without modifying code.
Installation
npm install @storybook/addon-ondevice-controls
Add it to your addons list in .rnstorybook/main.ts
:
const main: StorybookConfig = {
addons: [
'@storybook/addon-ondevice-controls',
// ... other addons
],
};
Supported Control Types
The React Native controls addon supports 13 different control types optimized for mobile interfaces:
Text Input Controls
text
Basic text input control for string values.
export default {
component: MyComponent,
argTypes: {
name: {
control: { type: 'text' },
},
},
};
number
Numeric input with optional range slider functionality.
export default {
component: MyComponent,
argTypes: {
// Basic number input
quantity: {
control: { type: 'number' },
},
// Range slider
opacity: {
control: {
type: 'number',
min: 0,
max: 1,
step: 0.1,
range: true, // Displays as slider
},
},
},
};
range
Dedicated slider control for numeric ranges.
export default {
component: MyComponent,
argTypes: {
volume: {
control: {
type: 'range',
min: 0,
max: 100,
step: 5,
},
},
},
};
Boolean Controls
boolean
Toggle switch using React Native's native Switch component.
export default {
component: MyComponent,
argTypes: {
isEnabled: {
control: { type: 'boolean' },
},
},
};
Selection Controls
select
Dropdown selection with support for custom labels.
export default {
component: MyComponent,
argTypes: {
size: {
options: ['small', 'medium', 'large'],
control: { type: 'select' },
},
// With custom labels
fruit: {
options: ['apple', 'banana', 'cherry'],
control: {
type: 'select',
labels: {
apple: 'Apple 🍎',
banana: 'Banana 🍌',
cherry: 'Cherry 🍒',
},
},
},
},
};
radio
Radio button selection for exclusive choices.
export default {
component: MyComponent,
argTypes: {
alignment: {
options: ['left', 'center', 'right'],
control: { type: 'radio' },
},
},
};
inline-radio
Inline radio button layout for horizontal display.
export default {
component: MyComponent,
argTypes: {
theme: {
options: ['light', 'dark'],
control: {
type: 'inline-radio', // or type: 'radio' with isInline: true
},
},
},
};
multi-select
Multiple selection control returning an array of values.
export default {
component: MyComponent,
argTypes: {
features: {
options: ['feature1', 'feature2', 'feature3'],
control: { type: 'multi-select' },
},
},
};
Color Controls
color
Full-featured color picker with mobile-optimized interface.
export default {
component: MyComponent,
argTypes: {
backgroundColor: {
control: { type: 'color' },
},
textColor: {
control: { type: 'color' },
},
},
};
Date Controls
date
Date and time picker with native mobile interfaces.
export default {
component: MyComponent,
argTypes: {
createdAt: {
control: { type: 'date' },
},
},
};
Dependencies: Requires @react-native-community/datetimepicker
for React Native projects.
Complex Data Controls
array
Array input control that parses comma-separated values.
export default {
component: MyComponent,
argTypes: {
tags: {
control: {
type: 'array',
separator: ',', // Optional: default is comma
},
},
},
};
object
JSON object editor with syntax validation.
export default {
component: MyComponent,
argTypes: {
config: {
control: { type: 'object' },
},
user: {
control: { type: 'object' },
},
},
};
Auto-Detection
Controls can be automatically inferred from your component's prop types:
// TypeScript component
interface ButtonProps {
label: string; // → text control
disabled: boolean; // → boolean control
size: 'sm' | 'md' | 'lg'; // → select control
count: number; // → number control
}
// Controls are automatically generated based on prop types
export default {
component: Button,
// No argTypes needed - controls auto-detected!
};
Story Examples
Complete Story with Multiple Control Types
import type { Meta, StoryObj } from '@storybook/react';
import { MyComponent } from './MyComponent';
const meta = {
component: MyComponent,
argTypes: {
// Text
title: { control: { type: 'text' } },
// Numbers and ranges
fontSize: {
control: { type: 'range', min: 12, max: 24, step: 1 },
},
opacity: {
control: { type: 'number', min: 0, max: 1, step: 0.1 },
},
// Boolean
isVisible: { control: { type: 'boolean' } },
// Selection
variant: {
options: ['primary', 'secondary', 'danger'],
control: { type: 'select' },
},
// Color
backgroundColor: { control: { type: 'color' } },
// Array
tags: { control: { type: 'array' } },
// Object
config: { control: { type: 'object' } },
// Date
lastUpdated: { control: { type: 'date' } },
},
} satisfies Meta<typeof MyComponent>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Interactive: Story = {
args: {
title: 'Sample Component',
fontSize: 16,
opacity: 1,
isVisible: true,
variant: 'primary',
backgroundColor: '#007AFF',
tags: ['react', 'native'],
config: { theme: 'light', animations: true },
lastUpdated: new Date(),
},
};
Platform Differences
Mobile (React Native)
- Color picker: Modal-based interface with triangle and holo color pickers
- Date picker: Separate date and time selection modals
- Select: Modal-based selection interface
- Range: Native slider component (requires
@react-native-community/slider
)
Web (React Native Web)
- Color picker: Native HTML color input
- Date picker: Native HTML datetime-local input
- Select: Native HTML select element
Advanced Configuration
Conditional Controls
export default {
component: MyComponent,
argTypes: {
type: {
options: ['button', 'link'],
control: { type: 'select' },
},
// Only show URL control when type is 'link'
url: {
control: { type: 'text' },
if: { arg: 'type', eq: 'link' },
},
},
};
Best Practices
- Use descriptive labels: Provide clear labels for select and radio options
- Set sensible ranges: Define appropriate min/max values for numeric controls
- Provide default values: Set reasonable defaults in story args
- Test with real data: Use realistic data in your control examples
Dependencies
Some controls require additional React Native dependencies:
- Range controls:
@react-native-community/slider
- Date controls:
@react-native-community/datetimepicker
Install these as needed:
npm install @react-native-community/slider @react-native-community/datetimepicker
Troubleshooting
Controls Not Appearing
- Ensure the addon is installed and added to
main.ts
- Check that
argTypes
are properly configured - Verify component props are typed correctly for auto-detection
Date Picker Issues
- Install
@react-native-community/datetimepicker
- For iOS: Follow platform-specific setup instructions
- Ensure proper date value formatting in args
Slider Not Working
- Install
@react-native-community/slider
- Set
range: true
or usetype: 'range'
in control config - Verify min/max/step values are valid