Skip to content

Instantly share code, notes, and snippets.

@shawn-sandy
Last active March 18, 2022 17:57
Show Gist options
  • Save shawn-sandy/b31f6ef96e82b3a256c2f5a7f7dfaa77 to your computer and use it in GitHub Desktop.
Save shawn-sandy/b31f6ef96e82b3a256c2f5a7f7dfaa77 to your computer and use it in GitHub Desktop.
storybook development

import { Meta } from "@storybook/addon-docs"

Elements

Browse example stories now by navigating to them in the sidebar. View their code in the src/elements/** directory to learn how they work. We recommend building UIs with a component-driven process starting with atomic components and ending with pages.

TipEdit the Markdown in{" "} src/stories/Introduction.stories.mdx
import React from 'react'
import PropTypes from 'prop-types'
const Button = ({ type = 'button', styles = {}, children = 'Default Button', onClick, ...props }) => {
const demoClick = () => console.log(`Clicked ${children}`)
const defaultStyles = {
fontSize: 'var(--btn-fs, calc(13rem /16))',
color: 'var(--btn-color, white)',
backgroundColor: 'var(--btn-bg, gray)',
display: 'var(--btn-dsp, inline-flex)',
gap: 'var(--btn-gap, 1rem)',
minHeight: 'calc(40rem /16 )',
placeItems: 'var(--btn-place, center)',
paddingInline: 'var(--btn-px, 2rem)',
border: 'var(--btn-border, none)',
cursor: 'var(--btn-cursor, pointer)'
}
return (
<button type={type} style={{ ...defaultStyles, ...styles }} onClick={onClick || demoClick} {...props}> {children || 'Buttons'}</button>
)
}
Button.propTypes = {
/**
* Button content - use html, text
*/
children: PropTypes.any,
/**
* Button onClick function - use to override default click handler
*/
onClick: PropTypes.func,
/**
* Set the Button type - default is 'button'
*/
type: PropTypes.string
}
export default Button

import React from 'react' import Button from './button'

export default { title: 'Elements/Buttons', component: Button }

const Template = (args) => <Button {...args} />

export const Default = Template.bind({}) Default.args = { children: 'Default Button', onClick: () => console.log('Clicked Default Button') } /**

  • General component description in JSDoc format. Markdown is supported. */ export const Red = Template.bind({}) Red.args = { children: 'Red Button', styles: { '--btn-bg': 'red', '--btn-color': 'white' }, onClick: () => console.log('Clicked Default Button') }
import React from 'react'
import Layout from './container'
export default {
title: 'Components/Layout/Sections',
component: Layout,
parameters: {
layout: 'padded',
status: {
type: 'alpha',
}
}
}
const Template = (args) => (
<Layout { ...args } styles={ { '--box-max-w': '100%' } } />
)
export const Section = Template.bind({})
Section.args = {
children: 'First paint is a performance-first, accessibility-driven, SCSS/CSS micro-framework'
}
export const FPGrid: ComponentStory<typeof Grid> = () => (
<Grid>
<div role="gridcell">
<h3>Grid col</h3>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing
elit. Quod nulla totam dolorem nemo facere ex
expedita illum laboriosam sit. Ea laboriosam rem
omnis sit autem temporibus ipsum maxime dignissimos
id.
</p>
</div>
<div role="gridcell">
<h3>Grid col</h3>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing
elit. Quod nulla totam dolorem nemo facere ex
expedita illum laboriosam sit. Ea laboriosam rem
omnis sit autem temporibus ipsum maxime dignissimos
id.
</p>
</div>
<div role="gridcell">
<h3>Grid col</h3>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing
elit. Quod nulla totam dolorem nemo facere ex
expedita illum laboriosam sit. Ea laboriosam rem
omnis sit autem temporibus ipsum maxime dignissimos
id.
</p>
</div>
<div role="gridcell">
<h3>Grid col</h3>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing
elit. Quod nulla totam dolorem nemo facere ex
expedita illum laboriosam sit. Ea laboriosam rem
omnis sit autem temporibus ipsum maxime dignissimos
id.
</p>
</div>
</Grid>
)
const Template: ComponentStory<typeof Grid> = ({
...args
}) => (
<section style={{ maxWidth: "min(80vw, 100vw)" }}>
<Grid {...args}>
<div role="gridcell">
<h3>Grid col</h3>
<p>
Lorem, ipsum dolor sit amet consectetur
adipisicing elit. Quod nulla totam dolorem nemo
facere ex expedita illum laboriosam sit. Ea
laboriosam rem omnis sit autem temporibus ipsum
maxime dignissimos id.
</p>
</div>
<div role="gridcell">
<h3>Grid col</h3>
<p>
Lorem, ipsum dolor sit amet consectetur
adipisicing elit. Quod nulla totam dolorem nemo
facere ex expedita illum laboriosam sit. Ea
laboriosam rem omnis sit autem temporibus ipsum
maxime dignissimos id.
</p>
</div>
<div role="gridcell">
<h3>Grid col</h3>
<p>
Lorem, ipsum dolor sit amet consectetur
adipisicing elit. Quod nulla totam dolorem nemo
facere ex expedita illum laboriosam sit. Ea
laboriosam rem omnis sit autem temporibus ipsum
maxime dignissimos id.
</p>
</div>
<div role="gridcell">
<h3>Grid col</h3>
<p>
Lorem, ipsum dolor sit amet consectetur
adipisicing elit. Quod nulla totam dolorem nemo
facere ex expedita illum laboriosam sit. Ea
laboriosam rem omnis sit autem temporibus ipsum
maxime dignissimos id.
</p>
</div>
</Grid>
</section>
)
//👇 Each story then reuses that template
export const StyledGrid = Template.bind({})
// Primary.args = { backgroundColor: "#ff0", label: "Example" }
StyledGrid.args = {
styles: {
"--grid-count": "2"
}
}

