Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
@storybook/addon-controls
Advanced tools
Interact with component inputs dynamically in the Storybook UI
The @storybook/addon-controls package allows developers to interact with component inputs dynamically within the Storybook UI. It provides a way to edit props, slots, styles, and other arguments of the components being tested in real-time. This addon generates a user interface for tweaking these inputs without needing to write any additional code.
Dynamic Props Editing
Allows users to dynamically edit the props of a component from within the Storybook UI. The code sample shows how to set up controls for a Button component, including a color picker for the backgroundColor prop and an action logger for the onClick event.
export default {
title: 'Button',
component: Button,
argTypes: {
backgroundColor: { control: 'color' },
onClick: { action: 'clicked' }
},
};
const Template = (args) => <Button {...args} />;
export const Primary = Template.bind({});
Primary.args = {
primary: true,
label: 'Button',
};
Custom Controls
Enables the creation of custom controls for component arguments, such as dropdowns, checkboxes, and more. The code sample demonstrates how to create a select control for the 'size' prop of an Input component.
export default {
title: 'Form/Input',
component: Input,
argTypes: {
size: {
control: {
type: 'select',
options: ['small', 'medium', 'large']
}
}
}
};
const Template = (args) => <Input {...args} />;
export const Medium = Template.bind({});
Medium.args = {
size: 'medium',
placeholder: 'Type here...'
};
Live Editing of Args
Provides a way to live edit the 'args' of a story, which are the arguments that get passed to the component being rendered. The code sample shows a text control for the 'content' prop of a Panel component.
export default {
title: 'Dashboard/Panel',
component: Panel,
argTypes: {
content: { control: 'text' }
}
};
const Template = (args) => <Panel {...args} />;
export const DefaultPanel = Template.bind({});
DefaultPanel.args = {
content: 'Default content',
};
This package is a predecessor to @storybook/addon-controls and offers similar functionality for changing props and other inputs of components within Storybook. However, addon-controls is more integrated with Storybook's Component Story Format (CSF) and offers a better developer experience with less boilerplate code.
While not providing the same UI for editing component inputs, @storybook/addon-actions allows developers to log and monitor events that occur on interactive components within Storybook. It complements the functionality of addon-controls by providing insight into how components respond to user actions.
This addon allows users to change the background colors behind their components within the Storybook preview. It is different from addon-controls but offers a complementary feature that enhances the visual testing capabilities of Storybook.
Storybook Controls gives you a graphical UI to interact with a component's arguments dynamically, without needing to code. It creates an addon panel next to your component examples ("stories"), so you can edit them live.
Controls is part of essentials and so is installed in all new Storybooks by default. If you need to add it to your Storybook, you can run:
npm i -D @storybook/addon-controls
Then, add following content to .storybook/main.js
:
export default {
addons: ['@storybook/addon-controls'],
};
The usage is documented in the documentation.
Addon-knobs is one of Storybook's most popular addons with over 1M weekly downloads, so we know lots of users will be affected by this change. Knobs is also a mature addon, with various options that are not available in addon-controls.
Therefore, rather than deprecating addon-knobs immediately, we will continue to release knobs with the Storybook core distribution until 7.0. This will give us time to improve Controls based on user feedback, and also give knobs users ample time to migrate.
If you are somehow tied to knobs or prefer the knobs interface, we are happy to take on maintainers for the knobs project. If this interests you, please get in touch with us in the #contributing
Discord channel.
If you're already using Storybook Knobs you should consider migrating to Controls.
You're probably using it for something that can be satisfied by one of the cases described above.
Let's walk through two examples: migrating knobs to auto-generated args and knobs to custom args.
First, let's consider a knobs version of a basic story that fills in the props for a component:
import { text } from '@storybook/addon-knobs';
import { Button } from './Button';
export const Basic = () => <Button label={text('Label', 'hello')} />;
This fills in the Button's label based on a knob, which is exactly the auto-generated use case above. So we can rewrite it using auto-generated args:
export const Basic = (args) => <Button {...args} />;
Basic.args = { label: 'hello' };
Similarly, we can also consider a story that uses knob inputs to change its behavior:
import { number, text } from '@storybook/addon-knobs';
export const Reflow = () => {
const count = number('Count', 10, { min: 0, max: 100, range: true });
const label = text('Label', 'reflow');
return (
<>
{[...Array(count)].map((_, i) => (
<Button key={i} label={`button ${i}`} />
))}
</>
);
};
And again, as above, this can be rewritten using fully custom args:
export const Reflow = ({ count, label, ...args }) => (
<>
{[...Array(count)].map((_, i) => (
<Button key={i} label={`${label} ${i}`} {...args} />
))}
</>
);
Reflow.args = {
count: 3,
label: 'reflow',
};
Reflow.argTypes = {
count: {
control: {
type: 'range',
min: 0,
max: 20,
},
},
};
There are a few known cases where controls can't be auto-generated:
With a little manual work you can still use controls in such cases. Consider the following example:
import { Button } from 'some-external-library';
export default {
title: 'Button',
argTypes: {
label: { control: 'text' },
borderWidth: { control: { type: 'number', min: 0, max: 10 } },
},
};
export const Basic = (args) => <Button {...args} />;
Basic.args = {
label: 'hello',
borderWidth: 1,
};
The argTypes
annotation (which can also be applied to individual stories if needed), gives Storybook the hints it needs to generate controls in these unsupported cases. See control annotations for a full list of control types.
It's also possible that your Storybook is misconfigured. If you think this might be the case, please search through Storybook's Github issues, and file a new issue if you don't find one that matches your use case.
The argTypes
annotation can be used to hide controls for a particular row, or even hide rows.
Suppose you have a Button
component with borderWidth
and label
properties (auto-generated or otherwise) and you want to hide the borderWidth
row completely and disable controls for the label
row on a specific story. Here's how you'd do that:
import { Button } from 'button';
export default {
title: 'Button',
component: Button,
};
export const CustomControls = (args) => <Button {...args} />;
CustomControls.argTypes = {
borderWidth: { table: { disable: true } },
label: { control: { disable: true } },
};
Like story parameters, args
and argTypes
annotations are hierarchically merged, so story-level annotations overwrite component-level annotations.
When importing stories from your CSF file into MDX, controls will work the same way. See the documentation for examples.
FAQs
Interact with component inputs dynamically in the Storybook UI
The npm package @storybook/addon-controls receives a total of 4,684,205 weekly downloads. As such, @storybook/addon-controls popularity was classified as popular.
We found that @storybook/addon-controls demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 12 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.