
Storybook Addon Range Controls
Storybook Addon Range Controls lets you discover layout issues by adjusting story args with sliders.

Motivation
Originally, I used Storybook’s built-in argTypes
with type: "range"
sliders to check design variations.
This was great for interactively testing data growth and reduction.
However, setting it up often required extra boilerplate code.
For simple primitives like strings and numbers, it wasn’t a big issue, but for more complex structures—such as arrays of nested objects (e.g., tags inside a card)—I found myself writing the same setup code repeatedly.
That repetitive overhead was what motivated me to create this addon:
a simpler way to configure sliders for strings, numbers, image, and arrays to stress-test UIs more easily.
Installation
npm install --save-dev storybook-addon-range-controls
Then, register it as an addon in .storybook/main.js
.
import type { StorybookConfig } from "@storybook/react";
const config = {
addons: [
"@storybook/addon-docs",
"storybook-addon-range-controls",
],
};
export default config;
Usage
The primary way to use this addon is to define the range
parameter. You can do this the
component level, as below, to affect all stories in the file, or you can do it for a single story.
import type { Meta } from "@storybook/your-framework";
import { Card } from "./Card";
const meta: Meta<typeof Card> = {
component: Card,
parameters: {
range: {
},
},
};
export default meta;
API
This addon contributes a range
parameter to Storybook, defined using PropConfig objects.
export type StringPropConfig = {
type: "string";
min?: number;
max?: number;
step?: number;
defaultChar?: string;
};
export type NumberPropConfig = {
type: "number";
min?: number;
max?: number;
step?: number;
};
export type ArrayPropConfig = {
type: "array";
min?: number;
max?: number;
step?: number;
items?: PropConfig;
defaultItem?: any | ((index: number) => any);
};
export type ImagePropConfig = {
type: "image";
width?: {
min?: number;
default?: number;
max?: number;
step?: number;
};
height?: {
min?: number;
default?: number;
max?: number;
step?: number;
};
src?: ({ width, height }: { width?: number; height?: number }) => string;
};
export type BooleanPropConfig = {
type: "boolean";
};
export type EnumPropConfig = {
type: "enum";
selection?: "single" | "multiple";
options?: string[] | number[] | { label: string; value: any }[];
};
export type ObjectPropConfig = {
type: "object";
} & {
[K in string as K extends "type" ? never : K]: PropConfig;
};
export type PropConfig =
| StringPropConfig
| NumberPropConfig
| ArrayPropConfig
| ImagePropConfig
| BooleanPropConfig
| EnumPropConfig
| ObjectPropConfig;
export type PropConfigs = {
[key: string]: PropConfig;
};
Configuration
The range
parameter accepts the following configuration options.
string | Adjust string length via a slider | min , max , step , defaultChar |
number | Adjust a numeric value via a slider | min , max , step |
array | Adjust array length via a slider | min , max , step , items , defaultItem |
image | Adjust image width/height via a slider | width , height , src |
enum | Enum with single or multiple selection | selection , options |
boolean | Toggle true/false | — |
object | Nested fields, each defined by its own type | — |
Common options (string
, number
, array
)
min | number | 0 | Minimum value of the range |
max | number | 100 | Maximum value of the range |
step | number | 1 | Step interval |
string
only
defaultChar | string | "x" | Character used when padding length via slider |
array
only
items | PropConfig | Definition of element type. |
defaultItem | any | (index: number) => any | Default element value. Can be fixed or generated by a function. |
image
only
width | { min, default, max, step } | Slider settings for width. Defaults: default=300, min=50, max=800, step=1 |
height | { min, default, max, step } | Slider settings for height. Defaults: default=200, min=50, max=800, step=1 |
src | ({ width, height }) => string | Custom URL generator. Defaults to https://placehold.co/{width}x{height} |
enum
only
selection | "single" | "multiple" | Single or multiple selection |
options | string[] | number[] | { label: string; value: any }[] | List of options. Supports arrays of label/value pairs |
object
only
Define nested fields, each with its own type
:
{
type: "object",
name: { type: "string" },
price: { type: "number" }
}
Examples
Configure range
on a story (or per-file) to control strings, numbers, arrays, enums, booleans, and nested objects with interactive controls.
import type { Meta } from "@storybook/your-framework";
import { Card } from "./Card";
const meta: Meta<typeof Card> = {
component: Card,
parameters: {
range: {
title: { type: "string", min: 0, max: 50, step: 5 },
subtitle: { type: "string", min: 0, max: 30, step: 1, defaultChar: "·" },
likes: { type: "number", min: 0, max: 999, step: 1 },
featured: { type: "boolean" },
tags: {
type: "array",
min: 0,
max: 5,
step: 1,
items: { type: "string" },
defaultItem: (i: number) => `tag-${i + 1}`,
},
users: {
type: "array",
min: 1,
max: 3,
items: {
type: "object",
name: { type: "string", min: 0, max: 20 },
age: { type: "number", min: 0, max: 120, step: 1 },
},
defaultItem: { name: "Alice", age: 20 },
},
thumbnail: {
type: "image",
width: { min: 100, default: 300, max: 600, step: 10 },
height: { min: 100, default: 200, max: 400, step: 10 },
src: ({ width, height }) =>
`https://picsum.photos/${width}/${height}?random=1`,
},
size: {
type: "enum",
selection: "single",
options: ["sm", "md", "lg"],
},
colors: {
type: "enum",
selection: "multiple",
options: [
{ label: "Red", value: "#f00" },
{ label: "Green", value: "#0f0" },
{ label: "Blue", value: "#00f" },
],
},
product: {
type: "object",
name: { type: "string" },
price: { type: "number", min: 0, max: 1000, step: 10 },
specs: {
type: "object",
weight: { type: "number", min: 0, max: 5000, step: 50 },
},
},
},
},
};
export default meta;