@theforeman/stories
v12.2.3
Published
Documentation library for the foreman project
Downloads
56
Readme
@theforeman/stories
Documentation library for the foreman project
What are stories?
Stories are a playground that allows you to develop, document, and demo your components in isolation. It uses storybook, and some tailor-made configurations for foreman plugins.
Writing a story
You can write stories in two ways:
- Component Story Format (CSF) - https://github.com/storybookjs/storybook/blob/next/addons/docs/docs/mdx.md
- MDX - https://github.com/storybookjs/storybook/blob/next/addons/docs/docs/mdx.md
Assuming we have a Toggle
component that lives in webpack/components/Toggle/Toggle.js
:
import React from 'react';
const Toggle = ({ opened, setOpened }) => (
<button onClick={() => setOpened(!opened)}>
{opened ? 'OPEN' : 'CLOSE'}
</button>
);
export default Toggle;
To create a story for a given component, Toggle
, first, create a story with the file name Toggle.stories.(js|mdx)
next to Toggle.js
.
The tfm-stories
will search for files with the .stories.(js|mdx)
extension.
•
└── webpack
└── components
└── Toggle
├── Toggle.js
└── Toggle.stories.js
Component Story Format (CSF)
Storybook’s Component Story Format (CSF) is the recommended way to write stories since Storybook 5.2. Read the announcement to learn more about how it came to be.
In CSF, stories and component metadata are defined as ES Modules. Every component story file consists of a required default export and one or more named exports.
import React from 'react';
import { action, boolean } from '@theforeman/stories';
import Toggle from './Toggle';
export default {
title: 'Components|Widgets/Toggle',
component: Toggle,
};
export const withState = () => {
const [opened, setOpened] = useState(false);
return <Toggle opened={opened} setOpened={setOpened} />;
};
export const withKnobs = () => (
<Toggle setOpened={action('setOpened')} opened={boolean('opened')} />
);
export const opened = () => (
<Toggle opened={true} />
);
export const closed = () => (
<Toggle opened={false} />
);
Using this format will automatically generate a doc-page
with the following features:
The first story will be configured as the primary story.
A Description slot is computed from the Component's docgen comments in the component's source. For example, here's the source for Badge:
/** * Use `Badge` to highlight key info with a predefined status. */ export const Badge = ({ status, children }) => { ... }
A
prop-types
table is computed from the component's docgen prop-types. For example, here's the source for Badge prop-types:Badge.propTypes = { /** Set the status of the badge */ status: PropTypes.oneOf(['success', 'error', 'info']), /** Set the content of the badge */ children: PropTypes.node, };
Storybook Docs MDX
MDX is a syntax for writing long-form documentation and stories side-by-side in the same file. In contrast to DocsPage, which provides smart documentation out of the box, MDX gives you full control over your component documentation.
Read more about writing mdx stories: https://github.com/storybookjs/storybook/blob/master/addons/docs/docs/mdx.md
import { Meta } from '@theforeman/stories';
import { Story, Canvas, ArgsTable, action } from '@theforeman/stories';
// note: In Storybook v6 Preview was renamed to Canvas, and Props was renamed to ArgsTable
import Toggle from './Toggle';
<Meta
title="Components|Widgets/Toggle"
component={Toggle}
/>
# Toggle
Use `Toggle` to highlight key info with a predefined status.
<ArgsTable of={Toggle} />
<Canvas>
<Story name="With Knobs">
<Toggle setOpened={action('setOpened')} opened={boolean('opened')} />
</Story>
</Canvas>
With `opened={true}`
<Canvas>
<Story name="opened">
<Toggle opened={true} />
</Story>
</Canvas>
With `opened={false}`
<Canvas>
<Story name="closed">
<Toggle opened={false} />
</Story>
</Canvas>
Run stories development server
tfm-stories [options]
Options:
-V, --version output the version number
--plugin Use for a foreman-plugin
-p, --port <number> Port to run Stories (default: 6006)
-s, --setup-file <filename> Stories global setup file.
-h, --help output usage information
Build stories
tfm-build-stories [options]
Options:
-V, --version output the version number
--plugin, --plugin Use for a foreman-plugin
-s, --setup-file <filename> Stories global setup file.
-o, --output-dir <dir-name> Directory where to store built files
-w, --watch Enable watch mode
-q, --quiet Suppress verbose build output
-h, --help output usage information
Sorting stories
Stories will be sorted based on:
- The
storyWeight
number parameter where smaller values appear first. By default, all the stories have astoryWeight
set to1000
. - Alphabetically A-Z
To change the storyWeight
for a given story
, set it in the story parameter.
CSF
export default {
title: 'Components/SomeComponent',
component: SomeComponent,
parameters: {
storyWeight: 100,
},
};
MDX
import { Meta } from '@theforeman/stories';
<Meta
title="Components/SomeComponent"
component={SomeComponent}
parameters={{
storyWeight: 100,
}}
/>
Available storybook addons
@storybook/addon-docs
Storybook Docs transforms your Storybook stories into world-class component documentation.
DocsPage. Out of the box, all your stories get a DocsPage
. DocsPage
is a zero-config aggregation of your component stories, text descriptions, docgen comments, props tables, and code examples into clean, readable pages.
MDX. If you want more control, MDX
allows you to write long-form markdown documentation and stories in one file. You can also use it to write pure documentation pages and embed them inside your Storybook alongside your stories.
Import components from @storybook/addon-docs
directly:
import { Story, Canvas, ArgsTable } from '@storybook/addon-docs';
See: https://github.com/storybookjs/storybook/tree/next/addons/docs
@storybook/addon-actions
@storybook/addon-actions can be used to display data received by event handlers in Storybook.
To use it in your stories, import the action
method from @storybook/addon-actions
and assign it to an event handler.
import { action } from '@storybook/addon-actions';
export const myByttonStory = () => <Button onClick={action('buttonClicked')}>Click Here</Button>;
@storybook/addon-knobs
@storybook/addon-knobs allow you to edit props dynamically using the Storybook UI. You can also use Knobs as a dynamic variable inside stories in Storybook.
To use it in your stories, import the knobs that you need from @storybook/addon-knobs
and assign them to props.
See available knobs: https://github.com/storybookjs/storybook/tree/master/addons/knobs#available-knobs
import { boolean, text, number } from '@storybook/addon-knobs';
// Knobs for React props
export const withAButton = () => (
<button disabled={boolean("Disabled", false)}>
{text("Label", "Hello Storybook")}
</button>
);
// Knobs as dynamic variables.
export const asDynamicVariables = () => {
const name = text("Name", "Arunoda Susiripala");
const age = number("Age", 89);
const content = `I am ${name} and I'm ${age} years old.`;
return <div>{content}</div>;
};
@storybook/addon-centered
@storybook/addon-centered was an addon that, in previous Storybook versions, could be used to center components inside the preview in Storybook. As of Storybook v6 it is no longer needed.
To center a story:
export const MyStory = () => <div>my story</div>;
MyStory.story = {
parameters: { layout: 'centered' },
};
layout
also accepts padded
and fullscreen
.
@storybook/addon-storysource
@storybook/addon-storysource is used to show stories source in the addon panel.
@storybook/addon-viewport
@storybook/addon-viewport allows your stories to be displayed in different sizes and layouts in Storybook. This helps build responsive components inside of Storybook.
Contributing
Please checkout the contributing.md
, the roadmap.md
and the open issues.