chore(storybook): Upgrade Storybook from 6 to 8 (#53809)

Co-authored-by: Huyen Nguyen <25715018+huyenltnguyen@users.noreply.github.com>
This commit is contained in:
Valentin Palkovic
2024-02-28 14:22:33 +05:30
committed by GitHub
co-authored by Huyen Nguyen
parent 630fdac393
commit 6fdcec43dd
24 changed files with 2979 additions and 4668 deletions
+2308 -4084
View File
File diff suppressed because it is too large Load Diff
+38 -8
View File
@@ -1,18 +1,42 @@
module.exports = {
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.tsx'],
stories: ['../src/**/*.mdx', '../src/**/*.stories.tsx'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-a11y',
'@storybook/addon-mdx-gfm',
'@storybook/addon-styling-webpack',
{
name: '@storybook/addon-postcss',
name: '@storybook/addon-styling-webpack',
options: {
postcssLoaderOptions: {
implementation: require('postcss')
}
rules: [
{
test: /\.css$/,
sideEffects: true,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1
}
},
{
loader: require.resolve('postcss-loader'),
options: {
implementation: require.resolve('postcss')
}
}
]
}
]
}
}
},
'@storybook/addon-webpack5-compiler-babel'
],
typescript: {
check: false,
checkOptions: {},
@@ -23,7 +47,13 @@ module.exports = {
prop.parent ? !/node_modules/.test(prop.parent.fileName) : true
}
},
core: {
builder: 'webpack5'
framework: {
name: '@storybook/react-webpack5',
options: {}
},
docs: {
autodocs: true
}
};
+1 -1
View File
@@ -1,4 +1,4 @@
import { addons } from '@storybook/addons';
import { addons } from '@storybook/manager-api';
import theme from './theme';
addons.setConfig({
@@ -1,4 +1,5 @@
/* the styled-elements and normalized are included here to replicate the presets that exist in the learn app */
import React from 'react';
import '../src/normalize.css';
import '../src/global-element-styles.css';
import '../src/base.css';
+21 -14
View File
@@ -28,7 +28,7 @@
"@fortawesome/free-solid-svg-icons": "6.4.2",
"@fortawesome/react-fontawesome": "0.2.0",
"@headlessui/react": "1.7.18",
"@radix-ui/react-tabs": "^1.0.3",
"@radix-ui/react-tabs": "1.0.3",
"react": "16.14.0",
"react-dom": "16.14.0",
"tslib": "2.6.2",
@@ -42,37 +42,44 @@
"@rollup/plugin-commonjs": "19.0.2",
"@rollup/plugin-node-resolve": "13.3.0",
"@rollup/plugin-typescript": "8.5.0",
"@storybook/addon-a11y": "6.5.16",
"@storybook/addon-actions": "6.5.16",
"@storybook/addon-docs": "6.5.16",
"@storybook/addon-essentials": "6.5.16",
"@storybook/addon-links": "6.5.16",
"@storybook/addon-postcss": "2.0.0",
"@storybook/builder-webpack5": "6.5.16",
"@storybook/manager-webpack5": "6.5.16",
"@storybook/react": "6.5.16",
"@storybook/addon-a11y": "8.0.0-beta.3",
"@storybook/addon-actions": "8.0.0-beta.3",
"@storybook/addon-docs": "8.0.0-beta.3",
"@storybook/addon-essentials": "8.0.0-beta.3",
"@storybook/addon-links": "8.0.0-beta.3",
"@storybook/addon-mdx-gfm": "8.0.0-beta.3",
"@storybook/addon-styling-webpack": "1.0.0-next.1",
"@storybook/addon-webpack5-compiler-babel": "2.0.0",
"@storybook/addon-webpack5-compiler-swc": "1.0.0",
"@storybook/blocks": "8.0.0-beta.3",
"@storybook/react": "8.0.0-beta.3",
"@storybook/react-webpack5": "8.0.0-beta.3",
"@testing-library/jest-dom": "5.17.0",
"@testing-library/react": "12.1.5",
"@types/jest": "29.5.12",
"@types/react": "16.14.56",
"@types/react-dom": "^16.9.17",
"@types/testing-library__jest-dom": "^5",
"@types/react-dom": "16.9.17",
"@types/testing-library__jest-dom": "5",
"autoprefixer": "10.4.17",
"babel-loader": "8.3.0",
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
"cross-env": "7.0.3",
"css-loader": "6.8.1",
"npm-run-all2": "5.0.2",
"postcss": "8.4.35",
"postcss-import": "14.1.0",
"postcss-loader": "8.1.0",
"rollup": "2.79.1",
"rollup-plugin-postcss": "4.0.2",
"rollup-plugin-terser": "7.0.2",
"storybook": "8.0.0-beta.3",
"style-loader": "3.3.3",
"tailwindcss": "3.4.1"
},
"scripts": {
"storybook": "start-storybook -p 6006",
"storybook": "storybook dev -p 6006",
"storybook:theming": "pnpm run storybook --no-manager-cache",
"build-storybook": "build-storybook",
"build-storybook": "storybook build",
"build": "pnpm run build:css && pnpm run build:js && tsc",
"build:js": "cross-env NODE_ENV=production rollup -c",
"build:css": "npx -y tailwindcss -i ./src/base.css -o ./dist/base.css --minify",
+53 -47
View File
@@ -1,6 +1,6 @@
import { Story } from '@storybook/react';
import React from 'react';
import { Alert, AlertProps } from './alert';
import { Meta, StoryObj } from '@storybook/react';
import { Alert } from './alert';
const story = {
title: 'Example/Alert',
@@ -9,61 +9,67 @@ const story = {
children: { control: { type: 'text' } },
className: { control: { type: 'text' } }
}
} satisfies Meta<typeof Alert>;
type Story = StoryObj<typeof Alert>;
export const Success: Story = {
args: {
children: 'Hello, Alert!',
variant: 'success'
}
};
const Template: Story<AlertProps> = args => <Alert {...args} />;
export const Success = Template.bind({});
Success.args = {
children: 'Hello, Alert!',
variant: 'success'
export const Info: Story = {
args: {
children: 'Hello, Alert!',
variant: 'info'
}
};
export const Info = Template.bind({});
Info.args = {
children: 'Hello, Alert!',
variant: 'info'
export const Warning: Story = {
args: {
children: 'Hello, Alert!',
variant: 'warning'
}
};
export const Warning = Template.bind({});
Warning.args = {
children: 'Hello, Alert!',
variant: 'warning'
export const Danger: Story = {
args: {
children: 'Hello, Alert!',
variant: 'danger'
}
};
export const Danger = Template.bind({});
Danger.args = {
children: 'Hello, Alert!',
variant: 'danger'
export const LongText: Story = {
args: {
variant: 'success',
children:
'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet animi commodi cumque dicta ducimus eum iure, maiores mollitia, odit porro quas quod rerum soluta sunt tempora unde, vel voluptas voluptates.'
}
};
export const LongText = Template.bind({});
LongText.args = {
variant: 'success',
children:
'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet animi commodi cumque dicta ducimus eum iure, maiores mollitia, odit porro quas quod rerum soluta sunt tempora unde, vel voluptas voluptates.'
};
export const WithHeadingAndParagraphs = Template.bind({});
WithHeadingAndParagraphs.args = {
variant: 'info',
children: (
<>
<h4>
<strong>Some Heading Text</strong>
</h4>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet animi
commodi cumque dicta ducimus eum iure, maiores mollitia, odit porro quas
quod rerum soluta sunt tempora unde, vel voluptas voluptates.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet animi
commodi cumque dicta ducimus eum iure, maiores mollitia, odit porro quas
quod rerum soluta sunt tempora unde, vel voluptas voluptates.
</p>
</>
)
export const WithHeadingAndParagraphs: Story = {
args: {
variant: 'info',
children: (
<>
<h4>
<strong>Some Heading Text</strong>
</h4>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet animi
commodi cumque dicta ducimus eum iure, maiores mollitia, odit porro
quas quod rerum soluta sunt tempora unde, vel voluptas voluptates.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet animi
commodi cumque dicta ducimus eum iure, maiores mollitia, odit porro
quas quod rerum soluta sunt tempora unde, vel voluptas voluptates.
</p>
</>
)
}
};
export default story;
@@ -1,7 +1,6 @@
import { Story } from '@storybook/react';
import React from 'react';
import { Meta, StoryObj } from '@storybook/react';
import { Button, ButtonProps } from '.';
import { Button } from '.';
const story = {
title: 'Example/Button',
@@ -49,64 +48,71 @@ const story = {
control: { type: 'text' }
}
}
} satisfies Meta<typeof Button>;
type Story = StoryObj<typeof Button>;
export const Default: Story = {
args: {
children: 'Button'
}
};
const Template: Story<ButtonProps> = args => {
return <Button {...args} />;
export const Danger: Story = {
args: {
variant: 'danger',
children: 'Button'
}
};
export const Default = Template.bind({});
Default.args = {
children: 'Button'
export const Info: Story = {
args: {
variant: 'info',
children: 'Button'
}
};
export const Danger = Template.bind({});
Danger.args = {
variant: 'danger',
children: 'Button'
export const Large: Story = {
args: {
size: 'large',
children: 'Button'
}
};
export const Info = Template.bind({});
Info.args = {
variant: 'info',
children: 'Button'
export const Small: Story = {
args: {
size: 'small',
children: 'Button'
}
};
export const Large = Template.bind({});
Large.args = {
size: 'large',
children: 'Button'
export const Disabled: Story = {
args: {
children: 'Button',
disabled: true
}
};
export const Small = Template.bind({});
Small.args = {
size: 'small',
children: 'Button'
export const FullWidth: Story = {
args: {
children: 'Button',
block: true
}
};
export const Disabled = Template.bind({});
Disabled.args = {
children: 'Button',
disabled: true
export const AsALink: Story = {
args: {
children: "I'm a link that looks like a button",
href: 'https://www.freecodecamp.org'
}
};
export const FullWidth = Template.bind({});
FullWidth.args = {
children: 'Button',
block: true
};
export const AsALink = Template.bind({});
AsALink.args = {
children: "I'm a link that looks like a button",
href: 'https://www.freecodecamp.org'
};
export const AsADownloadLink = Template.bind({});
AsADownloadLink.args = {
children: "I'm a download link",
href: 'https://www.freecodecamp.org',
download: 'my_file.txt'
export const AsADownloadLink: Story = {
args: {
children: "I'm a download link",
href: 'https://www.freecodecamp.org',
download: 'my_file.txt'
}
};
export default story;
@@ -1,18 +1,18 @@
import { Story } from '@storybook/react';
import React from 'react';
import { CloseButton, CloseButtonProps } from './close-button';
import { Meta, StoryObj } from '@storybook/react';
import { CloseButton } from './close-button';
const story = {
title: 'Example/CloseButton',
component: CloseButton
};
} satisfies Meta<typeof CloseButton>;
const Template: Story<CloseButtonProps> = args => <CloseButton {...args} />;
type Story = StoryObj<typeof CloseButton>;
export const Basic = Template.bind({});
Basic.args = {
className: '',
label: ''
export const Basic: Story = {
args: {
className: '',
label: ''
}
};
export default story;
+10 -7
View File
@@ -1,6 +1,6 @@
import React from 'react';
import { Story } from '@storybook/react';
import { Col, ColProps } from '.';
import { Meta, StoryFn, StoryObj } from '@storybook/react';
import { Col } from '.';
const story = {
title: 'Example/Col',
@@ -17,9 +17,9 @@ const story = {
lgOffset: { options: [0, 1, 2, undefined] },
smPush: { options: [1, undefined] }
}
};
} satisfies Meta<typeof Col>;
const Template: Story<ColProps> = args => {
const Template: StoryFn<typeof Col> = args => {
return (
<Col className='bg-gray-700' {...args}>
<p>Random text to test the element width</p>
@@ -27,9 +27,12 @@ const Template: Story<ColProps> = args => {
);
};
export const Default = Template.bind({});
Default.args = {
// default props go here
export const Default: StoryObj<typeof Col> = {
render: Template,
args: {
// default props go here
}
};
export default story;
@@ -1,6 +1,6 @@
import React from 'react';
import { Story } from '@storybook/react';
import { Container, ContainerProps } from '.';
import { Meta, StoryFn, StoryObj } from '@storybook/react';
import { Container } from '.';
const story = {
title: 'Example/Container',
@@ -12,9 +12,9 @@ const story = {
}
}
}
};
} satisfies Meta<typeof Container>;
const Template: Story<ContainerProps> = args => {
const Template: StoryFn<typeof Container> = args => {
return (
<Container {...args}>
<p>Random text to test the element width</p>
@@ -33,7 +33,9 @@ const Template: Story<ContainerProps> = args => {
);
};
export const Default = Template.bind({});
Default.args = {};
export const Default: StoryObj<typeof Container> = {
render: Template,
args: {}
};
export default story;
@@ -1,6 +1,5 @@
import React from 'react';
import { Story } from '@storybook/react';
import { ControlLabel, ControlLabelProps } from '.';
import { Meta, StoryObj } from '@storybook/react';
import { ControlLabel } from '.';
const story = {
title: 'Example/ControlLabel',
@@ -10,20 +9,19 @@ const story = {
include: ['className']
}
},
argType: {
argTypes: {
className: { control: { type: 'text' } },
htmlFor: { control: { type: 'text' } },
srOnly: { options: ['srOnly', ''] }
}
};
} satisfies Meta<typeof ControlLabel>;
const Template: Story<ControlLabelProps> = args => {
return <ControlLabel {...args} />;
};
type Story = StoryObj<typeof ControlLabel>;
export const Default = Template.bind({});
Default.args = {
children: 'Control Label'
export const Default: Story = {
args: {
children: 'Control Label'
}
};
export default story;
@@ -1,11 +1,11 @@
import React from 'react';
import { Story } from '@storybook/react';
import { Meta, StoryObj } from '@storybook/react';
import { MenuItem } from './menu-item/menu-item';
import { Dropdown, DropdownProps } from './drop-down';
import { Dropdown } from './drop-down';
const story = {
title: 'Example/Dropdown',
component: Dropdown
};
} satisfies Meta<typeof Dropdown>;
const DropDownChildren = () => (
<>
@@ -31,41 +31,48 @@ const DropUpChildren = () => (
</>
);
export const Menus = (): JSX.Element => (
<div
style={{
height: '220px',
width: '220px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start'
}}
>
export const Menus: StoryObj<typeof Dropdown> = {
decorators: [
Story => (
<div
style={{
height: '220px',
width: '220px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start'
}}
>
{Story()}
</div>
)
],
render: () => (
<Dropdown>
<DropDownChildren />
</Dropdown>
</div>
);
const UpTemplate: Story<DropdownProps> = args => {
return (
<div
style={{
height: '220px',
width: '220px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-end'
}}
>
<Dropdown {...args} />
</div>
);
)
};
export const DropUp = UpTemplate.bind({});
DropUp.args = {
children: <DropUpChildren />,
dropup: true
export const DropUp: StoryObj<typeof Dropdown> = {
decorators: [
Story => (
<div
style={{
height: '220px',
width: '220px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-end'
}}
>
{Story()}
</div>
)
],
args: {
children: <DropUpChildren />,
dropup: true
}
};
export default story;
@@ -1,6 +1,6 @@
import React from 'react';
import { Story } from '@storybook/react';
import { FormControl, FormControlProps } from '.';
import { Meta, StoryFn, StoryObj } from '@storybook/react';
import { FormControl } from '.';
const story = {
title: 'Example/FormControl',
@@ -31,27 +31,25 @@ const story = {
required: { control: 'boolean' },
type: { options: ['text', 'email', 'url'] }
}
};
} satisfies Meta<typeof FormControl>;
const DefaultTemplate: Story<FormControlProps> = args => {
return <FormControl {...args} />;
};
type Story = StoryObj<typeof FormControl>;
export const Default = DefaultTemplate.bind({});
Default.args = {
// default props go here
};
export const Default: Story = {};
const StaticTemplate: Story<React.ComponentProps<'p'>> = args => {
const StaticTemplate: StoryFn<(typeof FormControl)['Static']> = args => {
return <FormControl.Static {...args} />;
};
export const Static = StaticTemplate.bind({});
Static.args = {
children: 'foo@bar.com'
export const Static: StoryObj<typeof FormControl.Static> = {
render: StaticTemplate,
args: {
children: 'foo@bar.com'
}
};
const FeedBackTemplate: Story<React.ComponentProps<'span'>> = args => {
const FeedBackTemplate: StoryFn<React.ComponentProps<'span'>> = args => {
return <FormControl.Feedback {...args} />;
};
@@ -71,9 +69,12 @@ const checkMark = (
</svg>
);
export const Feedback = FeedBackTemplate.bind({});
Feedback.args = {
children: checkMark
export const Feedback: StoryObj<typeof FormControl.Feedback> = {
render: FeedBackTemplate,
args: {
children: checkMark
}
};
export default story;
@@ -1,9 +1,9 @@
import React from 'react';
import { Story } from '@storybook/react';
import { Meta, StoryObj } from '@storybook/react';
import { FormControl } from '../form-control';
import { ControlLabel } from '../control-label';
import { FormGroup, FormGroupProps } from '.';
import { FormGroup } from '.';
const story = {
title: 'Example/FormGroup',
@@ -15,7 +15,9 @@ const story = {
as: { control: { type: 'text' } },
validationState: { options: ['success', 'warning', 'error', null] }
}
};
} satisfies Meta<typeof FormGroup>;
type Story = StoryObj<typeof FormGroup>;
const Child = () => {
return (
@@ -26,31 +28,31 @@ const Child = () => {
);
};
const Template: Story<FormGroupProps> = args => {
return <FormGroup {...args} />;
export const Default: Story = {
args: {
children: <Child />
}
};
export const Default = Template.bind({});
Default.args = {
children: <Child />
export const Success: Story = {
args: {
children: <Child />,
validationState: 'success'
}
};
export const Success = Template.bind({});
Success.args = {
children: <Child />,
validationState: 'success'
export const Error: Story = {
args: {
children: <Child />,
validationState: 'error'
}
};
export const Error = Template.bind({});
Error.args = {
children: <Child />,
validationState: 'error'
};
export const warning = Template.bind({});
warning.args = {
children: <Child />,
validationState: 'warning'
export const Warning: Story = {
args: {
children: <Child />,
validationState: 'warning'
}
};
export default story;
@@ -1,5 +1,4 @@
import React from 'react';
import { Story } from '@storybook/react';
import { Meta, StoryObj } from '@storybook/react';
import { HelpBlock } from './help-block';
const story = {
@@ -10,15 +9,14 @@ const story = {
include: ['className', 'children']
}
}
};
} satisfies Meta<typeof HelpBlock>;
const Template: Story<React.ComponentPropsWithRef<'span'>> = args => {
return <HelpBlock {...args} />;
};
type Story = StoryObj<typeof HelpBlock>;
export const Default = Template.bind({});
Default.args = {
children: 'This is a HelpBlock'
export const Default: Story = {
args: {
children: 'This is a HelpBlock'
}
};
export default story;
+22 -23
View File
@@ -1,38 +1,37 @@
import { Story } from '@storybook/react';
import { Meta, StoryObj } from '@storybook/react';
import React from 'react';
import { Image } from './image';
import { ImageProps } from './image.types';
const story = {
// Additional type assertion necessary due to a bug of how Storybook handles the `decorators` property in meta
const story: Meta<typeof Image> = {
title: 'Example/Image',
component: Image,
argTypes: {
responsive: {
control: { type: 'boolean' }
}
},
decorators: [
Story => <div style={{ width: '100px', height: '100px' }}>{Story()}</div>
]
} satisfies Meta<typeof Image>;
type Story = StoryObj<typeof Image>;
export const Default: Story = {
args: {
alt: "camper's avatar",
src: 'https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png',
responsive: false
}
};
const Template: Story<ImageProps> = args => {
return (
<div style={{ width: '100px', height: '100px' }}>
<Image {...args} />
</div>
);
};
export const Default = Template.bind({});
Default.args = {
alt: "camper's avatar",
src: 'https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png',
responsive: false
};
export const Responsive = Template.bind({});
Responsive.args = {
alt: "camper's avatar",
src: 'https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png',
responsive: true
export const Responsive: Story = {
args: {
alt: "camper's avatar",
src: 'https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png',
responsive: true
}
};
export default story;
+219
View File
@@ -0,0 +1,219 @@
import { Meta } from '@storybook/blocks';
import Code from './assets/code-brackets.svg';
import Colors from './assets/colors.svg';
import Comments from './assets/comments.svg';
import Direction from './assets/direction.svg';
import Flow from './assets/flow.svg';
import Plugin from './assets/plugin.svg';
import Repo from './assets/repo.svg';
import StackAlt from './assets/stackalt.svg';
<Meta title='Introduction' />
<style>
{`
.subheading {
--mediumdark: '#999999';
font-weight: 900;
font-size: 13px;
color: #999;
letter-spacing: 6px;
line-height: 24px;
text-transform: uppercase;
margin-bottom: 12px;
margin-top: 40px;
}
.link-list {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr;
row-gap: 10px;
}
@media (min-width: 620px) {
.link-list {
row-gap: 20px;
column-gap: 20px;
grid-template-columns: 1fr 1fr;
}
}
@media all and (-ms-high-contrast:none) {
.link-list {
display: -ms-grid;
-ms-grid-columns: 1fr 1fr;
-ms-grid-rows: 1fr 1fr;
}
}
.link-item {
display: block;
padding: 20px 30px 20px 15px;
border: 1px solid #00000010;
border-radius: 5px;
transition: background 150ms ease-out, border 150ms ease-out, transform 150ms ease-out;
color: #333333;
display: flex;
align-items: flex-start;
}
.link-item:hover {
border-color: #1EA7FD50;
transform: translate3d(0, -3px, 0);
box-shadow: rgba(0, 0, 0, 0.08) 0 3px 10px 0;
}
.link-item:active {
border-color: #1EA7FD;
transform: translate3d(0, 0, 0);
}
.link-item strong {
font-weight: 700;
display: block;
margin-bottom: 2px;
}
.link-item img {
height: 40px;
width: 40px;
margin-right: 15px;
flex: none;
}
.link-item span {
font-size: 14px;
line-height: 20px;
}
.tip {
display: inline-block;
border-radius: 1em;
font-size: 11px;
line-height: 12px;
font-weight: 700;
background: #E7FDD8;
color: #66BF3C;
padding: 4px 12px;
margin-right: 10px;
vertical-align: top;
}
.tip-wrapper {
font-size: 13px;
line-height: 20px;
margin-top: 40px;
margin-bottom: 40px;
}
.tip-wrapper code {
font-size: 12px;
display: inline-block;
}
`}
</style>
# Welcome to Storybook
Storybook helps you build UI components in isolation from your app's business logic, data, and context.
That makes it easy to develop hard-to-reach states. Save these UI states as **stories** to revisit during development, testing, or QA.
Browse example stories now by navigating to them in the sidebar.
View their code in the `src/stories` directory to learn how they work.
We recommend building UIs with a [**component-driven**](https://componentdriven.org) process starting with atomic components and ending with pages.
<div className='subheading'>Configure</div>
<div className="link-list">
<a className="link-item" href="https://storybook.js.org/docs/react/addons/addon-types" target="_blank">
<img src={Plugin} alt="plugin" />
<span>
<strong>Presets for popular tools</strong>
Easy setup for TypeScript, SCSS and more.
</span>
</a>
<a className="link-item" href="https://storybook.js.org/docs/react/configure/webpack" target="_blank">
<img src={StackAlt} alt="Build" />
<span>
<strong>Build configuration</strong>
How to customize webpack and Babel
</span>
</a>
<a className="link-item" href="https://storybook.js.org/docs/react/configure/styling-and-css" target="_blank">
<img src={Colors} alt="colors" />
<span>
<strong>Styling</strong>
How to load and configure CSS libraries
</span>
</a>
<a className="link-item" href="https://storybook.js.org/docs/react/get-started/setup#configure-storybook-for-your-stack" target="_blank">
<img src={Flow} alt="flow" />
<span>
<strong>Data</strong>
Providers and mocking for data libraries
</span>
</a>
</div>
<div className='subheading'>Learn</div>
<div className="link-list">
<a className="link-item" href="https://storybook.js.org/docs" target="_blank">
<img src={Repo} alt="repo" />
<span>
<strong>Storybook documentation</strong>
Configure, customize, and extend
</span>
</a>
<a className="link-item" href="https://storybook.js.org/tutorials/" target="_blank">
<img src={Direction} alt="direction" />
<span>
<strong>In-depth guides</strong>
Best practices from leading teams
</span>
</a>
<a className="link-item" href="https://github.com/storybookjs/storybook" target="_blank">
<img src={Code} alt="code" />
<span>
<strong>GitHub project</strong>
View the source and add issues
</span>
</a>
<a className="link-item" href="https://discord.gg/storybook" target="_blank">
<img src={Comments} alt="comments" />
<span>
<strong>Discord chat</strong>
Chat with maintainers and the community
</span>
</a>
</div>
<div className='tip-wrapper'>
<span className='tip'>Tip</span>Edit the Markdown in{' '}
<code>src/stories/Introduction.stories.mdx</code>
</div>
@@ -1,219 +0,0 @@
import { Meta } from '@storybook/addon-docs';
import Code from './assets/code-brackets.svg';
import Colors from './assets/colors.svg';
import Comments from './assets/comments.svg';
import Direction from './assets/direction.svg';
import Flow from './assets/flow.svg';
import Plugin from './assets/plugin.svg';
import Repo from './assets/repo.svg';
import StackAlt from './assets/stackalt.svg';
<Meta title='Example/Introduction' />
<style>{`
.subheading {
--mediumdark: '#999999';
font-weight: 900;
font-size: 13px;
color: #999;
letter-spacing: 6px;
line-height: 24px;
text-transform: uppercase;
margin-bottom: 12px;
margin-top: 40px;
}
.link-list {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr;
row-gap: 10px;
}
@media (min-width: 620px) {
.link-list {
row-gap: 20px;
column-gap: 20px;
grid-template-columns: 1fr 1fr;
}
}
@media all and (-ms-high-contrast:none) {
.link-list {
display: -ms-grid;
-ms-grid-columns: 1fr 1fr;
-ms-grid-rows: 1fr 1fr;
}
}
.link-item {
display: block;
padding: 20px 30px 20px 15px;
border: 1px solid #00000010;
border-radius: 5px;
transition: background 150ms ease-out, border 150ms ease-out, transform 150ms ease-out;
color: #333333;
display: flex;
align-items: flex-start;
}
.link-item:hover {
border-color: #1EA7FD50;
transform: translate3d(0, -3px, 0);
box-shadow: rgba(0, 0, 0, 0.08) 0 3px 10px 0;
}
.link-item:active {
border-color: #1EA7FD;
transform: translate3d(0, 0, 0);
}
.link-item strong {
font-weight: 700;
display: block;
margin-bottom: 2px;
}
.link-item img {
height: 40px;
width: 40px;
margin-right: 15px;
flex: none;
}
.link-item span {
font-size: 14px;
line-height: 20px;
}
.tip {
display: inline-block;
border-radius: 1em;
font-size: 11px;
line-height: 12px;
font-weight: 700;
background: #E7FDD8;
color: #66BF3C;
padding: 4px 12px;
margin-right: 10px;
vertical-align: top;
}
.tip-wrapper {
font-size: 13px;
line-height: 20px;
margin-top: 40px;
margin-bottom: 40px;
}
.tip-wrapper code {
font-size: 12px;
display: inline-block;
}
`}</style>
# Welcome to Storybook
Storybook helps you build UI components in isolation from your app's business logic, data, and context.
That makes it easy to develop hard-to-reach states. Save these UI states as **stories** to revisit during development, testing, or QA.
Browse example stories now by navigating to them in the sidebar.
View their code in the `src/stories` directory to learn how they work.
We recommend building UIs with a [**component-driven**](https://componentdriven.org) process starting with atomic components and ending with pages.
<div className='subheading'>Configure</div>
<div className='link-list'>
<a
className='link-item'
href='https://storybook.js.org/docs/react/addons/addon-types'
target='_blank'
>
<img src={Plugin} alt='plugin' />
<span>
<strong>Presets for popular tools</strong>
Easy setup for TypeScript, SCSS and more.
</span>
</a>
<a
className='link-item'
href='https://storybook.js.org/docs/react/configure/webpack'
target='_blank'
>
<img src={StackAlt} alt='Build' />
<span>
<strong>Build configuration</strong>
How to customize webpack and Babel
</span>
</a>
<a
className='link-item'
href='https://storybook.js.org/docs/react/configure/styling-and-css'
target='_blank'
>
<img src={Colors} alt='colors' />
<span>
<strong>Styling</strong>
How to load and configure CSS libraries
</span>
</a>
<a
className='link-item'
href='https://storybook.js.org/docs/react/get-started/setup#configure-storybook-for-your-stack'
target='_blank'
>
<img src={Flow} alt='flow' />
<span>
<strong>Data</strong>
Providers and mocking for data libraries
</span>
</a>
</div>
<div className='subheading'>Learn</div>
<div className='link-list'>
<a className='link-item' href='https://storybook.js.org/docs' target='_blank'>
<img src={Repo} alt='repo' />
<span>
<strong>Storybook documentation</strong>
Configure, customize, and extend
</span>
</a>
<a
className='link-item'
href='https://storybook.js.org/tutorials/'
target='_blank'
>
<img src={Direction} alt='direction' />
<span>
<strong>In-depth guides</strong>
Best practices from leading teams
</span>
</a>
<a
className='link-item'
href='https://github.com/storybookjs/storybook'
target='_blank'
>
<img src={Code} alt='code' />
<span>
<strong>GitHub project</strong>
View the source and add issues
</span>
</a>
<a className='link-item' href='https://discord.gg/storybook' target='_blank'>
<img src={Comments} alt='comments' />
<span>
<strong>Discord chat</strong>
Chat with maintainers and the community
</span>
</a>
</div>
<div className='tip-wrapper'>
<span className='tip'>Tip</span>Edit the Markdown in{' '}
<code>src/stories/Introduction.stories.mdx</code>
</div>
+17 -18
View File
@@ -1,27 +1,26 @@
import React from 'react';
import { Story } from '@storybook/react';
import { Link, LinkProps } from '.';
import { Meta, StoryObj } from '@storybook/react';
import { Link } from '.';
const story = {
title: 'Example/Link',
component: Link
} satisfies Meta<typeof Link>;
type Story = StoryObj<typeof Link>;
export const Default: Story = {
args: {
children: 'Go to freeCodeCamp',
to: 'https://www.freecodecamp.org'
}
};
const Template: Story<LinkProps> = args => {
return <Link {...args} />;
};
export const Default = Template.bind({});
Default.args = {
children: 'Go to freeCodeCamp',
to: 'https://www.freecodecamp.org'
};
export const Block = Template.bind({});
Block.args = {
children: 'Go to freeCodeCamp',
to: 'https://www.freecodecamp.org',
block: true
export const Block: Story = {
args: {
children: 'Go to freeCodeCamp',
to: 'https://www.freecodecamp.org',
block: true
}
};
export default story;
+24 -20
View File
@@ -1,6 +1,6 @@
import React from 'react';
import { Story } from '@storybook/react';
import { Panel, PanelProps } from '.';
import { Meta, StoryObj } from '@storybook/react';
import { Panel } from '.';
const story = {
title: 'Example/Panel',
@@ -10,11 +10,11 @@ const story = {
include: ['className', 'variant']
}
},
argType: {
argTypes: {
className: { control: { type: 'text' } },
variant: { option: ['primary', 'danger', 'info', undefined] }
}
};
} satisfies Meta<typeof Panel>;
const Child = () => {
return (
@@ -27,29 +27,33 @@ const Child = () => {
);
};
const Template: Story<PanelProps> = args => <Panel {...args} />;
type Story = StoryObj<typeof Panel>;
export const Default = Template.bind({});
Default.args = {
children: <Child />
export const Default: Story = {
args: {
children: <Child />
}
};
export const Primary = Template.bind({});
Primary.args = {
children: <Child />,
variant: 'primary'
export const Primary: Story = {
args: {
children: <Child />,
variant: 'primary'
}
};
export const Info = Template.bind({});
Info.args = {
children: <Child />,
variant: 'info'
export const Info: Story = {
args: {
children: <Child />,
variant: 'info'
}
};
export const Danger = Template.bind({});
Danger.args = {
children: <Child />,
variant: 'danger'
export const Danger: Story = {
args: {
children: <Child />,
variant: 'danger'
}
};
export default story;
+8 -9
View File
@@ -1,19 +1,18 @@
import React from 'react';
import { Story } from '@storybook/react';
import { Row, RowProps } from '.';
import { Meta, StoryObj } from '@storybook/react';
import { Row } from '.';
const story = {
title: 'Example/Row',
component: Row
};
} satisfies Meta<typeof Row>;
const Template: Story<RowProps> = args => {
return <Row {...args} />;
};
type Story = StoryObj<typeof Row>;
export const Default = Template.bind({});
Default.args = {
children: <p>Random text to test the element width</p>
export const Default: Story = {
args: {
children: <p>Random text to test the element width</p>
}
};
export default story;
+29 -14
View File
@@ -1,6 +1,7 @@
import React from 'react';
import { Story } from '@storybook/react';
import { Table, TableProps } from '.';
import { Meta, StoryFn, StoryObj } from '@storybook/react';
import { Table } from '.';
const exampleTable = (
<>
<thead>
@@ -61,23 +62,37 @@ const story = {
control: { type: 'radio' }
}
}
};
} satisfies Meta<typeof Table>;
const Template: Story<TableProps> = args => (
const Template: StoryFn<typeof Table> = args => (
<Table {...args}>{exampleTable}</Table>
);
export const Default = Template.bind({});
Default.args = {
condensed: false,
striped: false
type Story = StoryObj<typeof Table>;
export const Default: Story = {
render: Template,
args: {
condensed: false,
striped: false
}
};
export const Condensed = Template.bind({});
Condensed.args = {
condensed: true
export const Condensed: Story = {
render: Template,
args: {
condensed: true
}
};
export const Striped = Template.bind({});
Striped.args = {
striped: true
export const Striped: Story = {
render: Template,
args: {
striped: true
}
};
export default story;
+14 -9
View File
@@ -1,13 +1,13 @@
import React from 'react';
import { Story } from '@storybook/react';
import { Meta, StoryFn, StoryObj } from '@storybook/react';
import { Tabs, TabsList, TabsTrigger, TabsContent } from '.';
const story = {
title: 'Example/Tabs',
component: Tabs
};
} satisfies Meta<typeof Tabs>;
const Template: Story<React.ComponentProps<typeof Tabs>> = args => {
const Template: StoryFn<typeof Tabs> = args => {
return (
<Tabs {...args}>
<TabsList>
@@ -22,12 +22,17 @@ const Template: Story<React.ComponentProps<typeof Tabs>> = args => {
);
};
export const Default = Template.bind({});
Default.args = {
id: 'uncontrolled-tab-example',
defaultValue: 'code',
onSelect: () => {
console.log('onSelect');
type Story = StoryObj<typeof Tabs>;
export const Default: Story = {
render: Template,
args: {
id: 'uncontrolled-tab-example',
defaultValue: 'code',
onSelect: () => {
console.log('onSelect');
}
}
};
@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import { Story } from '@storybook/react';
import { ToggleButton, ToggleButtonProps } from '.';
import { Meta, StoryObj } from '@storybook/react';
import { ToggleButton } from '.';
const story = {
title: 'Example/ToggleButton',
@@ -44,57 +44,62 @@ const story = {
type: { name: 'string' }
}
}
} satisfies Meta<typeof ToggleButton>;
type Story = StoryObj<typeof ToggleButton>;
export const Default: Story = {
args: {
children: 'Off'
}
};
const Template: Story<ToggleButtonProps> = args => {
return <ToggleButton {...args} />;
export const Checked: Story = {
args: {
checked: true,
children: 'On',
value: 'Value'
}
};
export const Default = Template.bind({});
Default.args = {
children: 'Off'
export const Large: Story = {
args: {
bsSize: 'large',
children: 'Off'
}
};
export const Checked = Template.bind({});
Checked.args = {
checked: true,
children: 'On',
value: 'Value'
export const Medium: Story = {
args: {
bsSize: 'medium',
children: 'Off'
}
};
export const Large = Template.bind({});
Large.args = {
bsSize: 'large',
children: 'Off'
export const Disabled: Story = {
args: {
children: 'Off',
disabled: true
}
};
export const Medium = Template.bind({});
Medium.args = {
bsSize: 'medium',
children: 'Off'
export const RadioChecked: Story = {
args: {
type: 'radio',
children: 'On',
value: 'radio',
name: 'radio',
checked: true
}
};
export const Disabled = Template.bind({});
Disabled.args = {
children: 'Off',
disabled: true
};
export const RadioChecked = Template.bind({});
RadioChecked.args = {
type: 'radio',
children: 'On',
value: 'radio',
name: 'radio',
checked: true
};
export const RadioUnchecked = Template.bind({});
RadioUnchecked.args = {
type: 'radio',
children: 'Off',
value: 'radio',
name: 'radio'
export const RadioUnchecked: Story = {
args: {
type: 'radio',
children: 'Off',
value: 'radio',
name: 'radio'
}
};
export const InsideToggleGroup = (): JSX.Element => {