├── .gitignore ├── .storybook ├── main.js └── preview.js ├── README.md ├── package.json ├── pages ├── api │ └── hello.js └── index.js ├── public ├── favicon.ico └── vercel.svg ├── stories ├── Banner.jsx ├── Banner.stories.jsx ├── Button.jsx ├── Button.stories.jsx ├── Header.jsx ├── Header.stories.jsx ├── Introduction.stories.mdx ├── Page.jsx ├── Page.stories.jsx ├── assets │ ├── code-brackets.svg │ ├── colors.svg │ ├── comments.svg │ ├── direction.svg │ ├── flow.svg │ ├── plugin.svg │ ├── repo.svg │ └── stackalt.svg ├── button.css ├── header.css └── page.css └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | #storybook 12 | /storybook-static 13 | 14 | # next.js 15 | /.next/ 16 | /out/ 17 | 18 | # production 19 | /build 20 | 21 | # misc 22 | .DS_Store 23 | 24 | # debug 25 | npm-debug.log* 26 | yarn-debug.log* 27 | yarn-error.log* 28 | 29 | # local env files 30 | .env.local 31 | .env.development.local 32 | .env.test.local 33 | .env.production.local 34 | -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "stories": [ 3 | "../stories/**/*.stories.mdx", 4 | "../stories/**/*.stories.@(js|jsx|ts|tsx)" 5 | ], 6 | "addons": [ 7 | "@storybook/addon-links", 8 | "@storybook/addon-essentials" 9 | ] 10 | } -------------------------------------------------------------------------------- /.storybook/preview.js: -------------------------------------------------------------------------------- 1 | export const parameters = { 2 | actions: { argTypesRegex: "^on[A-Z].*" }, 3 | controls: { 4 | matchers: { 5 | color: /(background|color)$/i, 6 | date: /Date$/, 7 | }, 8 | }, 9 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Storybook: React Component Library Example 2 | 3 | ![Storybook React tutorial Snipcart](https://www.datocms-assets.com/48401/1645800013-storybook-og.png) 4 | 5 | This post/tutorial focuses on UI development with Storybook. 6 | 7 | What is covered: 8 | 9 | - What Storybook is? 10 | - How can it save you valuable time when working with components? 11 | - How to set up a Storybook instance that is co-located with a React application? 12 | - How to create the first instance of a component along with its story? 13 | - How do various prop values affect the component’s appearance and functionality? 14 | 15 | 16 | 17 | -> Follow the tutorial [here](https://snipcart.com/blog/storybook-react-tutorial-example). 18 | 19 | -> Try the demo [here](https://nextjs-storybook-example-4nh7fvdd0-m0nica.vercel.app/). 20 | 21 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 22 | 23 | ## Getting Started 24 | 25 | First, run the development server: 26 | 27 | ```bash 28 | npm run dev 29 | # or 30 | yarn dev 31 | ``` 32 | 33 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 34 | 35 | You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. 36 | 37 | ## Learn More 38 | 39 | To learn more about Next.js, take a look at the following resources: 40 | 41 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 42 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 43 | 44 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 45 | 46 | ## Deploy on Vercel 47 | 48 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/import?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 49 | 50 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 51 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs-storybook-example", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "storybook": "start-storybook -p 6006", 10 | "build-storybook": "build-storybook" 11 | }, 12 | "dependencies": { 13 | "@emotion/react": "^11.4.0", 14 | "next": "11.0.1", 15 | "react": "17.0.2", 16 | "react-dom": "17.0.2" 17 | }, 18 | "devDependencies": { 19 | "@babel/core": "^7.14.6", 20 | "@storybook/addon-actions": "^6.3.4", 21 | "@storybook/addon-essentials": "^6.3.4", 22 | "@storybook/addon-links": "^6.3.4", 23 | "@storybook/react": "^6.3.4", 24 | "babel-loader": "^8.2.2" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /pages/api/hello.js: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | 3 | export default (req, res) => { 4 | res.statusCode = 200 5 | res.json({ name: 'John Doe' }) 6 | } 7 | -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | import Banner from "../stories/Banner.jsx"; 3 | export default function Home() { 4 | return ( 5 |
6 | 7 | Create Next App 8 | 9 | 10 | 11 |
12 | 13 |

14 | This is an example of how we can use our components from Storybook 15 | in a NextJS application. JSX components that are defined in 16 | Storybook can be imported/exported like regular JSX components. If 17 | you need to import components from Storybook in external 18 | applications then you should explore publishing a NPM package that 19 | contains the relevant components. 20 |

21 |
22 | 23 |

24 | Welcome to Next.js! 25 |

26 |

27 | Get started by editing pages/index.js 28 |

29 |
30 | 31 |

Documentation →

32 |

Find in-depth information about Next.js features and API.

33 |
34 | 35 | 36 |