import { Meta } from "@storybook/addon-docs"

Elements

Browse example stories now by navigating to them in the sidebar. View their code in the src/elements/** directory to learn how they work. We recommend building UIs with a component-driven process starting with atomic components and ending with pages.

TipEdit the Markdown in{" "} src/stories/Introduction.stories.mdx
import React from 'react'
import PropTypes from 'prop-types'
const ExampleComponent = ({ children, classes, styles, ...rest }) => {
return (
<div className={classes} style={styles} {...rest}>{children}</div>
)
}
ExampleComponent.propTypes = {
/**
* Content to render inside the container
*/
children: PropTypes.any,
/**
* Styles to apply to the container
*/
styles: PropTypes.object,
/**
* Classes to apply to the container
*/
classes: PropTypes.string
}
export default ExampleComponent
/** @format */
// Example.stories.ts|tsx
import React from 'react'
import { ComponentStory, ComponentMeta } from '@storybook/react'
import Example from './Example'
export default {
/* 👇 The title prop is optional.
* See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
* to learn how to generate automatic titles
*/
title: 'Example',
component: Example,
} as ComponentMeta<typeof Example>
//👇 We create a “template” of how args map to rendering
const Template: ComponentStory<typeof Example> = (args) => <Example {...args} />
//👇 Each story then reuses that template
export const Primary = Template.bind({})
Primary.args = { backgroundColor: '#ff0', label: 'Example' }
export const Secondary = Template.bind({})
Secondary.args = { ...Primary.args, label: '😄👍😍💯' }
export const Tertiary = Template.bind({})
Tertiary.args = { ...Primary.args, label: '📚📕📈🤓' }
import React from 'react'
import Component from './component'
export default {
title: 'Elements/component',
component: Component,
parameters: {
layout: 'centered',
}
}
const ComponentTemplate = (args) => <Component {...args} />
export const Comp = ComponentTemplate.bind({})
Comp.args = {
children: 'Content',
}
// export const Red = Template.bind({})
// Red.args = {
// children: 'Red Component',
// styles: { '--btn-bg': 'red', '--btn-color': 'white' },
// onClick: () => console.log('Clicked DefaultName Component')
// }
/** @format */
// Example.stories.ts|tsx
import React from 'react'
import { ComponentStory, ComponentMeta } from '@storybook/react'
import { Example } from './Example'
export default {
title: 'Example',
component: Example,
layout: 'padded',
status: {
type: 'alpha',
},
} as ComponentMeta<typeof Example>
export const Primary: ComponentStory<typeof Example> = () => (
<Example primary>Example</Example>
)

import { Meta } from '@storybook/addon-docs'

Example title

Browse example stories now by navigating to them in the sidebar. View their code in the src/**/** directory to learn how they work. We recommend building UIs with a component-driven process starting with atomic components and ending with pages.

