I am new to the storybook. When I go through the documentation and videos about the storybook I read about knobs Addon. Knobs addon and control looks similar. What is the difference between those two things?
Controls were introduced with Storybook version 6. They replace knobs for most of the use cases. However, there may be some edge cases were you still want to use knobs for dynamic values. For example, see this Github discussion on this topic: https://github.com/storybookjs/storybook/issues/11984
controls addon is a companion to the docs addon so it interfaces with the ArgsTable which by itself is designed to automatically extract your components' propTypes & defaultProps (although I found this not to work)
So, with Knobs you define each prop (which you wish to be dynamic) yourself, manually, and this requires some more manual sync when your component changes and also more work, and also Knobs variables definitions might be scattered all across your story's file, where controls are all defined in one place, though the same "order" can also be done with Knobs, it does not enforces it (for good reasons).
If you want to have an interactive propTypes documentation for your components, then I suggest using controls with addon-docs, and I've been using knobs for years, but that's it, it's time to upgrade.
If, for some reason, your component's propTypes where not auto-detected (in the story) then you can define then (with controls) like so:
import Alert from './';
export default {
title: 'General/Alert',
component: Alert,
parameters: {
controls: { expanded: true }, // Show full documentation for each property
},
argTypes: {
type: {
description: 'Alert.Types',
defaultValue: Alert.Types.WARNING,
table: {
type: {
summary: 'string',
},
defaultValue: {
summary: Alert.Types.WARNING,
},
},
options: Alert.Types,
control: {
type: 'select', // for selecting between the array of options above
},
},
title: {
defaultValue: '',
table: {
type: {
summary: 'string',
},
},
description: 'An optional title',
control: {
type: 'text',
},
},
onClose: {
table: {
type: {
summary: 'func',
},
},
description: 'Γ button click callback',
control: { type: null },
},
children: {
description: 'The message body (mandatory)',
type : {
required: true,
},
table: {
type: {
summary: 'node',
},
},
control: { type: null },
},
},
}
//...export your story...
Notes:
How to migrate dynamic knobs to controls?
Related
I am trying to include langage locale support from my React components in Storybook using "react-intl", I added the following global types in "preview.js" as list of Languages supported to appear in the Storybook toolbar:
export const globalTypes = {
locale: {
title: 'Locale',
description: 'Internationalization locale',
toolbar: {
icon: 'globe',
items: [
{ value: 'en', right: 'πΊπΈ', title: 'English' },
{ value: 'de', right: 'π©πͺ', title: 'Deutsch' },
],
dynamicTitle: true,
},
},
};
When I switch the langages it does not work always the default langage is showed, I need to know the code that can be used to implement the langage switcher and make it work with the code implemented within our React application in IdwIntlProvider.. I have to implement the functionality without using the react-intl Addon.
I'm trying to set custom labels for my controls in Storybook as outlined in the instructions here, but it's not working as expected. According to the instructions you can specify control.labels to configure custom labels for your checkbox, radio, or select input.
Right now I have a prop of size that allows the user to select the size of the component, but in Storybook it's showing the number value as opposed to name. e.g.
Instead of the number values I want the labels to read the names from the enum below.
export enum sizes {
small = 32,
default = 50,
large = 100,
};
How can I update Storybook to use the enum sizes name instead of the value?
// storybook
export default {
title: 'Components/Spinner',
component: Spinner,
controls: { expanded: true },
argTypes: {
type: {
options: ['primary', 'secondary', 'success', 'warning', 'danger', 'info', 'light'],
control: { type: 'radio'},
},
size: {
options: [sizes.default, sizes.small, sizes.large],
control: {
type: 'radio',
labels: {
Default: 'Default',
Small: 'Small',
Large: 'Large'
},
},
}
}
} as Meta;
FYI: If I update options to the following:
options: sizes,
I get both the name and the value and only the name works
In case anyone else comes across this issue I solved it by manually typing in the values. According to this Stackoverflow post enums end up as object. So it was outputting both the key and values.
export default {
title: 'Components/Spinner',
component: Spinner,
controls: { expanded: true },
argTypes: {
type: {
options: ['primary', 'secondary', 'success', 'warning', 'danger', 'info', 'light'],
control: { type: 'radio'},
},
size: {
options: [32, 50, 100],
control: {
type: 'radio',
labels: {
32: 'small',
50: 'default',
100: 'large',
},
},
}
}
} as Meta;
I'm in the process of creating an internal component library using Storybook and Kendo React and I'm having to explicitly define argTypes for controls for every prop in order to get them to give me anything but a string input (with the sole exception of booleans).
Here's a sample of one of my stories:
import React from "react";
import { ComponentStory, ComponentMeta } from "#storybook/react";
import { TestAvatar } from "../../components/Avatar/TestAvatar";
export default {
title: "Atomic Components/Test Avatar",
component: TestAvatar,
} as ComponentMeta<typeof TestAvatar>;
const Template: ComponentStory<typeof TestAvatar> = ({ ...args }: any) => (
<TestAvatar {...args} />
);
export const Standard = Template.bind({});
Standard.args = {
border: false,
themeColor: "base",
fillMode: "solid",
rounded: "medium",
size: "medium",
type: undefined,
};
Standard.argTypes = {
themeColor: {
options: ["base", "primary", "secondary", "tertiary", "success", "error"],
control: { type: "select" },
},
rounded: {
options: ["small", "medium", "large", "full", null],
control: { type: "select" },
},
size: {
options: ["small", "medium", "large"],
control: { type: "select" },
},
fillMode: {
options: ["solid", "outline"],
control: { type: "radio" },
},
type: {
options: ["image", "text", "icon"],
control: { type: "select" },
},
};
I have all the standard addons, although I haven't created any typescript options in main.js - I've tried, using info I got from this question but they don't seem to make any difference.
I've tried a few things, using Story and Meta from Storybook instead of the newer ComponentStory and ComponentMeta, I've tried extending the AvatarProps interface and I have also tried using the Kendo AvatarProps interface directly, but I can't find a way around it.
I suspect it's to do with how the Kendo library is typed.
I want to have to avoid creating controls for every single component I'm creating - does anyone have any ideas on how I can circumvent that amount of unnecessary work?
I'm new to AntD and having a little trouble with the stepper component - specifically, how to add a custom component into each of the steps.
For example,
const steps = [
{
title: 'First',
content: 'First-content',
},
{
title: 'Second',
content: 'Second-content',
},
{
title: 'Last',
content: 'Last-content',
},
];
For simplicity, if I were to use the Autocomplete component would it be just:
{
title: 'First',
content: '<Autocomplete />',
},
No luck so far. Any advice is appreciated.
There is no content in Steps.Step.
You may be trying to render a custom component in Steps, then you need to provide ReactNode and not a string type:
<Steps>
<Steps.Step> title="Finished" description={<AutoComplete/>} />
</Steps>
Its all mentioned in the docs, I believe what you need is the basics of React.
Maybe you found this official example Switch Step, there is a steps variable like this:
const steps = [
{
title: 'First',
content: 'First-content',
},
{
title: 'Second',
content: 'Second-content',
},
{
title: 'Last',
content: 'Last-content',
},
];
This is a user-defined variable, NOT pre-defined by antd, you can use whatever property even data structure you want. You can assign the ReactNode to content property like:
const steps = [
{
title: 'First',
content: <Autocomplete />,
},
// ...
]
And render the content based on current step state:
<div className="steps-content">{steps[current].content}</div>
There is NO content prop for the Steps.Step component. This is another way different from the accepted answer.
Prior to this, I was managing general Redux state as follows:
for example I was setting isRequestTags from a reducer.
But now I'm facing another challenge:
Suppose I have a list of tags, for each tag there can be some states defined like isPrimaryTag.
How can I define states for a list of items which have a common attribute?
If you have a list of tags, and each tag has, say, a name and a flag, then you can't "refactor" that out in any meaningful way, e.g.,
tags: [
{ name: 'foo', isPrimary: true },
{ name: 'bar', isPrimary: false }
]
If the common attributes are themselves an object, particularly a large one, you'd use normal state-shape practices as outlined in the Redux docs.
For example, if each tag had something like this:
tagInfo: {
isPrimary: true,
group: 'whatever',
somethingElse: { etc: 'etc' }
}
and multiple tags had the same value, you'd provide an ID/index:
tagInfos: [
{
isPrimary: true,
group: 'whatever',
somethingElse: { etc: 'etc' }
},
{
isPrimary: true,
group: 'whatever',
somethingElse: { etc: 'etc' }
}
]
tags: [
{ name: 'foo', tagInfoIndex: 0 },
{ name: 'bar', tagInfoIndex: 1 }
// etc
]
All that said, I'm not entirely sure if that's what you're asking.