primary
、secondary
など、さまざまなタイプのボタンコンポーネントがあります。
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ファイルでは、オプションを使用してマッピングしています。つまり、1つのページですべてのバリアントを確認できます。別の文字列が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"
/>
);
};
ノブを使用してすべてのバリエーションを1つのページに表示する方法はありますか?これはより手間がかかるため、各コンポーネントを手動で作成する必要がなく、buttonTypes
に新しい文字列が追加されても自動的に更新されないのが理想的です。
ノブの grouping 機能を使用すると、コンポーネントのすべてのインスタンスがすべてのコンポーネントインスタンス間で共有されるのではなく、コンポーネントの各インスタンスが独自のノブインスタンスを取得します。グループ化されたノブとグループ化されていないノブを混ぜて、特定のものを共有したい場合と共有したくない場合もあります。
次の例では、<Button/>
ストーリー。各インスタンスにはtype
およびdisabled
プロパティの独自のコピーがありますが、text
はそれらすべての間で共有されます。
各ボタンタイプには、type
およびdisabled
を設定できる独自のパネルがあります。 「その他」グループには、グループが設定されていないノブ(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";