Use Storybook argTypes to Force the Right Control for Each Prop
Configure Storybook Controls with argTypes so props render as select, color, or range inputs instead of free-text fields.
05 Sept 2025, 23:27 UTC

Problem: Storybook guesses the wrong input for your props
When you add a component to Storybook, the Controls panel tries to infer the right input for each prop. A string prop becomes a free-text field, even when the component only accepts "small", "medium", or "large". Designers and QA can type invalid values, and you still have to write separate stories to test every combination.
Useful takeaway: define argTypes in your story or component default export to override Storybook's automatic inference. You can map a prop to a select, color, range, date, or object control, and bind event props to the action logger. args set the starting value; argTypes describe how Storybook should render and validate the control. This applies to Storybook 6.x through 8.x.
Worked configuration: Button story with explicit controls
Assume a React Button component that accepts size, variant, accentColor, fontSize, and onClick. Create or edit Button.stories.js in your component folder:
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Button } from './Button';
export default {
title: 'Design System/Button',
component: Button,
argTypes: {
size: {
control: { type: 'select', options: ['small', 'medium', 'large'] },
description: 'Choose a predefined size. Free text is not accepted by the component.'
},
variant: {
control: { type: 'radio', options: ['primary', 'secondary', 'ghost'] }
},
accentColor: {
control: { type: 'color' }
},
fontSize: {
control: { type: 'range', min: 12, max: 32, step: 2 }
},
onClick: {
action: 'clicked',
description: 'Logs click events in the Actions panel.'
}
},
args: {
size: 'medium',
variant: 'primary',
fontSize: 16
}
} as ComponentMeta;
const Template: ComponentStory = (args) => ;
export const Default = Template.bind({});
Default.args = { label: 'Save changes' };
Run Storybook from the project root:
npm run storybook
No elevated permissions are required. The command starts the Storybook dev server, usually on localhost:6006. Open the story, then open the Controls panel. You should see a dropdown for size, radio buttons for variant, a color picker for accentColor, and a slider for fontSize. Changing any value updates the args and re-renders the button immediately. Clicking the button adds an entry to the Actions panel.
Where argTypes applies and how precedence works
You can define argTypes in three places:
- Per story file: in the default export, as shown above. This is the most common location.
- Per story: directly on a named story object, which overrides the component-level defaults for that story only.
- Globally: in
.storybook/preview.jsunder the component'sargTypeskey, applying to every story that uses that component.
Per-story settings take precedence over component-level defaults. If you omit argTypes entirely, Storybook infers controls from PropTypes, TypeScript types, or runtime values.
Verification checklist
- Start Storybook locally and open the target story.
- Open the Controls panel and confirm the prop renders as the control type you declared, not a plain text input.
- Change the control value and confirm the component re-renders with the new prop.
- For event props such as
onClick, interact with the component and confirm an entry appears in the Actions panel. - Temporarily remove the
argTypesblock, restart Storybook, and confirm Storybook falls back to automatic inference or a plain text input for the same prop.
Limits and common mistakes
- Static options only:
selectandradiooptions must be static arrays. You cannot compute options dynamically insideargTypes. - Inference gaps: Storybook may fail to infer controls for TypeScript union types, generics, or deeply nested objects. In those cases, explicit
argTypesis required. - No persistence: Values changed in the Controls panel do not survive a reload. Commit the desired values to
argsin the story file if you want them saved. - Object control performance: A large or frequently changing object control can slow down the Canvas. Prefer primitive controls or break nested data into separate props.
- Confusing args with argTypes:
argsset initial values.argTypesdescribe control behavior. Settingargs.sizedoes not create a dropdown; you still needargTypes.size.control.
Diagnostic decision: use argTypes or let Storybook infer?
| Situation | Recommended approach |
|---|---|
| Prop accepts a fixed set of string values | Use argTypes with select or radio and static options. |
| Prop is a color or numeric range | Use color or range with min, max, and step. |
Prop is a callback such as onClick | Use action in argTypes and verify in the Actions panel. |
| Simple string or boolean with no constraints | Let Storybook infer automatically; add argTypes only if the inferred control is wrong. |
| Complex nested object | Use object control cautiously, or flatten the prop into primitives. |
Reverting the change
This change only modifies Storybook configuration files. To revert, delete the argTypes block from the story file or .storybook/preview.js and restart Storybook. No database or build artifacts are affected.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.