Learn →

37 |

Learn about Next.js in an interactive course with quizzes!

38 |
39 | 40 | 44 |

Examples →

45 |

Discover and deploy boilerplate example Next.js projects.

46 |
47 | 48 | 52 |

Deploy →

53 |

54 | Instantly deploy your Next.js site to a public URL with Vercel. 55 |

56 |
57 |
58 |
59 | 60 | 70 | 71 | 201 | 202 | 216 |
217 | ); 218 | } 219 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snipcart/nextjs-storybook-example/5557c2a1ecf0e036d5909efe44b42e945a1b0f67/public/favicon.ico -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /stories/Banner.jsx: -------------------------------------------------------------------------------- 1 | /** @jsxImportSource @emotion/react */ 2 | import React from "react"; 3 | export default function Banner({ variant = "info", children }) { 4 | const beforeStyles = { 5 | width: 35, 6 | height: 35, 7 | display: "inline-flex", 8 | justifyContent: "center", 9 | position: "absolute", 10 | left: "-1.2rem", 11 | borderRadius: "50%", 12 | alignItems: "center", 13 | top: "-0.8rem", 14 | }; 15 | 16 | const variantStyles = { 17 | info: { 18 | borderLeft: "4px solid #b4aaff", 19 | backgroundColor: "rgba(224, 226, 255, 0.5)", 20 | color: "#2a2135", 21 | "&:before": { 22 | content: '"🔑"', 23 | backgroundColor: "#b4aaff", 24 | ...beforeStyles, 25 | }, 26 | }, 27 | danger: { 28 | borderLeft: "4px solid #ff7828", 29 | backgroundColor: "rgb(253, 236, 234)", 30 | "&:before": { 31 | content: '"⚠️"', 32 | backgroundColor: "#ff7828", 33 | ...beforeStyles, 34 | }, 35 | }, 36 | congrats: { 37 | borderLeft: "4px solid #72bc23", 38 | backgroundColor: "rgb(249, 253, 234)", 39 | "&:before": { 40 | content: '"🎉"', 41 | backgroundColor: "#72bc23", 42 | ...beforeStyles, 43 | }, 44 | }, 45 | documentation: { 46 | borderLeft: "4px solid #44a9ba", 47 | backgroundColor: "rgb(234, 248, 253);", 48 | "&:before": { 49 | content: '"📚"', 50 | backgroundColor: "#44a9ba", 51 | ...beforeStyles, 52 | }, 53 | }, 54 | }; 55 | return ( 56 | 72 | ); 73 | } 74 | 75 | Banner.propTypes = { 76 | variant: "info" | "congrats" | "documentation" | "danger", 77 | }; 78 | -------------------------------------------------------------------------------- /stories/Banner.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import Banner from "./Banner"; 4 | 5 | export default { 6 | title: "Example/Banner", 7 | component: Banner, 8 | }; 9 | 10 | export const Info = () => ( 11 | 12 |

13 | This is an example of an info banner to display important information. 14 |

15 |
16 | ); 17 | 18 | export const Danger = () => ( 19 | 20 |

This is an example of a danger banner to display warnings.

21 |
22 | ); 23 | 24 | export const Congrats = () => ( 25 | 26 |

This is an example a congrats banner to celebrate a win!

27 |
28 | ); 29 | 30 | export const Documentation = () => ( 31 | 32 |

33 | This is an example a documentation banner to highlight relevant reading 34 | materials and documentation. 35 |

36 |
37 | ); 38 | -------------------------------------------------------------------------------- /stories/Button.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import './button.css'; 4 | 5 | /** 6 | * Primary UI component for user interaction 7 | */ 8 | export const Button = ({ primary, backgroundColor, size, label, ...props }) => { 9 | const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary'; 10 | return ( 11 | 19 | ); 20 | }; 21 | 22 | Button.propTypes = { 23 | /** 24 | * Is this the principal call to action on the page? 25 | */ 26 | primary: PropTypes.bool, 27 | /** 28 | * What background color to use 29 | */ 30 | backgroundColor: PropTypes.string, 31 | /** 32 | * How large should the button be? 33 | */ 34 | size: PropTypes.oneOf(['small', 'medium', 'large']), 35 | /** 36 | * Button contents 37 | */ 38 | label: PropTypes.string.isRequired, 39 | /** 40 | * Optional click handler 41 | */ 42 | onClick: PropTypes.func, 43 | }; 44 | 45 | Button.defaultProps = { 46 | backgroundColor: null, 47 | primary: false, 48 | size: 'medium', 49 | onClick: undefined, 50 | }; 51 | -------------------------------------------------------------------------------- /stories/Button.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Button } from './Button'; 4 | 5 | export default { 6 | title: 'Example/Button', 7 | component: Button, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | }; 12 | 13 | const Template = (args) =>