TipCreate/Edit the MDX docs in{' '} src/**/**.stories.mdx, read more about MDX syntax{' '} Learn more
// .storybook/FirstPaint.js
import { create } from '@storybook/theming'
export default create({
base: 'light',
brandTitle: 'Theme Name',
brandUrl: '/',
// brandImage: 'https://first-paint.netlify.app/img/fp.svg',
// UI settings
appBg: 'white',
appContentBg: 'white',
appBorderColor: 'lightgrey',
colorSecondary: 'black',
// Text colors
textColor: 'black',
textInverseColor: 'rgba(255,255,255,0.9)',
// Toolbar default and active colors
barTextColor: 'sliver',
barSelectedColor: 'black',
barBg: 'whitesmoke',
// Form colors
inputBg: 'white',
inputBorder: 'silver',
inputTextColor: 'black',
inputBorderRadius: 4,
})
// .storybook/FirstPaint.js
import { create } from '@storybook/theming'
export default create({
base: 'light',
brandTitle: 'FirstPaint',
brandUrl: '/',
brandImage: 'https://res.cloudinary.com/dqjs95c7n/image/upload/v1643757934/fpb-logo-sm_lh5eth.svg',
// UI settings
appBg: 'white',
appContentBg: 'white',
appBorderColor: 'transparent',
colorSecondary: 'dimgray',
// Text colors
textColor: 'black',
textInverseColor: 'rgba(255,255,255,0.9)',
// Toolbar default and active colors
barTextColor: 'sliver',
barSelectedColor: 'dimgray',
barBg: 'transparent',
// Form colors
inputBg: 'white',
inputBorder: 'silver',
inputTextColor: 'black',
inputBorderRadius: 4
})
import React from 'react'
import FpImg from './img'
export default {
title: 'Elements/Media/Images',
component: FpImg,
parameters: {
layout: 'centered',
status: {
type: 'beta', // 'beta' | 'stable' | 'deprecated' | 'releaseCandidate'
// url: 'http://www.url.com/status', // will make the tag a link
// statuses: { ...} // add custom statuses for this story here
}
}
}
const ImgTemplate = (args) => <FpImg { ...args } />
export const Image = ImgTemplate.bind({})
Image.args = {
src: 'https://via.placeholder.com/150',
alt: 'Placeholder Image'
}
export const ImageMedium = ImgTemplate.bind({})
ImageMedium.args = {
src: 'https://via.placeholder.com/300',
alt: 'Placeholder Image',
width: '300',
height: '300'
}
/**
* ## Button Element.
* * Submit, Reset, and Button styles
* * Disabled state and default styles
* * [Button documentation](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button)
* * [Accessibility Info](https://www.w3.org/TR/wai-aria-practices-1.2/#button)
*/
module.exports = {
"stories": [
"../src/guides/**/*.stories.mdx",
"../src/tokens/**/*.stories.jsx",
"../src/elements/**/*.stories.jsx",
"../src/components/**/*.stories.jsx",
"../src/modules/**/*.stories.jsx",
"../src/pages/**/*.stories.jsx",
"../src/services/**/*.stories.jsx",
"../src/**/*.stories.@(js|jsx|ts|tsx)",
"../src/**/*.stories.mdx",
],
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials",
'@storybook/addon-a11y',
"@storybook/preset-create-react-app",
"@storybook/addon-storysource",
'storybook-design-token',
'storybook-addon-designs',
'@whitespace/storybook-addon-html',
{
name: '@storybook/addon-docs',
options: {
sourceLoaderOptions: {
injectStoryParameters: false,
},
},
},
],
"framework": "@storybook/react",
"core": {
"builder": "webpack5"
}
}
// .storybook/manager.js
import { addons } from '@storybook/addons'
import { themes } from '@storybook/theming'
import FirstPaint from './FirstPaint'
addons.setConfig({
isFullscreen: false,
showNav: false,
showPanel: true,
panelPosition: 'bottom',
enableShortcuts: true,
isToolshown: true,
selectedPanel: undefined,
initialActive: 'sidebar',
theme: FirstPaint,
sidebar: {
showRoots: false,
collapsedRoots: ['other'],
},
toolbar: {
title: { hidden: false, },
zoom: { hidden: false, },
eject: { hidden: false, },
copy: { hidden: false, },
fullscreen: { hidden: true, }
}
})
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
layout: 'centered',
}
import React from 'react'
import PropTypes from 'prop-types'
const Services = ({ children }) => (
<div>{children || 'Content here'}</div>
)
export default Services
Services.propTypes = {
/**
* Content of the page
*/
children: PropTypes.any
}
/** @format */
const Template: ComponentStory<typeof Example> = ({ ...args }) => (
<Example {...args} />
)
//👇 Each story then reuses that template
export const Primary = Template.bind({})
Primary.args = { backgroundColor: '#ff0', label: 'Example' }
"devDependencies": {
"@axe-core/react": "^4.4.0",
"@etchteam/storybook-addon-status": "^4.2.0",
"@shawnsandy/first-paint": "^2.7.0",
"@storybook/addon-a11y": "^6.4.19",
"@storybook/addon-actions": "^6.4.19",
"@storybook/addon-essentials": "^6.4.19",
"@storybook/addon-interactions": "^6.4.19",
"@storybook/addon-links": "^6.4.19",
"@storybook/addon-storysource": "^6.4.19",
"@storybook/builder-webpack5": "^6.4.19",
"@storybook/manager-webpack5": "^6.4.19",
"@storybook/node-logger": "^6.4.19",
"@storybook/preset-create-react-app": "^4.0.1",
"@storybook/react": "^6.4.19",
"@storybook/testing-library": "0.0.9",
"@whitespace/storybook-addon-html": "^5.0.0",
"axe-core": "^4.4.1",
"chromatic": "^6.4.3",
"sass": "^1.49.8",
"storybook-addon-performance": "^0.16.1",
"storybook-addon-pseudo-states": "^1.0.0",
"storybook-design-token": "^1.4.0",
"webpack": "^5.69.1"
}
{
"name": "@shawnsandy/fp-react",
"version": "0.0.1",
"private": false,
"dependencies": {
"@storybook/addon-a11y": "^6.4.18",
"@storybook/addon-docs": "^6.4.18",
"@storybook/addon-storysource": "^6.4.18",
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.5.0",
"react": "^17.0.2",
"react-content-loader": "^6.1.0",
"react-dom": "^17.0.2",
"react-scripts": "5.0.0",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "start-storybook -p 6006 -s public",
"start:react": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"dev": "styleguidist server",
"storybook": "start-storybook -p 6006 -s public",
"build-storybook": "build-storybook -o ./www/components"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
],
"overrides": [
{
"files": [
"**/*.stories.*"
],
"rules": {
"import/no-anonymous-default-export": "off"
}
}
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@axe-core/react": "^4.3.2",
"@storybook/addon-actions": "^6.4.18",
"@storybook/addon-essentials": "^6.4.18",
"@storybook/addon-links": "^6.4.18",
"@storybook/builder-webpack5": "^6.4.18",
"@storybook/manager-webpack5": "^6.4.18",
"@storybook/node-logger": "^6.4.18",
"@storybook/preset-create-react-app": "^4.0.0",
"@storybook/react": "^6.4.18",
"axe-core": "^4.4.0",
"chromatic": "^6.4.3",
"crypto-browserify": "^3.12.0",
"eslint-plugin-jsx-a11y": "^6.5.1",
"react-styleguidist": "11.2.0",
"sass": "^1.49.7",
"storybook-addon-designs": "^6.2.1",
"storybook-addon-export-to-codesandbox": "^0.6.4",
"storybook-design-token": "^1.4.0",
"webpack": "^5.68.0"
},
"browser": {
"crypto": false
}
}
{
"name": "@shawnsandy/fp-react",
"version": "0.0.1",
"private": false,
"dependencies": {
"@storybook/addon-a11y": "^6.4.18",
"@storybook/addon-docs": "^6.4.18",
"@storybook/addon-storysource": "^6.4.18",
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.5.0",
"react": "^17.0.2",
"react-content-loader": "^6.1.0",
"react-dom": "^17.0.2",
"react-scripts": "5.0.0",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "start-storybook -p 6006 -s public",
"start:react": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"dev": "styleguidist server",
"storybook": "start-storybook -p 6006 -s public",
"build-storybook": "build-storybook -o ./www/components"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
],
"overrides": [
{
"files": [
"**/*.stories.*"
],
"rules": {
"import/no-anonymous-default-export": "off"
}
}
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@axe-core/react": "^4.3.2",
"@storybook/addon-actions": "^6.4.18",
"@storybook/addon-essentials": "^6.4.18",
"@storybook/addon-links": "^6.4.18",
"@storybook/builder-webpack5": "^6.4.18",
"@storybook/manager-webpack5": "^6.4.18",
"@storybook/node-logger": "^6.4.18",
"@storybook/preset-create-react-app": "^4.0.0",
"@storybook/react": "^6.4.18",
"axe-core": "^4.4.0",
"chromatic": "^6.4.3",
"crypto-browserify": "^3.12.0",
"eslint-plugin-jsx-a11y": "^6.5.1",
"react-styleguidist": "11.2.0",
"sass": "^1.49.7",
"storybook-addon-designs": "^6.2.1",
"storybook-addon-export-to-codesandbox": "^0.6.4",
"storybook-design-token": "^1.4.0",
"webpack": "^5.68.0"
},
"browser": {
"crypto": false
}
}
/** @format */
import React from 'react'
import { ComponentMeta, ComponentStory } from '@storybook/react'
import { SampleComponent } from './sample'
export default {
title: 'Elements/Media/Images',
component: SampleComponent,
parameters: {
layout: 'centered',
status: {
type: 'alpha',
},
},
} as ComponentMeta<typeof SampleComponent>
const ComponentTemplate: ComponentStory<typeof SampleComponent> = (args) => (
<SampleComponent {...args} />
)
export const Sample = ComponentTemplate.bind({})
Sample.args = {
children: 'You can add a caption to an image',
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment