在 React Storybook 的单个页面上显示组件的所有变体,但仍然有旋钮?

Show all variations of a component on a single page in React Storybook but still have Knobs?

我有一个可以是不同类型的按钮组件,例如 primarysecondary 等:

export const buttonTypes = [
  'primary',
  'secondary',
  'tertiary',
  'positive',
  'negative',
]

const Button = ({ text, type }) => {
    return(
        <button className={type}>{text}</button>
    )
}

Button.propTypes = {
    text: PropTypes.string,
    type: PropTypes.oneOf(buttonTypes),
}

在我的 Storybook 文件中,我正在通过选项进行映射。这意味着您可以在单个页面上看到所有变体,如果将另一个字符串添加到 buttonTypes 数组,它将自动添加到样式指南中:

import ButtonComponent, { buttonTypes } from './Button';

const Button = () => {
    return(
        <div>
            {
                buttonTypes.map(type=>(
                    <ButtonComponent key={type} text={type} type={type} />
                ))
            }
        </div>
    )
}

export default {
  title: 'Components',
  component: Button,
};

问题是这不适用于许多附加组件,例如旋钮。要使旋钮工作,您需要 Button 成为实际组件,而不是像我上面那样做包装器。

import ButtonComponent, { buttonTypes } from './Button';

const Button = () => {
  return (
    <ButtonComponent
      type={select('type', buttonTypes, buttonTypes.primary)}
      text="Button"
    />
  );
};

有没有办法使用旋钮并在一个页面上显示所有变化?理想情况下无需手动创建每个组件,因为这需要更多工作,并且如果将新字符串添加到 buttonTypes,则不会自动更新。

使用旋钮的 grouping 功能,这样您的组件的每个实例都将获得自己的旋钮实例,而不是在所有组件实例之间共享所有旋钮实例。如果您希望某些内容共享而其他内容不共享,您甚至可以将分组旋钮与 non-grouped nobs 混合使用。

在下面的示例中,我有一个 <Button/> 故事,其中每个实例都有自己的 typedisabled 属性副本,但 text 是共享的他们之间。

每种按钮类型都有自己的面板,您可以在其中设置其 typedisabled。 "Other" 组包含任何未设置其组的旋钮(例如 text)。

src/Button/Button.component.jsx

import * as React from "react";

import "./Button.style.css";

export const Button = ({
    text,
    type,
    disabled,
    onClick
}) => (
    <button
        className={`button button--${type} ${disabled ? "button--disabled" : ""}`}
        disabled={disabled}
        onClick={onClick}
        children={text}
    />
);

src/Button/Button.stories.jsx

import * as React from "react";
import {withKnobs, text, boolean, select} from "@storybook/addon-knobs";
import {action} from "@storybook/addon-actions";

import {Button, buttonTypes} from "./";

export default {
    title: "Button",
    component: Button,
    decorators: [withKnobs]
};

export const ButtonStory = () => {
    const buttontext = text("Text", "Click Me");

    return (
        <div>
            {buttonTypes.map(buttonType => (
                <div key={buttonType}>
                    <Button
                        type={select("Type", buttonTypes, buttonType, buttonType)}
                        disabled={boolean("Disabled", false, buttonType)}
                        onClick={action(`${buttonType} clicked`)}
                        text={buttontext}
                    />
                </div>
            ))}
        </div>
    );
};

ButtonStory.story = {
    name: "All"
}

src/Button/Button.types.js

export const buttonTypes = [
    "primary",
    "secondary",
    "tertiary"
];

src/Button/Button.style.css

.button {
    padding: 0.5em;
    font-size: 1.25em;
    border-radius: 10px;
    border-width: 2px;
    border-style: solid;
    border-color: black;
}

.button--primary {
    background-color: rgb(132, 198, 106);
    color: black;
    border-color: black;
}

.button--secondary {
    background-color: rgb(194, 194, 194);
    color: black;
    border-color: black;
}

.button--tertiary {
    background-color: transparent;
    color: inherit;
    border-color: transparent;
}

.button--disabled {
    background-color: rgb(194, 194, 194);
    color: rgb(105, 102, 102);
    border-color: rgb(105, 102, 102);
}

src/Button/index.js

export {Button} from "./Button.component";
export {buttonTypes} from "./Button.types";