From 0916c4dfdf603f4544ce0d863827091186937a3e Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Tue, 31 Oct 2023 18:22:47 -0400 Subject: [PATCH 01/28] Add warning variant to callout --- package.json | 1 + .../basics/Callout/Callout.stories.tsx | 102 ++++++++---------- src/components/basics/Callout/Callout.tsx | 73 +++++++++++-- yarn.lock | 5 + 4 files changed, 120 insertions(+), 61 deletions(-) diff --git a/package.json b/package.json index 52f37b25..1089619b 100644 --- a/package.json +++ b/package.json @@ -76,6 +76,7 @@ "remark-html": "^13.0.1", "request": "^2.88.2", "semver": "^7.5.2", + "snarkdown": "^2.0.0", "unist-util-visit": "^2.0.3", "use-debounce": "^8.0.4", "usehooks-ts": "^2.9.1", diff --git a/src/components/basics/Callout/Callout.stories.tsx b/src/components/basics/Callout/Callout.stories.tsx index d70eb2ea..ea76a5ac 100644 --- a/src/components/basics/Callout/Callout.stories.tsx +++ b/src/components/basics/Callout/Callout.stories.tsx @@ -4,70 +4,62 @@ import { styles } from '@storybook/design-system'; import { Callout } from './Callout'; +const { spacing } = styles; + +const StoryWrapper = styled.div` + padding: ${spacing.padding.medium}px; +`; + export default { title: 'Basics/Callout', component: Callout, parameters: { chromatic: { viewports: [320, 900] }, }, + decorators: [(story) => {story()}], }; -const { typography, spacing } = styles; - -const StoryWrapper = styled.div` - padding: ${spacing.padding.medium}px; -`; - -const Title = styled.h1` - font-family: ${typography.type}; - font-weight: ${typography.weight.bold}; - font-size: ${typography.size.s3}px; - line-height: ${typography.size.m3}px; -`; +export const Default = { + args: { + title: "Hello there, I'm a Callout", + children: `I'm here to bring attention to some important information that you might be interested in.`, + }, +}; -const BodyText = styled.p` - font-family: ${typography.type}; - font-size: ${typography.size.s3}px; - line-height: ${typography.size.m3}px; - margin: 0; -`; +export const Variants = { + args: { + ...Default.args, + }, + render: (args) => ( + <> + +
+ +
+ +
+ + + ), +}; -const Template = (args) => ( - - - 👋 Hello there, I'm a Callout - - I'm here to bring attention to some important information that you might be interested in. -
- You can play with the way I look using the prop controls below 👇 -
-
-
-); +export const WithEmoji = { + args: { + ...Default.args, + icon: '👋', + }, +}; -export const Default = Template.bind({}); +export const WithoutTitle = { + args: { + ...WithEmoji.args, + title: undefined, + }, +}; -export const Variants = () => ( - - - I'm a neutral Callout - - I'm here to bring attention to some important information that you might be interested in - - -
- - I'm a positive Callout - - I'm here to bring attention to some important information that you might be interested in - - -
- - I'm a selected Callout - - I'm here to bring attention to some important information that you might be interested in - - -
-); +export const WithMarkdownTitle = { + args: { + ...WithEmoji.args, + title: '`next/font` support', + }, +}; diff --git a/src/components/basics/Callout/Callout.tsx b/src/components/basics/Callout/Callout.tsx index 272db92d..e5ad5750 100644 --- a/src/components/basics/Callout/Callout.tsx +++ b/src/components/basics/Callout/Callout.tsx @@ -1,24 +1,29 @@ import React from 'react'; +import snarkdown from 'snarkdown'; + import { rgba } from 'polished'; import { styled } from '@storybook/theming'; import { styles } from '@storybook/design-system'; -const { spacing, color, background } = styles; +const { spacing, color, background, typography, breakpoint } = styles; -type Variant = 'neutral' | 'positive' | 'selected'; +type Variant = 'neutral' | 'positive' | 'info' | 'warning'; const VARIANT_COLORS: Record = { neutral: { background: color.mediumlight, border: rgba(color.darker, 0.1) }, positive: { background: background.positive, border: rgba(color.positive, 0.1) }, - selected: { background: background.calmBlue, border: rgba(color.selected, 0.1) }, + info: { background: background.calmBlue, border: rgba(color.selected, 0.1) }, + warning: { background: background.warning, border: rgba(color.warning, 0.1) }, }; -export interface CalloutProps { +interface CalloutContainerProps { variant: Variant; } -export const Callout = styled.div` +const CalloutContainer = styled.div` padding: ${spacing.padding.medium}px; border-radius: ${spacing.borderRadius.small}px; + display: flex; + flex-direction: row; ${({ variant }) => ` background: ${VARIANT_COLORS[variant].background}; @@ -30,6 +35,62 @@ export const Callout = styled.div` } `; -Callout.defaultProps = { +CalloutContainer.defaultProps = { variant: 'neutral', }; + +const CalloutIcon = styled.span` + @media (min-width: ${breakpoint}px) { + margin-right: ${spacing.padding.small}px; + flex: 0 0 auto; + font-size: ${typography.size.m2}px; + display: inline-block; + } + display: none; +`; + +CalloutIcon.defaultProps = { + 'aria-hidden': true, +}; + +const CalloutContent = styled.div` + display: flex; + flex-direction: column; + flex: 1; + justify-content: center; +`; + +const CalloutTitle = styled.span` + font-family: ${typography.type}; + font-weight: ${typography.weight.bold}; + font-size: ${typography.size.s3}px; + line-height: ${typography.size.m3}px; + display: block; + + code { + color: inherit; + } +`; + +const CalloutBodyText = styled.p` + font-family: ${typography.type}; + font-size: ${typography.size.s3}px; + line-height: ${typography.size.m3}px; + margin: 0; +`; + +export interface CalloutProps extends CalloutContainerProps { + title?: string; + icon?: string; + children: string; +} + +export const Callout = ({ title, icon, children, variant }: CalloutProps) => ( + + {icon && {icon}} + + {title && } + {children} + + +); diff --git a/yarn.lock b/yarn.lock index b133b680..0413d9f7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -20522,6 +20522,11 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +snarkdown@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/snarkdown/-/snarkdown-2.0.0.tgz#b1feb4db91b9f94a8ebbd7a50f3e99aee18b1e03" + integrity sha512-MgL/7k/AZdXCTJiNgrO7chgDqaB9FGM/1Tvlcenenb7div6obaDATzs16JhFyHHBGodHT3B7RzRc5qk8pFhg3A== + snyk-config@^4.0.0-rc.2: version "4.0.0" resolved "https://registry.npmjs.org/snyk-config/-/snyk-config-4.0.0.tgz#21d459f19087991246cc07a7ffb4501dce6f4159" From 52b4d6125dd5ed69271ed4794604736992d5c620 Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Tue, 31 Oct 2023 18:23:54 -0400 Subject: [PATCH 02/28] Decouple Callout component from Recipe detail --- .../RecipesDetailScreen.js | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/components/screens/IntegrationsCatalog/RecipesDetailScreen/RecipesDetailScreen.js b/src/components/screens/IntegrationsCatalog/RecipesDetailScreen/RecipesDetailScreen.js index a195f93e..780a31d7 100644 --- a/src/components/screens/IntegrationsCatalog/RecipesDetailScreen/RecipesDetailScreen.js +++ b/src/components/screens/IntegrationsCatalog/RecipesDetailScreen/RecipesDetailScreen.js @@ -1,6 +1,7 @@ import React, { useMemo } from 'react'; import PropTypes from 'prop-types'; import { format } from 'date-fns'; +import { rgba } from 'polished'; import { styled } from '@storybook/theming'; import { Link as GatsbyLink } from 'gatsby'; import { MDXProvider } from '@mdx-js/react'; @@ -18,7 +19,7 @@ import { import { SubNav, SubNavBreadcrumb, SubNavCTA, SubNavRight } from '@storybook/components-marketing'; import useSiteMetadata from '../../../lib/useSiteMetadata'; -import { SocialGraph, Callout, Pre } from '../../../basics'; +import { SocialGraph, Pre } from '../../../basics'; import { IntegrationsAside, IntegrationsAsideContainer, @@ -32,7 +33,7 @@ import { generateBreadcrumb } from '../../../../util/generate-breadcrumb'; import { generateRecipeGithubIssueLink } from './helpers'; import { CodeSnippets } from './CodeSnippets'; -const { color, typography, spacing } = styles; +const { color, background, typography, spacing } = styles; const SectionLinksContainer = styled.div` margin-bottom: 30px; @@ -59,7 +60,19 @@ const ReadMe = styled.section` min-width: 0; `; -const AddonsCallout = styled(Callout)` +// TODO: UPDATE THIS TO NEW COMPONENT +const AddonsCallout = styled.div` + padding: ${spacing.padding.medium}px; + border-radius: ${spacing.borderRadius.small}px; + display: flex; + flex-direction: row; + + background: ${background.positive}; + box-shadow: ${rgba(color.positive, 0.1)} 0 0 0 1px inset; + + && *:last-child { + margin-bottom: 0px; + } margin-bottom: 40px; `; @@ -247,7 +260,7 @@ export const RecipesDetailScreen = ({ path, location, pageContext }) => { {hasAddons && (
- + Do it for me automatically The quickest way to integrate Storybook and {displayName} is to use an addon. From 5cb1391056ca820943d2d5b4aac304e027c81205 Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Tue, 31 Oct 2023 18:24:14 -0400 Subject: [PATCH 03/28] Make new callout component available to DocsScreen --- src/components/screens/DocsScreen/DocsScreen.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/components/screens/DocsScreen/DocsScreen.tsx b/src/components/screens/DocsScreen/DocsScreen.tsx index 6df19eef..ab581f5a 100644 --- a/src/components/screens/DocsScreen/DocsScreen.tsx +++ b/src/components/screens/DocsScreen/DocsScreen.tsx @@ -13,7 +13,14 @@ import { import { graphql } from 'gatsby'; import { CodeSnippets } from './CodeSnippets'; import { frameworkSupportsFeature, FrameworkSupportTable } from './FrameworkSupportTable'; -import { SocialGraph } from '../../basics'; +import { + SocialGraph, + Callout, + CalloutIcon, + CalloutContent, + CalloutTitle, + CalloutBodyText, +} from '../../basics'; import { Pre } from '../../basics/Pre'; import GatsbyLinkWrapper from '../../basics/GatsbyLinkWrapper'; import useSiteMetadata from '../../lib/useSiteMetadata'; @@ -235,6 +242,11 @@ function DocsScreen({ data, pageContext, location }) { IfRenderer: IfRendererWithCurrentFramework, YouTubeCallout, a: LinksWithPrefix, + Callout, + CalloutIcon, + CalloutContent, + CalloutTitle, + CalloutBodyText, }} > From 04abbeda631baa15f6e2378407d58e7bcda248f9 Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Tue, 31 Oct 2023 18:25:25 -0400 Subject: [PATCH 04/28] Make Callout available to recipe pages --- .../RecipesDetailScreen/RecipesDetailScreen.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/screens/IntegrationsCatalog/RecipesDetailScreen/RecipesDetailScreen.js b/src/components/screens/IntegrationsCatalog/RecipesDetailScreen/RecipesDetailScreen.js index 780a31d7..781c5dac 100644 --- a/src/components/screens/IntegrationsCatalog/RecipesDetailScreen/RecipesDetailScreen.js +++ b/src/components/screens/IntegrationsCatalog/RecipesDetailScreen/RecipesDetailScreen.js @@ -19,7 +19,7 @@ import { import { SubNav, SubNavBreadcrumb, SubNavCTA, SubNavRight } from '@storybook/components-marketing'; import useSiteMetadata from '../../../lib/useSiteMetadata'; -import { SocialGraph, Pre } from '../../../basics'; +import { SocialGraph, Pre, Callout } from '../../../basics'; import { IntegrationsAside, IntegrationsAsideContainer, @@ -278,6 +278,7 @@ export const RecipesDetailScreen = ({ path, location, pageContext }) => { pre: Pre, RecipeHeader, CodeSnippets, + Callout, }} > From fdba7eaeee0a96b953579f4531feae46c690eba7 Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Wed, 1 Nov 2023 09:55:48 -0400 Subject: [PATCH 05/28] Remove subcomponents --- src/components/screens/DocsScreen/DocsScreen.tsx | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/components/screens/DocsScreen/DocsScreen.tsx b/src/components/screens/DocsScreen/DocsScreen.tsx index ab581f5a..e6cc2022 100644 --- a/src/components/screens/DocsScreen/DocsScreen.tsx +++ b/src/components/screens/DocsScreen/DocsScreen.tsx @@ -13,14 +13,8 @@ import { import { graphql } from 'gatsby'; import { CodeSnippets } from './CodeSnippets'; import { frameworkSupportsFeature, FrameworkSupportTable } from './FrameworkSupportTable'; -import { - SocialGraph, - Callout, - CalloutIcon, - CalloutContent, - CalloutTitle, - CalloutBodyText, -} from '../../basics'; +import { SocialGraph } from '../../basics'; +import { Callout } from '../../basics/Callout'; import { Pre } from '../../basics/Pre'; import GatsbyLinkWrapper from '../../basics/GatsbyLinkWrapper'; import useSiteMetadata from '../../lib/useSiteMetadata'; @@ -243,10 +237,6 @@ function DocsScreen({ data, pageContext, location }) { YouTubeCallout, a: LinksWithPrefix, Callout, - CalloutIcon, - CalloutContent, - CalloutTitle, - CalloutBodyText, }} > From 8e3264486c8580fea2663a21f50aed32a941a37b Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Wed, 1 Nov 2023 11:49:51 -0400 Subject: [PATCH 06/28] Update Tailwind recipe with new callout --- src/components/basics/Callout/Callout.tsx | 4 +- src/content/recipes/tailwindcss.md | 110 +++++++++++++--------- 2 files changed, 68 insertions(+), 46 deletions(-) diff --git a/src/components/basics/Callout/Callout.tsx b/src/components/basics/Callout/Callout.tsx index e5ad5750..7aa93c9a 100644 --- a/src/components/basics/Callout/Callout.tsx +++ b/src/components/basics/Callout/Callout.tsx @@ -85,8 +85,8 @@ export interface CalloutProps extends CalloutContainerProps { children: string; } -export const Callout = ({ title, icon, children, variant }: CalloutProps) => ( - +export const Callout = ({ title, icon, children, variant, ...props }: CalloutProps) => ( + {icon && {icon}} {title && } diff --git a/src/content/recipes/tailwindcss.md b/src/content/recipes/tailwindcss.md index 54c43590..43087599 100644 --- a/src/content/recipes/tailwindcss.md +++ b/src/content/recipes/tailwindcss.md @@ -1,36 +1,30 @@ -
+ -This recipe assumes that you have a React app using Tailwind CSS and have just set up Storybook >=7.0 using the [getting started guide](/docs/react/get-started/install). Don’t have this? Follow Tailwind's [setup instructions](https://tailwindcss.com/docs/installation) then run: +This recipe assumes that you have a React app using Tailwind CSS and have just set up **Storybook >=7.0** using the [getting started guide](/docs/react/get-started/install). Don’t have this? Follow Tailwind's [setup instructions](https://tailwindcss.com/docs/installation) then run: ```shell # Add Storybook: npx storybook@latest init ``` -
+ - +## 1. Configure PostCSS -How to setup Tailwind CSS and Storybook - + -Storybook.js is a fantastic tool for developing and showcasing UI components in isolation. One of the great things about it is that you can use any CSS framework you like, including Tailwind CSS. +Tailwind uses PostCSS to compile your CSS. If you are using: +- `vite` +- `@storybook/nextjs` +- `@storybook/preset-create-react-app` with `react-scripts@2.0.0` +- `@storybook/angular` + +then you can skip to the [next step](#2-provide-tailwind-to-stories). -In this post, we will: + -1. 🏗️ Build Tailwind next to Storybook -2. 🎁 Provide Tailwind to stories -3. 🧱 Use Tailwind in your components -4. 🎨 Switch Tailwind themes in a click -![Finished example of Tailwind CSS in Storybook with a theme switcher](https://user-images.githubusercontent.com/18172605/208201389-1f448dbb-978c-442e-9d6b-7bf3fea63e64.gif) - -## Before you begin - -Tailwind uses PostCSS to compile your CSS. If you are using Vite, `@storybook/nextjs`, `@storybook/angular`, or `@storybook/preset-create-react-app` with `react-scripts@2.0.0`, then you can skip to the [theme switching section](#add-a-theme-switcher-tool). - -## Configure PostCSS For Webpack users, you'll need to install the [`@storybook/addon-styling-webpack`](https://storybook.js.org/addons/@storybook/addon-styling-webpack) addon. @@ -42,7 +36,12 @@ npx storybook@latest add @storybook/addon-styling-webpack This will run a configuration script that will walk you through setting up the addon. If prompted, select `PostCSS` from the configuration options. -### Provide Tailwind to stories +
+ Did the configuration script fail? +

Under the hood, this runs npx @storybook/auto-config styling which should read your project and try to configure your Storybook Webpack for your desired tools. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be. You can find manual configuration instruction for PostCSS here.

+
+ +## 2. Provide Tailwind to stories Now you can import the `tailwind.css` file into your `.storybook/preview.js` file. This will make Tailwind’s style classes available to all of your stories. @@ -52,29 +51,24 @@ Now you can import the `tailwind.css` file into your `.storybook/preview.js` fil import '../src/tailwind.css'; // replace with the name of your tailwind css file ``` -## Use Tailwind in components - -Let’s update some of our example components to use Tailwind instead. Open up Storybook to see what we have so far. - -![Storybook before adding tailwind CSS to the example components](https://user-images.githubusercontent.com/18172605/208201413-ace25d53-880a-4580-a81a-3d628fba229e.gif) - -To make use of Tailwind, replace the contents of each component file with the following code: - - - - - - - -![Storybook after adding tailwind CSS to the example components](https://user-images.githubusercontent.com/18172605/208201423-c7ea9392-1851-4fc3-9968-6d05399c2e91.gif) +### 2.1. Angular + +If you are using Angular, you will need to add the `tailwind.css` file to your `angular.json` file instead. This will make sure your styles are processed with PostCSS and are injected into the preview iframe where your stories are rendered. + +```json +// angular.json +{ + "storybook": { + "builder": "@storybook/angular:start-storybook", + "options": { + "browserTarget": "my-default-project:build", + "styles": ["src/tailwind.css"] + } + } +} +``` -### Add a theme switcher tool +## 3. Add a theme switcher tool Tailwind comes out of the box with a light and dark theme. You can override those themes and add more. To get the most out of your stories, you should have a way to toggle between all of your themes. @@ -87,7 +81,7 @@ First of all, update your `tailwind.config.js` file to [change themes based on a module.exports = { content: ['./src/**/*.{js,jsx,ts,tsx}'], - // Toggle dark-mode based on data-mode="dark" + // Toggle dark-mode based on .dark class or data-mode="dark" darkMode: ['class', '[data-mode="dark"]'], theme: { extend: {}, @@ -106,7 +100,35 @@ npx storybook@latest add @storybook/addon-themes This will run a configuration script that will walk you through setting up the addon. -To add the switcher, add the [`withThemeByDataAttribute`](https://github.com/storybookjs/addon-themes/blob/main/code/addons/themes/docs/api.md#withthemebydataattribute) decorator to your Storybook from `@storybook/addon-themes` +
+ Did the configuration script fail? +

Under the hood, this runs npx @storybook/auto-config themes which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be. To manually add this addon, install it then add it to the addons array in your `.storybook/main.ts`

+
+ +### 3.1. Toggle themes by class name + +Add the [`withThemeByClassName`](https://github.com/storybookjs/addon-themes/blob/main/code/addons/themes/docs/api.md#withthemebyclassname) decorator to your Storybook from `@storybook/addon-themes` + +```js +// .storybook/preview.js +import { withThemeByClassName } from '@storybook/addon-themes'; + +/* snipped for brevity */ + +export const decorators = [ + withThemeByClassName({ + themes: { + light: 'light', + dark: 'dark', + }, + defaultTheme: 'light', + }), +]; +``` + +### 3.2. Toggle themes by data-attribute + +Add the [`withThemeByDataAttribute`](https://github.com/storybookjs/addon-themes/blob/main/code/addons/themes/docs/api.md#withthemebydataattribute) decorator to your Storybook from `@storybook/addon-themes` ```js // .storybook/preview.js From 3d71879ceaa703b74ea240833486f09794c7110f Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Thu, 2 Nov 2023 10:05:33 -0400 Subject: [PATCH 07/28] Update asides in sass recipe --- src/content/recipes/sass.md | 48 ++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/src/content/recipes/sass.md b/src/content/recipes/sass.md index d84a7656..1ea7d624 100644 --- a/src/content/recipes/sass.md +++ b/src/content/recipes/sass.md @@ -1,23 +1,15 @@ -
+## 1. Add `@storybook/addon-styling-webpack` -Some configurations of Storybook already come pre-configured to support Sass. If your project meets the following, you're likely ready to go. + -1. Storybook >= 7.x with the `vite` builder. -2. Storybook >= 7.x with the `@storybook/nextjs` framework. -3. Storybook >= 6.x with the `@storybook/preset-create-react-app` and `react-scripts@2.x.x` or higher. -4. Storybook >= 6.x with the `@storybook/angular` framework. Inject your global stylesheets into Storybook through your `angular.json` file. +Some configurations of Storybook already come pre-configured to support Sass. If your project meets the following, then you can skip to the [next step](#2-import-global-styles). -
+- Storybook >= 7.x with the `vite` builder. +- Storybook >= 7.x with the `@storybook/nextjs` framework. +- Storybook >= 7.x with the `@storybook/preset-create-react-app` and `react-scripts@2.x.x` or higher. +- Storybook >= 7.x with the `@storybook/angular` framework. - - -How to setup Sass and Storybook - - - -Sass is a popular CSS preprocessor that allows developers to write more maintainable and reusable stylesheets. Storybook is an industry-standard tool for developing and testing UI components in isolation. With the help of the `@storybook/addon-styling-webpack` package, developers can easily incorporate Sass stylesheets into their Storybook components. - -## Adding `@storybook/addon-styling-webpack` + Run the following script to install and register the addon: @@ -27,7 +19,12 @@ npx storybook@latest add @storybook/addon-styling-webpack This will run a configuration script that will walk you through setting up the addon. When prompted, select `Sass` from the configuration options. -## Import global styles +
+ Did the configuration script fail? +

Under the hood, this runs npx @storybook/auto-config styling which should read your project and try to configure your Storybook Webpack for your desired tools. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be. You can find manual configuration instruction for Sass here.

+
+ +## 2. Import global styles If you have any global styles you would like to expose for your stories, you can now import them into your `preview.js` file: @@ -36,6 +33,23 @@ If you have any global styles you would like to expose for your stories, you can import '../src/index.scss'; ``` +### 2.1. Angular + +If you are using Angular, you will need to add your global scss file(s) to your `angular.json` file instead. This will make sure your styles are processed by Angular's Webpack and injected into the preview iframe where your stories are rendered. + +```json +// angular.json +{ + "storybook": { + "builder": "@storybook/angular:start-storybook", + "options": { + "browserTarget": "my-default-project:build", + "styles": ["src/index.scss"] + } + } +} +``` + ## Get involved Now you're ready to use Sass with Storybook. 🎉 If you use Sass at work, we'd love your feedback on the Sass + Storybook experience. From 70f5b272778db9e9802ce6199c47c5bd9c2767cc Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Thu, 2 Nov 2023 10:34:45 -0400 Subject: [PATCH 08/28] Add new callouts to emotion recipe --- src/content/recipes/@emotion/styled.md | 275 ++----------------------- 1 file changed, 20 insertions(+), 255 deletions(-) diff --git a/src/content/recipes/@emotion/styled.md b/src/content/recipes/@emotion/styled.md index dbca4159..c6d9dbda 100644 --- a/src/content/recipes/@emotion/styled.md +++ b/src/content/recipes/@emotion/styled.md @@ -1,4 +1,4 @@ -
+ This recipe assumes that you have a React app using Emotion and have just set up Storybook >=7.0 using the [getting started guide](/docs/react/get-started/install). Don’t have this? Follow Emotion's [installation instructions](https://emotion.sh/docs/introduction#react) then run: @@ -7,29 +7,9 @@ This recipe assumes that you have a React app using Emotion and have just set up npx storybook@latest init ``` -
+ - - -How to setup Emotion and Storybook - - - -Emotion is a popular library for building UI components with CSS-in-JS, while Storybook is a tool for creating and testing UI components in isolation. -This post will show you how to integrate these two tools to create a powerful and flexible development environment for building user interfaces with Emotion. - -This post will explain how to: - -1. 🔌 Setup `Global` styles -1. 🧱 Use Emotion in your components -1. 💅 Use a theme in your stories -1. 🎨 Switch betweens themes in a click - -If you’d like to see the example code of this recipe, check out the [example repository](https://github.com/Integrayshaun/emotion-recipe) on GitHub. Let's get started! - -![Completed Emotion example with theme switcher](https://user-images.githubusercontent.com/18172605/208312563-875ca3b0-e7bc-4401-a445-4553b48068ed.gif) - -## Install `@storybook/addon-themes` +## 1. Add `@storybook/addon-themes` To get started, you'll need to install [`@storybook/addon-themes`](https://storybook.js.org/addons/@storybook/addon-themes). @@ -39,13 +19,14 @@ Run the following script to install and register the addon: npx storybook@latest add @storybook/addon-themes ``` -### How to setup `GlobalStyles` +
+ Did the configuration script fail? +

Under the hood, this runs npx @storybook/auto-config themes which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be. To manually add this addon, install it then add it to the addons array in your .storybook/main.ts

+
-UIs often have a set of global styles that are applied to every component like CSS resets, `font-size`, `font-family`, and colors. +## 2. Provide `GlobalStyles` -In Emotion, use the [`Global`](https://emotion.sh/docs/globals) component to scope styles globally instead of locally (which is the library's default behavior). - -Open `.storybook/preview.js` and create a `GlobalStyles` component which includes a `font-family`. Then apply it to your stories with the [`withThemeFromJSXProvider`](https://github.com/storybookjs/storybook/blob/next/code/addons/themes/docs/api.md#withthemefromjsxprovider) decorator by adding it to the `decorators` array. +Inside of `.storybook/preview.js`,create a `GlobalStyles` component which includes a `font-family`. Then apply it to your stories with the [`withThemeFromJSXProvider`](https://github.com/storybookjs/storybook/blob/next/code/addons/themes/docs/api.md#withthemefromjsxprovider) decorator by adding it to the `decorators` array. ```js // .storybook/preview.js @@ -69,180 +50,22 @@ export const decorators = [ ]; ``` -
+ -If you already have `Global` in your app, you can import it into `.storybook/preview.js` instead of creating it anew. +If you already have `` in your app, you can import it into `.storybook/preview.js` instead of creating it anew. -
+ -### Using Emotion in components +## 3. Provide your theme(s) -Let’s update some of our example components to use Emotion instead. Open up the Button component in `./src/stories/button.js.` and replace it with the following code: - -```js -// ./src/stories/button.js - -import React from 'react'; -import PropTypes from 'prop-types'; -import { css } from '@emotion/react'; -import styled from '@emotion/styled'; - -const getVariantStyles = ({ primary = false }) => - primary - ? css` - color: white; - background-color: #1ea7fd; - ` - : css` - color: #333; - background-color: transparent; - box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset; - `; - -const getSizeStyles = ({ size = 'medium' }) => { - switch (size) { - case 'small': { - return css` - font-size: 12px; - padding: 10px 16px; - `; - } - case 'large': { - return css` - font-size: 16px; - padding: 12px 24px; - `; - } - default: { - return css` - font-size: 14px; - padding: 11px 20px; - `; - } - } -}; - -/** - * Primary UI component for user interaction - */ -const StyledButton = styled.button` - font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; - font-weight: 700; - border: 0; - border-radius: 3em; - cursor: pointer; - display: inline-block; - line-height: 1; - - ${(props) => getVariantStyles(props)} - ${(props) => getSizeStyles(props)} - ${({ backgroundColor }) => - backgroundColor && - css` - background-color: ${backgroundColor}; - `} -`; - -export const Button = ({ label, ...rest }) => {label}; - -Button.propTypes = { - /** - * Is this the principal call to action on the page? - */ - primary: PropTypes.bool, - /** - * What background color to use - */ - backgroundColor: PropTypes.string, - /** - * How large should the button be? - */ - size: PropTypes.oneOf(['small', 'medium', 'large']), - /** - * Button contents - */ - label: PropTypes.string.isRequired, - /** - * Optional click handler - */ - onClick: PropTypes.func, -}; - -Button.defaultProps = { - backgroundColor: null, - primary: false, - size: 'medium', - onClick: undefined, -}; -``` - -Now the `Button` component is made with Emotion. In Storybook, you won't notice a visual difference. But if you inspect the DOM, you'll see hashed CSS-in-JS classnames. - -### Provide a theme for Emotion in Storybook - -![Switching over to using a theme for emotion in Storybook](https://user-images.githubusercontent.com/18172605/208312571-431a182d-fe2b-40e7-a21f-aaadf55c899e.gif) - -One of the benefits of Emotion is that you can provide a theme to help you style all of your components in a consistent way. Let's create a new `./src/theme.js` and add the following light theme: - -```js -// ./src/theme.js - -export const lightTheme = { - colors: { - background: '#F6F9FC', - backgroundInverse: '#7A8997', - positive: '#E1FFD4', - negative: '#FEDED2', - primary: '#FF4785', - secondary: '#1EA7FD', - tertiary: '#DDDDDD', - text: '#222222', - }, - spacing: { - padding: { - small: 10, - medium: 20, - large: 30, - }, - borderRadius: { - small: 5, - default: 10, - }, - }, - typography: { - type: { - primary: '"Nunito Sans", "Helvetica Neue", Helvetica, Arial, sans-serif', - code: '"SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace', - }, - weight: { - regular: '400', - bold: '700', - extrabold: '800', - black: '900', - }, - size: { - s1: 12, - s2: 14, - s3: 16, - m1: 20, - m2: 24, - m3: 28, - l1: 32, - l2: 40, - l3: 48, - }, - }, -}; -``` - -To share this theme with the components in Storybook, you'll need to provide it to the `withThemeFromJSXProvider` decorator along with `@emotion/styled`'s ThemeProvider component. +To share your theme(s) with the components in Storybook, you'll need to provide them to the `withThemeFromJSXProvider` decorator along with `@emotion/styled`'s `` component. ```js // .storybook/preview.js import { withThemeFromJSXProvider } from '@storybook/addon-themes'; import { Global, css, ThemeProvider } from '@emotion/react'; -import { lightTheme } from '../src/themes'; +import { lightTheme, darkTheme } from '../src/themes'; const GlobalStyles = () => ( - - - - - -### Switch between themes in a click - -Dark mode has become an increasingly popular offering on the web. This can be achieved quickly using themes. - -![Completed Emotion example with theme switcher](https://user-images.githubusercontent.com/18172605/208312563-875ca3b0-e7bc-4401-a445-4553b48068ed.gif) - -Let's add the following dark theme to `theme.js` - -```js -// ./src/theme.js +Now, components made with Emotion will get the theme through the `theme` prop along with the styles inherited from ``. -/* snipped for brevity */ + -export const darkTheme = { - ...lightTheme, - colors: { - background: '#1b1c1d', - backgroundInverse: '#333333', - positive: '#9fd986', - negative: '#df987d', - primary: '#d43369', - secondary: '#1b8bd0', - tertiary: '#DDDDDD', - text: '#FFFFFF', - }, -}; -``` +When you provide more than one theme, a toolbar menu will appear in the Storybook UI to select your desired theme for your stories. -Now, to get the most out of your stories, there should be a way to toggle between themes in a click. + ![Completed Emotion example with theme switcher](https://user-images.githubusercontent.com/18172605/208312563-875ca3b0-e7bc-4401-a445-4553b48068ed.gif) -To add the switcher, add your `darkTheme` object into the the `withThemeFromJSXProvider` decorator themes object - -```js -// .storybook/preview.js -import { Global, css, ThemeProvider } from '@emotion/react'; -import { lightTheme, darkTheme } from '../src/themes'; - -/* snipped for brevity */ - -export const decorators = [ - withThemeFromJSXProvider({ - themes: { - light: lightTheme, - dark: darkTheme, - } - defaultTheme: 'light', - Provider: ThemeProvider, - GlobalStyles, -})]; -``` - -Adding a second theme will create a new toolbar menu to select your desired theme for your stories. - ## Get involved Now you're ready to use Emotion with Storybook. 🎉 From 30b1a75ac11de330fd84809046a8a6ac0bdd2e6c Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Thu, 2 Nov 2023 10:43:33 -0400 Subject: [PATCH 09/28] Add new Callouts to material ui recipe --- src/content/recipes/@mui/material.md | 80 +++++++--------------------- 1 file changed, 18 insertions(+), 62 deletions(-) diff --git a/src/content/recipes/@mui/material.md b/src/content/recipes/@mui/material.md index e4572ee4..7ba50c3f 100644 --- a/src/content/recipes/@mui/material.md +++ b/src/content/recipes/@mui/material.md @@ -1,24 +1,10 @@ -
+ This recipe assumes that you already have a React app using the `@mui/material` package set up with Storybook 7.0 or newer. If you don’t have a project ready, check out this [Stackblitz](https://stackblitz.com/edit/github-ju9knk?file=src/stories/Button.tsx) to follow along. -
+ - - -How to setup Material UI and Storybook - - - -Material UI offers a set of themeable components that devs can use to start building UIs right away. It’s based on Material Design language from Google. - -Storybook is a frontend workbench for building UIs in isolation. By combining Storybook and Material UI, you can build UIs faster without all the grunt work. This recipe shows you how to configure Storybook to load Material UI components and dynamically interact with their API. - -- 📦 Bundle your fonts for fast and consistent rendering -- 🎨 Load your custom theme and add a theme switcher -- ♻️ Reuse Material UI types to auto-generate story controls - -## Install `@storybook/addon-themes` +## 1. Add `@storybook/addon-themes` To get started, you'll need to install [`@storybook/addon-themes`](https://storybook.js.org/addons/@storybook/addon-themes). @@ -28,7 +14,12 @@ Run the following script to install and register the addon: npx storybook@latest add @storybook/addon-themes ``` -### Bundle fonts and icons for better perf +
+ Did the configuration script fail? +

Under the hood, this runs npx @storybook/auto-config themes which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be. To manually add this addon, install it then add it to the addons array in your .storybook/main.ts

+
+ +### 2. Bundle fonts and icons for better perf Material UI depends on two fonts to render as intended, Google’s [`Roboto`](https://fonts.google.com/specimen/Roboto) and [`Material Icons`](https://fonts.google.com/icons?query=Christian+Robertson&icon.style=Outlined&icon.set=Material+Icons). While you can load these fonts directly from the Google Fonts CDN, bundling fonts with Storybook is better for performance. @@ -54,50 +45,10 @@ import '@fontsource/roboto/700.css'; import '@fontsource/material-icons'; ``` -### Load custom themes and add a theme switcher +### 3. Load your theme(s) and global CSS -Material UI comes with a default theme out of the box, but you can also create and provide your own themes. Given the popularity of dark mode, you'll likely end with more than one custom theme. Let's look at how you can load custom themes and switch between them with just a click. +Inside of `.storybook/preview.js`, import ``, ``, and your theme(s), then apply them to your stories with the [`withThemeFromJSXProvider`](https://github.com/storybookjs/storybook/blob/next/code/addons/themes/docs/api.md#withthemefromjsxprovider) decorator by adding it to the `decorators` array. -![Switching between light and dark mode using a theme switcher in the Storybook toolbar](https://lh3.googleusercontent.com/iqsY5lIKADg0xiIxGe7a9qS40R_HP-yNi50PGqO5VuPKVTFoio98LRdM8VvIE40kENxw6nHpu9P5DqkUQNLRJDtGCg9aw-hf4hW8dCtnRdqgxjCLJHOol-04dKjN-cEi-7pBzgy-s8Z8X_ojXMLGXdy04CsttlQevGeAiu6nyGHxzb7VW9FsTnmYQw) - -For example, take these custom light and dark mode themes. - -```js -// src/themes.js - -import { createTheme } from '@mui/material'; -import { blueGrey, cyan, pink } from '@mui/material/colors'; - -export const lightTheme = createTheme({ - palette: { - mode: 'light', - primary: { - main: cyan['A200'], - }, - secondary: { - main: pink['A400'], - }, - }, -}); - -export const darkTheme = createTheme({ - palette: { - mode: 'dark', - primary: { - main: pink['A200'], - }, - secondary: { - main: cyan['A400'], - }, - background: { - default: blueGrey['800'], - paper: blueGrey['700'], - }, - }, -}); -``` - -Then apply the custom themes to our stories. We’ll need to wrap them in Material UI’s `ThemeProvider` using the `withThemeFromJSXProvider` decorator. ```js // .storybook/preview.js @@ -119,9 +70,14 @@ export const decorators = [ })]; ``` -Awesome! Now when Storybook is reloaded, you'll see that our `withThemeFromJSXProvider` decorator is providing our custom light theme by default. + + +When you provide more than one theme, a toolbar menu will appear in the Storybook UI to select your desired theme for your stories. + + + -## Use Material UI prop types for better controls and docs +## 4. Use Material UI prop types for better controls and docs Storybook controls give you graphical controls to manipulate a component’s props. They’re handy for finding edge cases of a component and prototyping in the browser. From f3ca020c5f7fc292373f4b5a96358bef4095d191 Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Thu, 2 Nov 2023 10:47:39 -0400 Subject: [PATCH 10/28] Update Sveltekit recipe with new Callout --- src/content/recipes/@sveltejs/kit.md | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/content/recipes/@sveltejs/kit.md b/src/content/recipes/@sveltejs/kit.md index 5874e7f2..ee8b794a 100644 --- a/src/content/recipes/@sveltejs/kit.md +++ b/src/content/recipes/@sveltejs/kit.md @@ -1,18 +1,12 @@ -
+ This recipe assumes that you are using SvelteKit >= 1.0 as well as Storybook >= 7.0 -
+ - +## Feature support -How to setup SvelteKit and Storybook - - - -Svelte is quickly becoming a major framework in the front-end ecosystem, offering lots of fantastic features for web developers. With SvelteKit, it also provides a powerful meta-framework for applications. At Storybook, we're investing in the Svelte ecosystem to create a seamless and enjoyable experience for users of Svelte and Storybook. - -Fortunately, there is now an easier way to develop isolated components with the new `@storybook/sveltekit` framework package. As an industry-standard for component development, Storybook is proud to offer SvelteKit 1.0 features in a seamless integration. With our package, Storybook automatically mirrors the project settings of both SvelteKit. Here's what you'll get: +With our package, Storybook automatically mirrors the project settings of both SvelteKit. Here's what you'll get: - 📚 Supports imports that use the special `$lib` alias - 👓 Components can read current environment information from `$app/environment` From 9b7f9687a216a19fa5425ce13b101d685d8e511a Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Thu, 2 Nov 2023 10:57:59 -0400 Subject: [PATCH 11/28] Update Bootstrap recipe --- src/content/recipes/bootstrap.md | 44 +++++++++----------------------- 1 file changed, 12 insertions(+), 32 deletions(-) diff --git a/src/content/recipes/bootstrap.md b/src/content/recipes/bootstrap.md index 103fda89..46931b98 100644 --- a/src/content/recipes/bootstrap.md +++ b/src/content/recipes/bootstrap.md @@ -1,4 +1,4 @@ -
+ This recipe assumes that you are using Storybook >=7.0 using the [getting started guide](/docs/react/get-started/install). Don’t have this? Then run: @@ -7,28 +7,9 @@ This recipe assumes that you are using Storybook >=7.0 using the [getting starte npx storybook@latest init ``` -
+ - - -How to setup Bootstrap and Storybook - - - -Bootstrap is a popular library for quickly building UI with ready-made CSS classes, while Storybook is a tool for creating and testing UI components in isolation. This post will show you how to integrate these two tools to create a powerful and flexible development environment for building user interfaces with Bootstrap. - -This post will explain how to: - -1. 🔌 Setup Bootstrap in Storybook using CSS or Sass -2. 🎨 Switch betweens themes in a click - -If you’d like to see the example code of this recipe, check out the [example repository](https://github.com/Integrayshaun/bootstrap-storybook-example) on GitHub. Let's get started! - -![Completed styled-components example with theme switcher](https://raw.githubusercontent.com/Integrayshaun/bootstrap-storybook-example/main/.storybook/demo-recording.gif) - -## How to setup `Bootstrap` - -### CSS +## 1. Import `Bootstrap` Import the Bootstrap files in your `.storybook/preview.js` file. @@ -53,19 +34,13 @@ export const parameters = { }; ``` -### Sass + -If you're using Sass in a Webpack based Storybook (Other than Next or Angular), you'll need to install the [`@storybook/addon-styling-webpack`](https://storybook.js.org/addons/@storybook/addon-styling-webpack) addon. +Check out our [Sass recipe](/docs/react/recipes/sass) for instructions on how to configure Storybook to work with Sass. -Run the following script to install and register the addon: + -```shell -npx storybook@latest add @storybook/addon-styling-webpack -``` - -This will run a configuration script that will walk you through setting up the addon. If prompted, select `Sass` in the configuration options. - -## Add a theme switcher +## 2. Add a theme switcher Bootstrap now ships with a dark mode that you can activate by adding a `[data-bs-theme]` data attribute to a parent element. @@ -77,6 +52,11 @@ Run the following script to install and register the addon: npx storybook@latest add @storybook/addon-themes ``` +
+ Did the configuration script fail? +

Under the hood, this runs npx @storybook/auto-config themes which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be. To manually add this addon, install it then add it to the addons array in your `.storybook/main.ts`

+
+ Then, to enable switching between these modes in a click for your stories, use our `withThemeByDataAttribute` decorator by adding the following code to your `.storybook/preview.js` file. ```js From 85f21dbb93a6238cddffc0e6032a1e9db531e4dc Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Thu, 2 Nov 2023 11:01:34 -0400 Subject: [PATCH 12/28] Add new callouts to VE recipe --- src/content/recipes/@vanilla-extract/css.md | 24 ++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/content/recipes/@vanilla-extract/css.md b/src/content/recipes/@vanilla-extract/css.md index 25f1611b..7fe75f5b 100644 --- a/src/content/recipes/@vanilla-extract/css.md +++ b/src/content/recipes/@vanilla-extract/css.md @@ -1,4 +1,4 @@ -
+ This recipe assumes that you are using Storybook >= 7.0. If you haven't set up Storybook yet, run the following command in the root of your project: @@ -6,23 +6,16 @@ This recipe assumes that you are using Storybook >= 7.0. If you haven't set up S npx storybook@latest init ``` -
+ - - -How to setup Vanilla Extract and Storybook - - - -Vanilla Extract Uses TypeScript as your CSS preprocessor. Allowing you to write type‑safe, locally scoped classes, variables and themes, then generate static CSS files at build time. Storybook is an industry-standard tool for developing and testing UI components in isolation. ## Configure your Storybook builder -
+ If you're already using Vanilla Extract in your project, you may already have these dependencies installed. -
+ First of all, install the required dependencies: @@ -52,10 +45,17 @@ npx storybook@latest add @storybook/addon-styling-webpack This will run a configuration script that will walk you through setting up the addon. If prompted, select `Vanilla Extract` as your CSS processor. -### Manually configure Webpack +
+ Did the configuration script fail? +

Under the hood, this runs npx @storybook/auto-config styling which should read your project and try to configure your Storybook Webpack for your desired tools. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be.

+
+ + For an example of manual configuration, you can view a full example on [Stackblitz](https://stackblitz.com/edit/sb-vanilla-extract-webpack?file=.storybook/main.ts). + + ## Get involved Now you're ready to use Vanilla Extract with Storybook. 🎉 If you use Vanilla Extract at work, we'd love your feedback on the Vanilla Extract + Storybook experience. From 37388d3b6bca27e44f453f8b8c5d330b37abaa90 Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Thu, 2 Nov 2023 11:06:45 -0400 Subject: [PATCH 13/28] Add new callouts to Less recipe --- src/content/recipes/less.md | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/content/recipes/less.md b/src/content/recipes/less.md index ec4d45e4..46569c52 100644 --- a/src/content/recipes/less.md +++ b/src/content/recipes/less.md @@ -1,4 +1,4 @@ -
+ This recipe assumes that you are using Storybook >= 7.0. If you haven't set up Storybook yet, run the following command in the root of your project: @@ -6,23 +6,17 @@ This recipe assumes that you are using Storybook >= 7.0. If you haven't set up S npx storybook@latest init ``` -
+ - +## 1. Configure your Storybook builder -How to setup Less and Storybook + - +If you are using Vite as your Storybook builder, you can skip to the [next step](#2-import-global-styles). -Less is a popular CSS preprocessor that allows developers to write more maintainable and reusable stylesheets. Storybook is an industry-standard tool for developing and testing UI components in isolation. With the help of the `@storybook/addon-styling` package, developers can easily incorporate Less stylesheets into their Storybook components. + -## Before you begin - -If you are using Vite as your Storybook builder, all you need to do is import your Less files into your `preview.js` file. - -## Configure your Storybook builder - -If you use Webpack to build your Storybook you'll need to install the [`@storybook/addon-styling-webpack`](https://storybook.js.org/addons/@storybook/addon-styling-webpack) addon. +Firstly, install the [`@storybook/addon-styling-webpack`](https://storybook.js.org/addons/@storybook/addon-styling-webpack) addon. Run the following script to install and register the addon: @@ -32,7 +26,12 @@ npx storybook@latest add @storybook/addon-styling-webpack This will run a configuration script that will walk you through setting up the addon. When prompted, select `Less` from the configuration options. -## Import global styles +
+ Did the configuration script fail? +

Under the hood, this runs npx @storybook/auto-config styling which should read your project and try to configure your Storybook Webpack for your desired tools. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be. You can find manual configuration instruction for Less here.

+
+ +## 2. Import global styles If you have any global styles you would like to expose for your stories, you can now import them into your `preview.js` file: From 8da29d7e915bba11878d02a250b839b69df962fb Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Thu, 2 Nov 2023 11:21:30 -0400 Subject: [PATCH 14/28] Update Next recipe with new callouts --- src/content/recipes/next.md | 548 +++++++++++++++++++++++++++++++++--- 1 file changed, 515 insertions(+), 33 deletions(-) diff --git a/src/content/recipes/next.md b/src/content/recipes/next.md index 5ea791b2..0afb292f 100644 --- a/src/content/recipes/next.md +++ b/src/content/recipes/next.md @@ -1,27 +1,13 @@ -
+ This recipe assumes that you are using Next.js >= 12.x as well as Storybook >= 7.x -
+ - +## Setup your project -How to setup Next.js and Storybook - - -Tens of thousands of websites and apps rely on Next.js for its powerful features, and the latest release of version 13 has brought many improvements, particularly in routing and image optimization. However, transitioning your existing Next app, along with its integrations, can be a daunting task. - -Fortunately, there is now an easier way to develop isolated components with the new `@storybook/nextjs` framework package. As an industry-standard for component development, Storybook is proud to offer Next.js 13 features in a seamless integration. With our package, Storybook automatically mirrors the project settings of both Next.js 12 and 13. Here's what you'll get: - -- 🔀 Routing -- 🖼 Image optimization -- ⤵️ Absolute imports -- 🎨 Styling -- 🎛 Webpack & Babel config -- 💫 and [more](https://github.com/storybookjs/storybook/blob/next/code/frameworks/nextjs/README.md#supported-features)! - -## In a project without Storybook +### In a project without Storybook Follow the prompts after running this command in your Next.js project's root directory: @@ -29,7 +15,7 @@ Follow the prompts after running this command in your Next.js project's root dir npx storybook@latest init ``` -## In a project with Storybook +### In a project with Storybook This framework is designed to work with Storybook 7. If you’re not already using v7, upgrade with this command: @@ -37,11 +23,11 @@ This framework is designed to work with Storybook 7. If you’re not already usi npx storybook@latest upgrade ``` -### Automatic migration +#### Automatic migration When running the upgrade command above, you should get a prompt asking you to migrate to `@storybook/nextjs`, which should handle everything for you. In case that auto-migration does not work for your project, refer to the manual migration below. -### Manual migration +#### Manual migration Install the framework: @@ -77,26 +63,382 @@ export default { ], }; ``` +## Framework Options + +You can be pass an options object for additional configuration if needed. + +For example: + +```js +// .storybook/main.js +import * as path from 'path'; + +export default { + // ... + framework: { + name: '@storybook/nextjs', + options: { + image: { + loading: 'eager', + }, + nextConfigPath: path.resolve(__dirname, '../next.config.js'), + }, + }, +}; +``` + +- `image`: Props to pass to every instance of `next/image` +- `nextConfigPath`: The absolute path to the `next.config.js` + +## Next.js's Image Component + +[next/image](https://nextjs.org/docs/api-reference/next/image) is [notoriously difficult](https://github.com/vercel/next.js/issues/18393) to get working with Storybook. This framework allows you to use Next.js's `Image` component with no configuration! + +### Local Images + +[Local images](https://nextjs.org/docs/basic-features/image-optimization#local-images) work just fine! Keep in mind that this feature was [only added in Next.js v11](https://nextjs.org/blog/next-11#automatic-size-detection-local-images). + +```js +import Image from 'next/image'; +import profilePic from '../public/me.png'; + +function Home() { + return ( + <> +

My Homepage

+ Picture of the author +

Welcome to my homepage!

+ + ); +} +``` + +### Remote Images + +[Remote images](https://nextjs.org/docs/basic-features/image-optimization#remote-images) also work just fine! + +```js +import Image from 'next/image'; + +export default function Home() { + return ( + <> +

My Homepage

+ Picture of the author +

Welcome to my homepage!

+ + ); +} +``` + +## Next.js Font Optimization + +[next/font](https://nextjs.org/docs/basic-features/font-optimization) is partially supported in Storybook. The packages `next/font/google` and `next/font/local` are supported. + +### next/font/google + +You don't have to do anything. `next/font/google` is supported out of the box. + +### next/font/local + +For local fonts you have to define the [src](https://nextjs.org/docs/api-reference/next/font#src) property. +The path is relative to the directory where the font loader function is called. + +If the following component defines your localFont like this: + +```js +// src/components/MyComponent.js +import localFont from 'next/font/local'; + +const localRubikStorm = localFont({ src: './fonts/RubikStorm-Regular.ttf' }); +``` + +You have to tell Storybook where the `fonts` directory is located. The `from` value is relative to the `.storybook` directory. The `to` value is relative to the execution context of Storybook. Very likely it is the root of your project. + +```js +// .storybook/main.js +export default { + ... + "staticDirs": [ + { + from: '../src/components/fonts', + to: 'src/components/fonts' + } + ], +} +``` + +### Not supported features of `next/font` + +The following features are not supported (yet). Support for these features might be planned for the future: + +- [Support font loaders configuration in next.config.js](https://nextjs.org/docs/basic-features/font-optimization#specifying-a-subset) +- [fallback](https://nextjs.org/docs/api-reference/next/font#fallback) option +- [adjustFontFallback](https://nextjs.org/docs/api-reference/next/font#adjustfontfallback) option +- [declarations](https://nextjs.org/docs/api-reference/next/font#declarations) option +- [preload](https://nextjs.org/docs/api-reference/next/font#preload) option gets ignored. Storybook handles Font loading its own way. +- [display](https://nextjs.org/docs/api-reference/next/font#display) option gets ignored. All fonts are loaded with display set to "block" to make Storybook load the font properly. + +### Mocking fonts during testing + +Occasionally fetching fonts from Google may fail as part of your Storybook build step. It is highly recommended to mock these requests, as those failures can cause your pipeline to fail as well. Next.js [supports mocking fonts](https://github.com/vercel/next.js/blob/725ddc7371f80cca273779d37f961c3e20356f95/packages/font/src/google/fetch-css-from-google-fonts.ts#L36) via a JavaScript module located where the env var `NEXT_FONT_GOOGLE_MOCKED_RESPONSES` references. + +For example, using [GitHub Actions](https://www.chromatic.com/docs/github-actions): + +```shell + - uses: chromaui/action@v1 + env: + #👇 the location of mocked fonts to use + NEXT_FONT_GOOGLE_MOCKED_RESPONSES: ${{ github.workspace }}/mocked-google-fonts.js + with: + projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} + token: ${{ secrets.GITHUB_TOKEN }} +``` + +Your mocked fonts will look something like this: + +```js +// mocked-google-fonts.js +//👇 Mocked responses of google fonts with the URL as the key +module.exports = { + 'https://fonts.googleapis.com/css?family=Inter:wght@400;500;600;800&display=block': ` + /* cyrillic-ext */ + @font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: block; + src: url(https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZJhiJ-Ek-_EeAmM.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; + } + /* more font declarations go here */ + /* latin */ + @font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: block; + src: url(https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZ9hiJ-Ek-_EeA.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; + }`, +}; +``` + +## Next.js Routing + +[Next.js's router](https://nextjs.org/docs/routing/introduction) is automatically stubbed for you so that when the router is interacted with, all of its interactions are automatically logged to the Actions ctions panel if you have the [Storybook actions addon](https://storybook.js.org/docs/react/essentials/actions). + + + +When using Next.js 13+, you should only use `next/router` in the `pages` directory. In the `app` directory, it is necessary to use `next/navigation`. + + + +### Overriding defaults + +Per-story overrides can be done by adding a `nextjs.router` property onto the story [parameters](https://storybook.js.org/docs/react/writing-stories/parameters). The framework will shallowly merge whatever you put here into the router. + +```js +// SomeComponentThatUsesTheRouter.stories.js +import SomeComponentThatUsesTheRouter from './SomeComponentThatUsesTheRouter'; + +export default { + component: SomeComponentThatUsesTheRouter, +}; + +// If you have the actions addon, +// you can interact with the links and see the route change events there +export const Example = { + parameters: { + nextjs: { + router: { + pathname: '/profile/[id]', + asPath: '/profile/1', + query: { + id: '1', + }, + }, + }, + }, +}; +``` + +### Global Defaults + +Global defaults can be set in [preview.js](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) and will be shallowly merged with the default router. + +```js +// .storybook/preview.js + +export const parameters = { + nextjs: { + router: { + pathname: '/some-default-path', + asPath: '/some-default-path', + query: {}, + }, + }, +}; +``` + +### Default Router + +The default values on the stubbed router are as follows (see [globals](https://storybook.js.org/docs/react/essentials/toolbars-and-globals#globals) for more details on how globals work) + +```ts +const defaultRouter = { + push(...args) { + action('nextRouter.push')(...args); + return Promise.resolve(true); + }, + replace(...args) { + action('nextRouter.replace')(...args); + return Promise.resolve(true); + }, + reload(...args) { + action('nextRouter.reload')(...args); + }, + back(...args) { + action('nextRouter.back')(...args); + }, + forward() { + action('nextRouter.forward')(); + }, + prefetch(...args) { + action('nextRouter.prefetch')(...args); + return Promise.resolve(); + }, + beforePopState(...args) { + action('nextRouter.beforePopState')(...args); + }, + events: { + on(...args) { + action('nextRouter.events.on')(...args); + }, + off(...args) { + action('nextRouter.events.off')(...args); + }, + emit(...args) { + action('nextRouter.events.emit')(...args); + }, + }, + // The locale should be configured [globally](https://storybook.js.org/docs/react/essentials/toolbars-and-globals#globals) + locale: globals?.locale, + asPath: '/', + basePath: '/', + isFallback: false, + isLocaleDomain: false, + isReady: true, + isPreview: false, + route: '/', + pathname: '/', + query: {}, +}; +``` + +### Actions Integration Caveats + +If you override a function, you lose the automatic actions integration and have to build it out yourself. -## Configuring next/navigation +```js +// .storybook/preview.js -Next.js 13 introduced the experimental app directory with new features and conventions. It brings support for nested routes and layouts. +export const parameters = { + nextjs: { + router: { + push() { + // The default implementation that logs the action into the Actions panel is lost + }, + }, + }, +}; +``` -If your story uses components in the app directory and they are importing modules from `next/navigation`, you have to tell Storybook to use the correct mocked router context by setting the `nextjs.appDirectory` parameter to `true`: +Doing this yourself looks something like this (make sure you install the `@storybook/addon-actions` package): ```js +// .storybook/preview.js +import { action } from '@storybook/addon-actions'; + +export const parameters = { + nextjs: { + router: { + push(...args) { + // Custom logic can go here + // This logs to the Actions panel + action('nextRouter.push')(...args); + // Return whatever you want here + return Promise.resolve(true); + }, + }, + }, +}; +``` + +## Next.js Navigation + + + +Please note that [next/navigation](https://beta.nextjs.org/docs/upgrade-guide#step-5-migrating-routing-hooks) can only be used in components/pages in the `app` directory of Next.js 13+. + + + +### Set `nextjs.appDirectory` to `true` + +If your story imports components that use `next/navigation`, you need to set the parameter `nextjs.appDirectory` to `true` in your Story: + +```js +// SomeComponentThatUsesTheRouter.stories.js +import SomeComponentThatUsesTheNavigation from './SomeComponentThatUsesTheNavigation'; + +export default { + component: SomeComponentThatUsesTheNavigation, +}; + export const Example = { parameters: { nextjs: { appDirectory: true, }, }, +}, +``` + +If your Next.js project uses the `app` directory for every page (in other words, it does not have a `pages` directory), you can set the parameter `nextjs.appDirectory` to `true` in the [preview.js](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) file to apply it to all stories. + +```js +// .storybook/preview.js + +export const parameters = { + nextjs: { + appDirectory: true, + }, }; ``` -The Navigation provider is configured with some defaults. You can override those defaults by setting the parameter for `nextjs.navigation`: +The parameter `nextjs.appDirectory` defaults to `false` if not set. + +### Overriding defaults + +Per-story overrides can be done by adding a `nextjs.navigation` property onto the story [parameters](https://storybook.js.org/docs/react/writing-stories/parameters). The framework will shallowly merge whatever you put here into the router. ```js +// SomeComponentThatUsesTheNavigation.stories.js +import SomeComponentThatUsesTheNavigation from './SomeComponentThatUsesTheNavigation'; + +export default { + component: SomeComponentThatUsesTheNavigation, +}; + +// If you have the actions addon, +// you can interact with the links and see the route change events there export const Example = { parameters: { nextjs: { @@ -104,7 +446,7 @@ export const Example = { navigation: { pathname: '/profile', query: { - user: 'santa', + user: '1', }, }, }, @@ -112,25 +454,165 @@ export const Example = { }; ``` -Take a look at the [AppRouterProvider](https://github.com/storybookjs/storybook/blob/next/code/frameworks/nextjs/src/routing/app-router-provider.tsx#L15) for all available parameters. +### Global Defaults -## Configuring next/router +Global defaults can be set in [preview.js](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) and will be shallowly merged with the default router. -Within the pages directory, you should continue to use imports from `next/router` for routing purposes. If you want to configure the Router provider, you can do so by setting the `nextjs.router` parameter: +```js +// .storybook/preview.js + +export const parameters = { + nextjs: { + appDirectory: true, + navigation: { + pathname: '/some-default-path', + }, + }, +}; +``` + +### `useSelectedLayoutSegment` `useSelectedLayoutSegments` and `useParams` hook + +The `useSelectedLayoutSegment` `useSelectedLayoutSegments` and `useParams` hooks are supported in Storybook. You have to set the `nextjs.navigation.segments` parameter to return the segments or the params you want to use. ```js -export const Example = { +// SomeComponentThatUsesTheNavigation.stories.js +import SomeComponentThatUsesTheNavigation from './SomeComponentThatUsesTheNavigation'; + +export default { + component: SomeComponentThatUsesTheNavigation, parameters: { nextjs: { - router: { - basePath: '/profile', + appDirectory: true, + navigation: { + segments: ['dashboard', 'analytics'] }, }, }, }; + +export const Example = {}; + +// SomeComponentThatUsesTheNavigation.js +import { useSelectedLayoutSegment, useSelectedLayoutSegments, useParams } from 'next/navigation'; + +export default function SomeComponentThatUsesTheNavigation() { + const segment = useSelectedLayoutSegment(); // dashboard + const segments = useSelectedLayoutSegments(); // ["dashboard", "analytics"] + const params = useParams(); // {} + ... +} ``` -Take a look at the [PageRouterProvider](https://github.com/storybookjs/storybook/blob/next/code/frameworks/nextjs/src/routing/page-router-provider.tsx#L18) for all available parameters. +To use `useParams`, you have to use a two string elements array for a segment, the first array element is the param key and the second array element is the param value. + +```js +// SomeComponentThatUsesParams.stories.js +import SomeComponentThatUsesParams from './SomeComponentThatUsesParams'; + +export default { + component: SomeComponentThatUsesParams, + parameters: { + nextjs: { + appDirectory: true, + navigation: { + segments: [ + ['slug', 'hello'], + ['framework', 'nextjs'], + ] + }, + }, + }, +}; + +export const Example = {}; + +// SomeComponentThatUsesParams.js +import { useSelectedLayoutSegment, useSelectedLayoutSegments, useParams } from 'next/navigation'; + +export default function SomeComponentThatUsesParams() { + const segment = useSelectedLayoutSegment(); // hello + const segments = useSelectedLayoutSegments(); // ["hello", "nextjs"] + const params = useParams(); // { slug: "hello", framework: "nextjs" } + ... +} +``` + +The default value of `nextjs.navigation.segments` is `[]` if not set. + +### Default Navigation Context + +The default values on the stubbed navigation context are as follows: + +```ts +const defaultNavigationContext = { + push(...args) { + action('nextNavigation.push')(...args); + }, + replace(...args) { + action('nextNavigation.replace')(...args); + }, + forward(...args) { + action('nextNavigation.forward')(...args); + }, + back(...args) { + action('nextNavigation.back')(...args); + }, + prefetch(...args) { + action('nextNavigation.prefetch')(...args); + }, + refresh: () => { + action('nextNavigation.refresh')(); + }, + pathname: '/', + query: {}, +}; +``` + +### Actions Integration Caveats + +If you override a function, you lose the automatic action tab integration and have to build it out yourself. + +```js +// .storybook/preview.js + +export const parameters = { + nextjs: { + appDirectory: true, + navigation: { + push() { + // The default implementation that logs the action into the Actions panel is lost + }, + }, + }, +}; +``` + +Doing this yourself looks something like this (make sure you install the `@storybook/addon-actions` package): + +```js +// .storybook/preview.js +import { action } from '@storybook/addon-actions'; + +export const parameters = { + nextjs: { + appDirectory: true, + navigation: { + push(...args) { + // Custom logic can go here + // This logs to the Actions panel + action('nextNavigation.push')(...args); + // Return whatever you want here + return Promise.resolve(true); + }, + }, + }, +}; +``` + +## Next.js Head + +[next/head](https://nextjs.org/docs/api-reference/next/head) is supported out of the box. You can use it in your stories like you would in your Next.js application. Please keep in mind, that the Head children are placed into the head element of the iframe that Storybook uses to render your stories. ## Get involved From 7ce2f75c0fc8181195c534bbd09f3336bf8340f6 Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Thu, 2 Nov 2023 11:25:33 -0400 Subject: [PATCH 15/28] Update Pinia recipe with new Callout --- src/content/recipes/pinia.md | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/content/recipes/pinia.md b/src/content/recipes/pinia.md index 084b7218..1c9b3de0 100644 --- a/src/content/recipes/pinia.md +++ b/src/content/recipes/pinia.md @@ -1,4 +1,4 @@ -
+ This recipe assumes that you are using Vue 3 and Storybook >= 7.x. If you haven't upgraded yet, run the following command: @@ -6,19 +6,9 @@ This recipe assumes that you are using Vue 3 and Storybook >= 7.x. If you haven' npx storybook@latest upgrade ``` -
+ - - -How to setup Pinia and Storybook - - - -Pinia is the recommended standard for state management in Vue. It gives you a lightweight and type-safe way to handle global state for your applications. This recipe will show you how to integrate [Pinia](https://pinia.vuejs.org/) into Storybook so that you can test your state connected components. - -If you want to look at a full example, look at this [awesome repo](https://github.com/chakAs3/vue3-pinia-storybook/tree/main) built by [Chakir Qatab (ChakAs3)](https://github.com/chakAs3). - -## Initialize Pinia +## 1. Initialize Pinia Inside of `.storybook/preview.ts`, import and initialize Pinia. @@ -47,7 +37,7 @@ const preview: Preview = { }; ``` -## Register Pinia +## 2. Register Pinia Import Storybook's setup function that lets you register tools with Storybook's Vue app instance. @@ -80,6 +70,12 @@ const preview: Preview = { }; ``` + + +If you want to look at a full example, look at this [awesome repo](https://github.com/chakAs3/vue3-pinia-storybook/tree/main) built by [Chakir Qatab (ChakAs3)](https://github.com/chakAs3). + + + ## Get involved Now you're ready to use Pinia with Storybook. 🎉 If you use Pinia at work, we'd love your feedback on the Pinia + Storybook experience. From 39e6c10a72dd588b39061df96435884cb6bb8a97 Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Thu, 2 Nov 2023 11:30:52 -0400 Subject: [PATCH 16/28] Update React-i18n recipe --- .../RecipesDetailScreen.js | 4 +-- src/content/recipes/react-i18next.md | 28 ++++++------------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/src/components/screens/IntegrationsCatalog/RecipesDetailScreen/RecipesDetailScreen.js b/src/components/screens/IntegrationsCatalog/RecipesDetailScreen/RecipesDetailScreen.js index 781c5dac..ad246536 100644 --- a/src/components/screens/IntegrationsCatalog/RecipesDetailScreen/RecipesDetailScreen.js +++ b/src/components/screens/IntegrationsCatalog/RecipesDetailScreen/RecipesDetailScreen.js @@ -65,7 +65,7 @@ const AddonsCallout = styled.div` padding: ${spacing.padding.medium}px; border-radius: ${spacing.borderRadius.small}px; display: flex; - flex-direction: row; + flex-direction: column; background: ${background.positive}; box-shadow: ${rgba(color.positive, 0.1)} 0 0 0 1px inset; @@ -272,7 +272,7 @@ export const RecipesDetailScreen = ({ path, location, pageContext }) => {
)} - + - -How to setup React i18next and Storybook - - - -Most developers use [`i18next`](https://www.i18next.com/), a popular JavaScript library that lets apps define separate files for each supported locale. It detects a user’s language preferences and region, and only loads the detected locale. - -Instead of being passed to components as inputs, the locale is shared globally through context. Let’s use i18next to extend Storybook with a locale switcher in the toolbar to choose which locale is shared with your components. - -Follow along using the [code examples](https://github.com/i18next/react-i18next/tree/master/example/storybook) in the react-i18next GitHub repository. - -![Switching locale between English, German, and Arabic in Storybook](https://storybookblog.ghost.io/content/images/2022/09/finished-switcher.gif) - -### Prerequisites + Before we begin, ensure that you have a working React app using [`react-i18next`](https://github.com/i18next/react-i18next) which is set up with Storybook 6.0 or newer. If you need resources to set these up, I’ve included some recommendations below: @@ -20,9 +6,11 @@ Before we begin, ensure that you have a working React app using [`react-i18next` - [Configure i18next language detector](https://react.i18next.com/latest/using-with-hooks) - [Getting started with Storybook](https://storybook.js.org/tutorials/intro-to-storybook/) -Or if you'd prefer a video, check out **Chantastic's** awesome video on adding i18next to your React app. +Or if you'd prefer a video, check out [**Chantastic's** awesome video]() on adding i18next to your React app. + + -### 1. Expose i18next to Storybook +## 1. Expose i18next to Storybook To make your translations available in your stories, you’ll first need to expose your i18next instance to Storybook. Here’s an example of an i18next instance from the `./src/i18n.js` file being used in my React app. @@ -54,7 +42,7 @@ To expose this instance to Storybook, we can import it into the `./.storybook/pr import i18n from '../src/i18n'; ``` -### 2. Wrap your stories with the i18next provider +## 2. Wrap your stories with the i18next provider Now that Storybook has access to i18next, we need to share that with our stories. To do that we’re going to make a decorator to wrap our stories in. @@ -85,7 +73,7 @@ Sweet! Our stories officially have access to our translations. If we change the ![Manually changing the locale from English to French](https://storybookblog.ghost.io/content/images/2022/09/manual-change.gif) -### 3. Add a locale switcher +## 3. Add a locale switcher Hardcoding your locale is annoying and won’t be helpful to anyone viewing your deployed Storybook, so let’s add a locale switcher to the Storybook toolbar. If you want to learn more about switchers, check out **Yann Braga’s** article on [adding a theme switcher](https://storybook.js.org/blog/how-to-add-a-theme-switcher-to-storybook/). @@ -148,7 +136,7 @@ Voila— a fully functioning locale switcher for your stories powered by react-i ![Switching between English and German using the locale switcher](https://storybookblog.ghost.io/content/images/2022/09/en-to-de.gif) -### 4. Set document direction +## 4. Set document direction Some languages are not read from left to right like English is. Arabic, for example, is read from right to left. HTML has built-in support for this with the `dir` attribute. From b26132461586a82b7fe37e0f7152fa3c8c2e399e Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Thu, 2 Nov 2023 14:01:41 -0400 Subject: [PATCH 17/28] Update remaining recipes --- src/content/recipes/react-i18next.md | 2 +- src/content/recipes/styled-components.md | 281 ++--------------------- src/content/recipes/vuetify.md | 95 +------- 3 files changed, 29 insertions(+), 349 deletions(-) diff --git a/src/content/recipes/react-i18next.md b/src/content/recipes/react-i18next.md index f5f8ccdc..fca27471 100644 --- a/src/content/recipes/react-i18next.md +++ b/src/content/recipes/react-i18next.md @@ -6,7 +6,7 @@ Before we begin, ensure that you have a working React app using [`react-i18next` - [Configure i18next language detector](https://react.i18next.com/latest/using-with-hooks) - [Getting started with Storybook](https://storybook.js.org/tutorials/intro-to-storybook/) -Or if you'd prefer a video, check out [**Chantastic's** awesome video]() on adding i18next to your React app. +Or if you'd prefer a video, check out [**Chantastic's** awesome video](https://youtu.be/sr0Pahym3VM?feature=shared) on adding i18next to your React app.
diff --git a/src/content/recipes/styled-components.md b/src/content/recipes/styled-components.md index 14314def..942f5de1 100644 --- a/src/content/recipes/styled-components.md +++ b/src/content/recipes/styled-components.md @@ -1,4 +1,4 @@ -
+ This recipe assumes that you have a React app using styled-components and have just set up Storybook >=7.0 using the [getting started guide](/docs/react/get-started/install). Don’t have this? Follow styled-components' [installation instructions](https://styled-components.com/docs/basics#installation) then run: @@ -7,28 +7,9 @@ This recipe assumes that you have a React app using styled-components and have j npx storybook@latest init ``` -
+
- - -How to setup styled-components and Storybook - - - -styled-components is a popular library for building UI components with CSS-in-JS, while Storybook is a tool for creating and testing UI components in isolation. This post will show you how to integrate these two tools to create a powerful and flexible development environment for building user interfaces with styled-components. - -This post will explain how to: - -1. 🔌 Setup `GlobalStyles` -2. 🧱 Use styled-components in your components -3. 💅 Use a theme in your stories -4. 🎨 Switch betweens themes in a click - -If you’d like to see the example code of this recipe, check out the [example repository](https://github.com/Integrayshaun/styled-components-recipe) on GitHub. Let's get started! - -![Completed styled-components example with theme switcher](https://user-images.githubusercontent.com/18172605/208312563-875ca3b0-e7bc-4401-a445-4553b48068ed.gif) - -## Install `@storybook/addon-themes` +## 1. Add `@storybook/addon-themes` Run the following script to install and register the addon: @@ -38,13 +19,14 @@ npx storybook@latest add @storybook/addon-themes This will run a configuration script that will walk you through setting up the addon. When prompted, select `styled-components` from the configuration options. -### How to setup `GlobalStyles` +
+ Did the configuration script fail? +

Under the hood, this runs npx @storybook/auto-config themes which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be. To manually add this addon, install it then add it to the addons array in your .storybook/main.ts

+
-UIs often have a set of global styles that are applied to every component like CSS resets, `font-size`, `font-family`, and colors. +## 2. Provide `GlobalStyles` -In styled-components, use the [`createGlobalStyle`](https://styled-components.com/docs/api#createglobalstyle) API to scope styles globally instead of locally (which is the library's default behavior). - -Open `.storybook/preview.js` and create a `GlobalStyles` component which includes a `font-family`. Then apply it to your stories with the [`withThemeFromJSXProvider`](https://github.com/storybookjs/storybook/blob/next/code/addons/themes/docs/api.md#withthemefromjsxprovider) decorator by adding it to the `decorators` array. +In `.storybook/preview.js`, create a `GlobalStyles` component which includes a `font-family`. Then apply it to your stories with the [`withThemeFromJSXProvider`](https://github.com/storybookjs/storybook/blob/next/code/addons/themes/docs/api.md#withthemefromjsxprovider) decorator by adding it to the `decorators` array. ```js // .storybook/preview.js @@ -64,244 +46,15 @@ export const decorators = [ ]; ``` -
+ -If you already have `GlobalStyles` in your app, you can import it into `.storybook/preview.js` instead of creating it anew. +If you already have `` in your app, you can import it into `.storybook/preview.js` instead of creating it anew. -
+
-### Use styled-components in components -Let’s update some of our example components to use styled-components instead. Open up the Button component in `./src/stories/button.js.` and replace it with the following code: - -```js -// ./src/stories/button.js - -import React from 'react'; -import PropTypes from 'prop-types'; -import styled, { css } from 'styled-components'; - -const getVariantStyles = ({ primary = false }) => - primary - ? css` - color: white; - background-color: #1ea7fd; - ` - : css` - color: #333; - background-color: transparent; - box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset; - `; - -const getSizeStyles = ({ size = 'medium' }) => { - switch (size) { - case 'small': { - return css` - font-size: 12px; - padding: 10px 16px; - `; - } - case 'large': { - return css` - font-size: 16px; - padding: 12px 24px; - `; - } - default: { - return css` - font-size: 14px; - padding: 11px 20px; - `; - } - } -}; - -/** - * Primary UI component for user interaction - */ -const StyledButton = styled.button` - font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; - font-weight: 700; - border: 0; - border-radius: 3em; - cursor: pointer; - display: inline-block; - line-height: 1; - - ${(props) => getVariantStyles(props)} - ${(props) => getSizeStyles(props)} - ${({ backgroundColor }) => - backgroundColor && - css` - background-color: ${backgroundColor}; - `} -`; - -export const Button = ({ label, ...rest }) => {label}; - -Button.propTypes = { - /** - * Is this the principal call to action on the page? - */ - primary: PropTypes.bool, - /** - * What background color to use - */ - backgroundColor: PropTypes.string, - /** - * How large should the button be? - */ - size: PropTypes.oneOf(['small', 'medium', 'large']), - /** - * Button contents - */ - label: PropTypes.string.isRequired, - /** - * Optional click handler - */ - onClick: PropTypes.func, -}; - -Button.defaultProps = { - backgroundColor: null, - primary: false, - size: 'medium', - onClick: undefined, -}; -``` - -Now the `Button` component is made with styled-components. In Storybook, you won't notice a visual difference. But if you inspect the DOM, you'll see hashed CSS-in-JS classnames. - -### Provide a theme for styled-components in Storybook - -![Switching over to using a theme for styled-components in Storybook](https://user-images.githubusercontent.com/18172605/208312571-431a182d-fe2b-40e7-a21f-aaadf55c899e.gif) - -One of the benefits of styled-components is that you can provide a theme to help you style all of your components in a consistent way. Let's create a new `./src/theme.js` and add the following light theme: - -```js -// ./src/theme.js - -export const lightTheme = { - colors: { - background: '#F6F9FC', - backgroundInverse: '#7A8997', - positive: '#E1FFD4', - negative: '#FEDED2', - primary: '#FF4785', - secondary: '#1EA7FD', - tertiary: '#DDDDDD', - text: '#222222', - }, - spacing: { - padding: { - small: 10, - medium: 20, - large: 30, - }, - borderRadius: { - small: 5, - default: 10, - }, - }, - typography: { - type: { - primary: '"Nunito Sans", "Helvetica Neue", Helvetica, Arial, sans-serif', - code: '"SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace', - }, - weight: { - regular: '400', - bold: '700', - extrabold: '800', - black: '900', - }, - size: { - s1: 12, - s2: 14, - s3: 16, - m1: 20, - m2: 24, - m3: 28, - l1: 32, - l2: 40, - l3: 48, - }, - }, -}; -``` - -To share this theme with the components in Storybook, you'll need to provide it to the `withThemeFromJSXProvider` decorator along with `styled-components` ThemeProvider component. - -```js -// .storybook/preview.js -import { withThemeFromJSXProvider } from '@storybook/addon-themes'; -import { createGlobalStyle, ThemeProvider } from 'styled-components'; - -import { lightTheme } from '../src/themes'; - -const GlobalStyles = createGlobalStyle` - body { - font-family: "Nunito Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; - } -`; - -export const decorators = [ - withThemeFromJSXProvider({ - themes: { - light: lightTheme, - } - defaultTheme: 'light', - Provider: ThemeProvider, - GlobalStyles, -})]; -``` - -Now, components made with styled-components will get the theme through the `theme` prop along with the styles inherited from `GlobalStyles`. Let's update the example components to use the theme. - - - - - - - -### Switch between themes in a click - -Dark mode has become an increasingly popular offering on the web. This can be achieved quickly using themes. - -![Completed styled-components example with theme switcher](https://user-images.githubusercontent.com/18172605/208312563-875ca3b0-e7bc-4401-a445-4553b48068ed.gif) - -Let's add the following dark theme to `theme.js` - -```js -// ./src/theme.js - -/* snipped for brevity */ - -export const darkTheme = { - ...lightTheme, - colors: { - background: '#1b1c1d', - backgroundInverse: '#333333', - positive: '#9fd986', - negative: '#df987d', - primary: '#d43369', - secondary: '#1b8bd0', - tertiary: '#DDDDDD', - text: '#FFFFFF', - }, -}; -``` - -Now, to get the most out of your stories, there should be a way to toggle between themes in a click. - -![Completed styled-components example with theme switcher](https://user-images.githubusercontent.com/18172605/208312563-875ca3b0-e7bc-4401-a445-4553b48068ed.gif) - -To add the switcher, add your `darkTheme` object into the the `withThemeFromJSXProvider` decorator themes object +## 3. Provide your theme(s) +To share your theme(s) with the components in Storybook, you'll need to provide them to the `withThemeFromJSXProvider` decorator along with `styled-components` `` component. ```js // .storybook/preview.js @@ -324,7 +77,11 @@ export const decorators = [ })]; ``` -Adding a second theme will create a new toolbar menu to select your desired theme for your stories. + + +When you provide more than one theme, a toolbar menu will appear in the Storybook UI to select your desired theme for your stories. + + ## Get involved diff --git a/src/content/recipes/vuetify.md b/src/content/recipes/vuetify.md index 88b84091..e7ca50a9 100644 --- a/src/content/recipes/vuetify.md +++ b/src/content/recipes/vuetify.md @@ -1,4 +1,4 @@ -
+ This recipe assumes that you have a Vue 3 app using Vuetify v3 and have just set up Storybook 7.0 using the [getting started guide](/docs/7.0/vue/get-started/install). Don’t have this? Follow Vuetify’s [installation instructions](https://next.vuetifyjs.com/en/getting-started/installation/#installation) then run: @@ -7,28 +7,9 @@ This recipe assumes that you have a Vue 3 app using Vuetify v3 and have just set npx storybook@latest init ``` -
+
- - -How to setup Vuetify and Storybook - - - -Vuetify is a popular UI framework for Vue.js that provides a variety of pre-designed components, while Storybook is a tool for creating and testing UI components in isolation. -This post will show you how to integrate these two tools to create a powerful and flexible development environment for building user interfaces with Vuetify. - -This post will explain how to: - -1. 🔌 Setup Vuetify with Storybook -2. 🧱 Use Vuetify in your components -3. 🎨 Switch Vuetify themes in a click - -If you’d like to see the example code of this recipe, check out the [example repository](https://github.com/Integrayshaun/vue3-vuetify-storybook-recipe-example) on GitHub. Let's get started! - -![Completed Vuetify example with theme switcher](https://user-images.githubusercontent.com/18172605/207120625-bedb53ec-eac4-4690-a06a-5d0579cb9809.gif) - -## Register Vuetify in Storybook +## 1. Register Vuetify in Storybook To get started, you'll need to add Vuetify’s fontloader and plugin to your Storybook configuration. To do this, add the following to your `.storybook/preview.js` file: @@ -47,6 +28,8 @@ setup((app) => { Here `registerPlugins` loads Vuetify’s fonts and registers all of its components with Storybook’s Vue app. +## 2. Create a story wrapper component + Next you will need to wrap your stories in Vuetify's `v-app` component in order to use some of it's larger layout components like `v-app-bar`. To do this, create a component in `.storybook/` called `StoryWrapper.vue` @@ -63,6 +46,7 @@ To do this, create a component in `.storybook/` called `StoryWrapper.vue` ``` +## 3. Create a `withVuetifyTheme` decorator Now create a storybook [decorator](/docs/vue/writing-stories/decorators) to wrap your stories in your StoryWrapper component. Below I created a new file in `.storybook` called `withVuetifyTheme.decorator.js`. @@ -88,7 +72,7 @@ export const withVuetifyTheme = (storyFn, context) => { }; ``` -Finally, give this decorator to Storybook in your `preview.js` file. +Now, give this decorator to Storybook in your `preview.js` file. ```js // .storybook/preview.js @@ -106,72 +90,11 @@ setup((app) => { export const decorators = [withVuetifyTheme]; ``` -## Using Vuetify Components - -Let’s update some of our example components to use Vuetify instead. Open up the Button component in `./src/stories/button.vue`. - -![Unchanged example button component from Storybook init](https://user-images.githubusercontent.com/18172605/207120859-0383d01a-6448-4327-94c9-dcb1ec86f868.png) - -Currently, it’s not looking very Vuetiful so let’s make some changes. Replace the contents of `./src/stories/Button.vue` with the following code: - -```vue - - - -``` - -Now looking back at Storybook, the Vuetify button is being used. It even changed in the page-level stories. -![Converting the example button into a Vuetify button](https://user-images.githubusercontent.com/18172605/207120996-cdd40459-97f7-4e40-9782-719c45c38d11.gif) - -## Add a theme switcher tool using `globalTypes` +## 4. Add a theme switcher tool Vuetify comes out of the box with a light and dark theme that you can override or add to. To get the most out of your stories, you should have a way to toggle between all of your themes. -![Switching to Vuetify's dark theme in Storybook](https://user-images.githubusercontent.com/18172605/207121142-dbc27018-02d1-438d-b3d1-1d45e265e16a.gif) - To add our switcher, declare a [global type](/docs/vue/essentials/toolbars-and-globals) named `theme` in `.storybook/preview.js` and give it a list of supported themes to choose from. ```js @@ -197,7 +120,7 @@ export const globalTypes = { This code will create a new toolbar menu to select your desired theme for your stories. -## Add a `withVuetifyTheme` decorator +## 5. Add a theme provider There needs to be a way to tell Vuetify to use the theme selected in the toolbar. This can be done by updating our `StoryWrapper` component and `withVuetifyTheme` decorator From bab73b5488caec7b38f53c5fd67ebffea7494ca5 Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Thu, 2 Nov 2023 14:11:43 -0400 Subject: [PATCH 18/28] Remove TODO --- .../RecipesDetailScreen/RecipesDetailScreen.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/screens/IntegrationsCatalog/RecipesDetailScreen/RecipesDetailScreen.js b/src/components/screens/IntegrationsCatalog/RecipesDetailScreen/RecipesDetailScreen.js index ad246536..81845b29 100644 --- a/src/components/screens/IntegrationsCatalog/RecipesDetailScreen/RecipesDetailScreen.js +++ b/src/components/screens/IntegrationsCatalog/RecipesDetailScreen/RecipesDetailScreen.js @@ -60,7 +60,6 @@ const ReadMe = styled.section` min-width: 0; `; -// TODO: UPDATE THIS TO NEW COMPONENT const AddonsCallout = styled.div` padding: ${spacing.padding.medium}px; border-radius: ${spacing.borderRadius.small}px; From 5957555f96a45ca053470335d989718857aa2ec2 Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Fri, 3 Nov 2023 13:01:31 -0400 Subject: [PATCH 19/28] Fix styling issues for Docs MDX styling --- src/components/basics/Callout/Callout.tsx | 27 ++++++++++++------- .../screens/DocsScreen/DocsScreen.tsx | 12 +-------- src/styles/formatting.js | 4 ++- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/components/basics/Callout/Callout.tsx b/src/components/basics/Callout/Callout.tsx index 7aa93c9a..8092cf59 100644 --- a/src/components/basics/Callout/Callout.tsx +++ b/src/components/basics/Callout/Callout.tsx @@ -16,6 +16,11 @@ const VARIANT_COLORS: Record = warning: { background: background.warning, border: rgba(color.warning, 0.1) }, }; +const VARIANT_DEFAULT_ICON: Partial> = { + info: 'ℹ️', + warning: '⚠️', +}; + interface CalloutContainerProps { variant: Variant; } @@ -85,12 +90,16 @@ export interface CalloutProps extends CalloutContainerProps { children: string; } -export const Callout = ({ title, icon, children, variant, ...props }: CalloutProps) => ( - - {icon && {icon}} - - {title && } - {children} - - -); +export const Callout = ({ title, icon, children, variant, ...props }: CalloutProps) => { + const appliedIcon = icon ?? VARIANT_DEFAULT_ICON[variant]; + + return ( + + {appliedIcon && {appliedIcon}} + + {title && } + {children} + + + ); +}; diff --git a/src/components/screens/DocsScreen/DocsScreen.tsx b/src/components/screens/DocsScreen/DocsScreen.tsx index e6cc2022..3308c0d9 100644 --- a/src/components/screens/DocsScreen/DocsScreen.tsx +++ b/src/components/screens/DocsScreen/DocsScreen.tsx @@ -37,14 +37,6 @@ const MDWrapper = styled.main` flex: 1; `; -const StyledHighlight = styled(Highlight)` - -webkit-text-size-adjust: none; - - > * > *:last-child { - margin-bottom: 0; - } -`; - const NextSubheading = styled(Subheading)` color: ${color.mediumdark}; font-size: ${typography.size.s2}px; @@ -239,9 +231,7 @@ function DocsScreen({ data, pageContext, location }) { Callout, }} > - - {body} - + {body} diff --git a/src/styles/formatting.js b/src/styles/formatting.js index 824ed3da..a6137636 100644 --- a/src/styles/formatting.js +++ b/src/styles/formatting.js @@ -274,7 +274,8 @@ export const mdFormatting = css` code { font-size: 87.5%; - color: inherit; + color: ${color.darkest}; + white-space: pre; } pre { @@ -284,6 +285,7 @@ export const mdFormatting = css` padding: 1em; font-size: inherit; + color: ${color.darkest}; code { padding: 0; From 1ad2a0ffa734f866d7885a1f9b13cdfa2b970080 Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Mon, 6 Nov 2023 09:10:15 -0500 Subject: [PATCH 20/28] Run through chatGPT for spelling and grammar --- src/content/recipes/@emotion/styled.md | 4 ++-- src/content/recipes/@mui/material.md | 6 +++--- src/content/recipes/@vanilla-extract/css.md | 2 +- src/content/recipes/less.md | 2 +- src/content/recipes/sass.md | 6 +++--- src/content/recipes/styled-components.md | 4 ++-- src/content/recipes/tailwindcss.md | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/content/recipes/@emotion/styled.md b/src/content/recipes/@emotion/styled.md index c6d9dbda..806c383c 100644 --- a/src/content/recipes/@emotion/styled.md +++ b/src/content/recipes/@emotion/styled.md @@ -21,12 +21,12 @@ npx storybook@latest add @storybook/addon-themes
Did the configuration script fail? -

Under the hood, this runs npx @storybook/auto-config themes which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be. To manually add this addon, install it then add it to the addons array in your .storybook/main.ts

+

Under the hood, this runs npx @storybook/auto-config themes, which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository so that we can make this as good as possible. To manually add this addon, install it, and then add it to the addons array in your .storybook/main.ts.

## 2. Provide `GlobalStyles` -Inside of `.storybook/preview.js`,create a `GlobalStyles` component which includes a `font-family`. Then apply it to your stories with the [`withThemeFromJSXProvider`](https://github.com/storybookjs/storybook/blob/next/code/addons/themes/docs/api.md#withthemefromjsxprovider) decorator by adding it to the `decorators` array. +Inside of `.storybook/preview.js`, create a `` component that includes a `font-family`. Then apply it to your stories with the [`withThemeFromJSXProvider` decorator](https://github.com/storybookjs/storybook/blob/next/code/addons/themes/docs/api.md#withthemefromjsxprovider) by adding it to the decorators array. ```js // .storybook/preview.js diff --git a/src/content/recipes/@mui/material.md b/src/content/recipes/@mui/material.md index 7ba50c3f..de08cebd 100644 --- a/src/content/recipes/@mui/material.md +++ b/src/content/recipes/@mui/material.md @@ -16,7 +16,7 @@ npx storybook@latest add @storybook/addon-themes
Did the configuration script fail? -

Under the hood, this runs npx @storybook/auto-config themes which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be. To manually add this addon, install it then add it to the addons array in your .storybook/main.ts

+

Under the hood, this runs npx @storybook/auto-config themes, which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository so that we can make this as good as possible. To manually add this addon, install it, and then add it to the addons array in your .storybook/main.ts.

### 2. Bundle fonts and icons for better perf @@ -33,7 +33,7 @@ To get started, install the fonts as dependencies. yarn add @fontsource/roboto @fontsource/material-icons ``` -Then import the CSS files into `.storybook/preview.js`, the entrypoint of your Storybook. +Then import the CSS files into `.storybook/preview.js, the entry point of your Storybook. ```javascript // .storybook/preview.js @@ -81,7 +81,7 @@ When you provide more than one theme, a toolbar menu will appear in the Storyboo Storybook controls give you graphical controls to manipulate a component’s props. They’re handy for finding edge cases of a component and prototyping in the browser. -Usually, you have to manually configure controls. But if you’re using Typescript, you can reuse Material UI’s component prop types to auto generate story controls. As a bonus, this will also automatically populate the prop table in your documentation tab. +Usually, you have to manually configure controls. But if you’re using Typescript, you can reuse Material UI’s component prop types to auto-generate story controls. As a bonus, this will also automatically populate the prop table in your documentation tab. ![Changing the button components props using Storybook controls](https://storybookblog.ghost.io/content/images/2022/10/2022-10-04-15.48.29.gif) diff --git a/src/content/recipes/@vanilla-extract/css.md b/src/content/recipes/@vanilla-extract/css.md index 7fe75f5b..62860199 100644 --- a/src/content/recipes/@vanilla-extract/css.md +++ b/src/content/recipes/@vanilla-extract/css.md @@ -47,7 +47,7 @@ This will run a configuration script that will walk you through setting up the a
Did the configuration script fail? -

Under the hood, this runs npx @storybook/auto-config styling which should read your project and try to configure your Storybook Webpack for your desired tools. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be.

+

Under the hood, this command runs npx @storybook/auto-config styling, which is responsible for reading your project and attempting to configure your Storybook Webpack for your desired tools. If running that command directly does not resolve your issue, please consider filing a bug report on the @storybook/auto-config repository so that we can further improve it. For manual configuration instructions for Less, you can refer to the documentation here.

diff --git a/src/content/recipes/less.md b/src/content/recipes/less.md index 46569c52..d13c785d 100644 --- a/src/content/recipes/less.md +++ b/src/content/recipes/less.md @@ -28,7 +28,7 @@ This will run a configuration script that will walk you through setting up the a
Did the configuration script fail? -

Under the hood, this runs npx @storybook/auto-config styling which should read your project and try to configure your Storybook Webpack for your desired tools. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be. You can find manual configuration instruction for Less here.

+

Under the hood, this command runs npx @storybook/auto-config styling, which is responsible for reading your project and attempting to configure your Storybook Webpack for your desired tools. If running that command directly does not resolve your issue, please consider filing a bug report on the @storybook/auto-config repository so that we can further improve it. For manual configuration instructions for Less, you can refer to the documentation here.

## 2. Import global styles diff --git a/src/content/recipes/sass.md b/src/content/recipes/sass.md index 1ea7d624..0f01f2bd 100644 --- a/src/content/recipes/sass.md +++ b/src/content/recipes/sass.md @@ -2,12 +2,12 @@ -Some configurations of Storybook already come pre-configured to support Sass. If your project meets the following, then you can skip to the [next step](#2-import-global-styles). +Some Storybook configurations are pre-configured to support Sass. If your project meets any of the following criteria, you can skip to the [next step](#2-import-global-styles). - Storybook >= 7.x with the `vite` builder. - Storybook >= 7.x with the `@storybook/nextjs` framework. - Storybook >= 7.x with the `@storybook/preset-create-react-app` and `react-scripts@2.x.x` or higher. -- Storybook >= 7.x with the `@storybook/angular` framework. +- Storybook >= 7.x with the `@storybook/angular` framework @@ -21,7 +21,7 @@ This will run a configuration script that will walk you through setting up the a
Did the configuration script fail? -

Under the hood, this runs npx @storybook/auto-config styling which should read your project and try to configure your Storybook Webpack for your desired tools. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be. You can find manual configuration instruction for Sass here.

+

Under the hood, this command runs npx @storybook/auto-config styling, which is responsible for reading your project and attempting to configure your Storybook Webpack for your desired tools. If running that command directly does not resolve your issue, please consider filing a bug report on the @storybook/auto-config repository so that we can further improve it. For manual configuration instructions for Sass, you can refer to the documentation here.

## 2. Import global styles diff --git a/src/content/recipes/styled-components.md b/src/content/recipes/styled-components.md index 942f5de1..eca5d78b 100644 --- a/src/content/recipes/styled-components.md +++ b/src/content/recipes/styled-components.md @@ -21,12 +21,12 @@ This will run a configuration script that will walk you through setting up the a
Did the configuration script fail? -

Under the hood, this runs npx @storybook/auto-config themes which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be. To manually add this addon, install it then add it to the addons array in your .storybook/main.ts

+

Under the hood, this runs npx @storybook/auto-config themes, which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository so that we can make this as good as possible. To manually add this addon, install it, and then add it to the addons array in your .storybook/main.ts.

## 2. Provide `GlobalStyles` -In `.storybook/preview.js`, create a `GlobalStyles` component which includes a `font-family`. Then apply it to your stories with the [`withThemeFromJSXProvider`](https://github.com/storybookjs/storybook/blob/next/code/addons/themes/docs/api.md#withthemefromjsxprovider) decorator by adding it to the `decorators` array. +In `.storybook/preview.js`, create a ` component that includes a `font-family`. Then apply it to your stories with the [`withThemeFromJSXProvider`](https://github.com/storybookjs/storybook/blob/next/code/addons/themes/docs/api.md#withthemefromjsxprovider) decorator by adding it to the `decorators` array. ```js // .storybook/preview.js diff --git a/src/content/recipes/tailwindcss.md b/src/content/recipes/tailwindcss.md index 43087599..805c1b48 100644 --- a/src/content/recipes/tailwindcss.md +++ b/src/content/recipes/tailwindcss.md @@ -38,7 +38,7 @@ This will run a configuration script that will walk you through setting up the a
Did the configuration script fail? -

Under the hood, this runs npx @storybook/auto-config styling which should read your project and try to configure your Storybook Webpack for your desired tools. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be. You can find manual configuration instruction for PostCSS here.

+

Under the hood, this command runs npx @storybook/auto-config styling, which is responsible for reading your project and attempting to configure your Storybook Webpack for your desired tools. If running that command directly does not resolve your issue, please consider filing a bug report on the @storybook/auto-config repository so that we can further improve it. For manual configuration instructions for PostCSS, you can refer to the documentation here.

## 2. Provide Tailwind to stories @@ -102,7 +102,7 @@ This will run a configuration script that will walk you through setting up the a
Did the configuration script fail? -

Under the hood, this runs npx @storybook/auto-config themes which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be. To manually add this addon, install it then add it to the addons array in your `.storybook/main.ts`

+

Under the hood, this runs npx @storybook/auto-config themes, which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository so that we can make this as good as possible. To manually add this addon, install it, and then add it to the addons array in your .storybook/main.ts.

### 3.1. Toggle themes by class name From 58d599dbdf75e3ac04a4c53f428df0b2f3bd5925 Mon Sep 17 00:00:00 2001 From: Shaun Evening Date: Mon, 6 Nov 2023 14:23:08 -0500 Subject: [PATCH 21/28] Apply suggestions from code review Co-authored-by: Kyle Gach --- src/content/recipes/@emotion/styled.md | 4 ++-- src/content/recipes/@mui/material.md | 2 +- src/content/recipes/@vanilla-extract/css.md | 2 +- src/content/recipes/bootstrap.md | 2 +- src/content/recipes/next.md | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/content/recipes/@emotion/styled.md b/src/content/recipes/@emotion/styled.md index 806c383c..a4656305 100644 --- a/src/content/recipes/@emotion/styled.md +++ b/src/content/recipes/@emotion/styled.md @@ -29,7 +29,7 @@ npx storybook@latest add @storybook/addon-themes Inside of `.storybook/preview.js`, create a `` component that includes a `font-family`. Then apply it to your stories with the [`withThemeFromJSXProvider` decorator](https://github.com/storybookjs/storybook/blob/next/code/addons/themes/docs/api.md#withthemefromjsxprovider) by adding it to the decorators array. ```js -// .storybook/preview.js +// .storybook/preview.jsx import { withThemeFromJSXProvider } from '@storybook/addon-themes'; import { Global, css } from '@emotion/react'; @@ -61,7 +61,7 @@ If you already have `` in your app, you can import it into `.storybook To share your theme(s) with the components in Storybook, you'll need to provide them to the `withThemeFromJSXProvider` decorator along with `@emotion/styled`'s `` component. ```js -// .storybook/preview.js +// .storybook/preview.jsx import { withThemeFromJSXProvider } from '@storybook/addon-themes'; import { Global, css, ThemeProvider } from '@emotion/react'; diff --git a/src/content/recipes/@mui/material.md b/src/content/recipes/@mui/material.md index de08cebd..edd0a5ef 100644 --- a/src/content/recipes/@mui/material.md +++ b/src/content/recipes/@mui/material.md @@ -33,7 +33,7 @@ To get started, install the fonts as dependencies. yarn add @fontsource/roboto @fontsource/material-icons ``` -Then import the CSS files into `.storybook/preview.js, the entry point of your Storybook. +Then import the CSS files into `.storybook/preview.js`, the entry point of your Storybook. ```javascript // .storybook/preview.js diff --git a/src/content/recipes/@vanilla-extract/css.md b/src/content/recipes/@vanilla-extract/css.md index 62860199..a916960b 100644 --- a/src/content/recipes/@vanilla-extract/css.md +++ b/src/content/recipes/@vanilla-extract/css.md @@ -47,7 +47,7 @@ This will run a configuration script that will walk you through setting up the a
Did the configuration script fail? -

Under the hood, this command runs npx @storybook/auto-config styling, which is responsible for reading your project and attempting to configure your Storybook Webpack for your desired tools. If running that command directly does not resolve your issue, please consider filing a bug report on the @storybook/auto-config repository so that we can further improve it. For manual configuration instructions for Less, you can refer to the documentation here.

+

Under the hood, this command runs npx @storybook/auto-config styling, which is responsible for reading your project and attempting to configure your Storybook Webpack for your desired tools. If running that command directly does not resolve your issue, please consider filing a bug report on the @storybook/auto-config repository so that we can further improve it. For manual configuration instructions for Less, you can refer to the documentation.

diff --git a/src/content/recipes/bootstrap.md b/src/content/recipes/bootstrap.md index 46931b98..48e7eaaf 100644 --- a/src/content/recipes/bootstrap.md +++ b/src/content/recipes/bootstrap.md @@ -54,7 +54,7 @@ npx storybook@latest add @storybook/addon-themes
Did the configuration script fail? -

Under the hood, this runs npx @storybook/auto-config themes which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be. To manually add this addon, install it then add it to the addons array in your `.storybook/main.ts`

+

Under the hood, this runs npx @storybook/auto-config themes which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository for that we can make this good as can be. To manually add this addon, install it then add it to the addons array in your .storybook/main.ts.

Then, to enable switching between these modes in a click for your stories, use our `withThemeByDataAttribute` decorator by adding the following code to your `.storybook/preview.js` file. diff --git a/src/content/recipes/next.md b/src/content/recipes/next.md index 0afb292f..94294d30 100644 --- a/src/content/recipes/next.md +++ b/src/content/recipes/next.md @@ -4,7 +4,7 @@ This recipe assumes that you are using Next.js >= 12.x as well as Storybook >= 7
-## Setup your project +## Set up your project ### In a project without Storybook From 12a416e404ed89f2464394668184d6000962c4e5 Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Mon, 6 Nov 2023 14:26:41 -0500 Subject: [PATCH 22/28] Make details consistent --- src/content/recipes/@emotion/styled.md | 2 +- src/content/recipes/@mui/material.md | 2 +- src/content/recipes/styled-components.md | 2 +- src/content/recipes/tailwindcss.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/content/recipes/@emotion/styled.md b/src/content/recipes/@emotion/styled.md index a4656305..680eb2a5 100644 --- a/src/content/recipes/@emotion/styled.md +++ b/src/content/recipes/@emotion/styled.md @@ -21,7 +21,7 @@ npx storybook@latest add @storybook/addon-themes
Did the configuration script fail? -

Under the hood, this runs npx @storybook/auto-config themes, which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository so that we can make this as good as possible. To manually add this addon, install it, and then add it to the addons array in your .storybook/main.ts.

+

Under the hood, this runs npx @storybook/auto-config themes, which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository so that we can further improve it. To manually add this addon, install it, and then add it to the addons array in your .storybook/main.ts.

## 2. Provide `GlobalStyles` diff --git a/src/content/recipes/@mui/material.md b/src/content/recipes/@mui/material.md index edd0a5ef..bfe60a24 100644 --- a/src/content/recipes/@mui/material.md +++ b/src/content/recipes/@mui/material.md @@ -16,7 +16,7 @@ npx storybook@latest add @storybook/addon-themes
Did the configuration script fail? -

Under the hood, this runs npx @storybook/auto-config themes, which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository so that we can make this as good as possible. To manually add this addon, install it, and then add it to the addons array in your .storybook/main.ts.

+

Under the hood, this runs npx @storybook/auto-config themes, which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository so that we can further improve it. To manually add this addon, install it, and then add it to the addons array in your .storybook/main.ts.

### 2. Bundle fonts and icons for better perf diff --git a/src/content/recipes/styled-components.md b/src/content/recipes/styled-components.md index eca5d78b..f1c19802 100644 --- a/src/content/recipes/styled-components.md +++ b/src/content/recipes/styled-components.md @@ -21,7 +21,7 @@ This will run a configuration script that will walk you through setting up the a
Did the configuration script fail? -

Under the hood, this runs npx @storybook/auto-config themes, which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository so that we can make this as good as possible. To manually add this addon, install it, and then add it to the addons array in your .storybook/main.ts.

+

Under the hood, this runs npx @storybook/auto-config themes, which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository so that we can further improve it. To manually add this addon, install it, and then add it to the addons array in your .storybook/main.ts.

## 2. Provide `GlobalStyles` diff --git a/src/content/recipes/tailwindcss.md b/src/content/recipes/tailwindcss.md index 805c1b48..2eaca97a 100644 --- a/src/content/recipes/tailwindcss.md +++ b/src/content/recipes/tailwindcss.md @@ -102,7 +102,7 @@ This will run a configuration script that will walk you through setting up the a
Did the configuration script fail? -

Under the hood, this runs npx @storybook/auto-config themes, which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository so that we can make this as good as possible. To manually add this addon, install it, and then add it to the addons array in your .storybook/main.ts.

+

Under the hood, this runs npx @storybook/auto-config themes, which should read your project and try to configure your Storybook with the correct decorator. If running that command directly does not solve your problem, please file a bug on the @storybook/auto-config repository so that we can further improve it. To manually add this addon, install it, and then add it to the addons array in your .storybook/main.ts.

### 3.1. Toggle themes by class name From bda0e9c27a548d56c2629eec1598e84f90afeacb Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Mon, 6 Nov 2023 14:29:21 -0500 Subject: [PATCH 23/28] Update snippet name to jsx --- src/content/recipes/@mui/material.md | 6 +++--- src/content/recipes/bootstrap.md | 2 +- src/content/recipes/less.md | 2 +- src/content/recipes/next.md | 14 +++++++------- src/content/recipes/react-i18next.md | 12 ++++++------ src/content/recipes/sass.md | 2 +- src/content/recipes/styled-components.md | 4 ++-- src/content/recipes/tailwindcss.md | 6 +++--- src/content/recipes/vuetify.md | 6 +++--- 9 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/content/recipes/@mui/material.md b/src/content/recipes/@mui/material.md index bfe60a24..08a2d9d4 100644 --- a/src/content/recipes/@mui/material.md +++ b/src/content/recipes/@mui/material.md @@ -36,7 +36,7 @@ yarn add @fontsource/roboto @fontsource/material-icons Then import the CSS files into `.storybook/preview.js`, the entry point of your Storybook. ```javascript -// .storybook/preview.js +// .storybook/preview.jsx import '@fontsource/roboto/300.css'; import '@fontsource/roboto/400.css'; @@ -51,7 +51,7 @@ Inside of `.storybook/preview.js`, import ``, `` ```js -// .storybook/preview.js +// .storybook/preview.jsx import { CssBaseline, ThemeProvider } from '@mui/material'; import { withThemeFromJSXProvider } from '@storybook/addon-themes'; import { lightTheme, darkTheme } from '../src/themes.js'; @@ -136,7 +136,7 @@ module.exports = { We also want to update the parameters in `.storybook/preview.js` to show the description and default columns for the controls table. ```js -// .storybook/preview.js +// .storybook/preview.jsx export const parameters = { actions: { argTypesRegex: '^on[A-Z].*' }, diff --git a/src/content/recipes/bootstrap.md b/src/content/recipes/bootstrap.md index 48e7eaaf..b0fcf0d3 100644 --- a/src/content/recipes/bootstrap.md +++ b/src/content/recipes/bootstrap.md @@ -14,7 +14,7 @@ npx storybook@latest init Import the Bootstrap files in your `.storybook/preview.js` file. ```js -// .storybook/preview.js +// .storybook/preview.jsx import 'bootstrap/dist/css/bootstrap.min.css'; // Only import this if you want to use Bootstrap's diff --git a/src/content/recipes/less.md b/src/content/recipes/less.md index d13c785d..2c35e747 100644 --- a/src/content/recipes/less.md +++ b/src/content/recipes/less.md @@ -36,7 +36,7 @@ This will run a configuration script that will walk you through setting up the a If you have any global styles you would like to expose for your stories, you can now import them into your `preview.js` file: ```js -// .storybook/preview.js +// .storybook/preview.jsx import '../src/index.less'; ``` diff --git a/src/content/recipes/next.md b/src/content/recipes/next.md index 94294d30..355c9362 100644 --- a/src/content/recipes/next.md +++ b/src/content/recipes/next.md @@ -275,7 +275,7 @@ export const Example = { Global defaults can be set in [preview.js](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) and will be shallowly merged with the default router. ```js -// .storybook/preview.js +// .storybook/preview.jsx export const parameters = { nextjs: { @@ -348,7 +348,7 @@ const defaultRouter = { If you override a function, you lose the automatic actions integration and have to build it out yourself. ```js -// .storybook/preview.js +// .storybook/preview.jsx export const parameters = { nextjs: { @@ -364,7 +364,7 @@ export const parameters = { Doing this yourself looks something like this (make sure you install the `@storybook/addon-actions` package): ```js -// .storybook/preview.js +// .storybook/preview.jsx import { action } from '@storybook/addon-actions'; export const parameters = { @@ -414,7 +414,7 @@ export const Example = { If your Next.js project uses the `app` directory for every page (in other words, it does not have a `pages` directory), you can set the parameter `nextjs.appDirectory` to `true` in the [preview.js](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) file to apply it to all stories. ```js -// .storybook/preview.js +// .storybook/preview.jsx export const parameters = { nextjs: { @@ -459,7 +459,7 @@ export const Example = { Global defaults can be set in [preview.js](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) and will be shallowly merged with the default router. ```js -// .storybook/preview.js +// .storybook/preview.jsx export const parameters = { nextjs: { @@ -574,7 +574,7 @@ const defaultNavigationContext = { If you override a function, you lose the automatic action tab integration and have to build it out yourself. ```js -// .storybook/preview.js +// .storybook/preview.jsx export const parameters = { nextjs: { @@ -591,7 +591,7 @@ export const parameters = { Doing this yourself looks something like this (make sure you install the `@storybook/addon-actions` package): ```js -// .storybook/preview.js +// .storybook/preview.jsx import { action } from '@storybook/addon-actions'; export const parameters = { diff --git a/src/content/recipes/react-i18next.md b/src/content/recipes/react-i18next.md index fca27471..1f4ae949 100644 --- a/src/content/recipes/react-i18next.md +++ b/src/content/recipes/react-i18next.md @@ -38,7 +38,7 @@ export default i18n; To expose this instance to Storybook, we can import it into the `./.storybook/preview.js` file where Storybook holds its shared story configurations. ```js -// .storybook/preview.js +// .storybook/preview.jsx import i18n from '../src/i18n'; ``` @@ -47,7 +47,7 @@ import i18n from '../src/i18n'; Now that Storybook has access to i18next, we need to share that with our stories. To do that we’re going to make a decorator to wrap our stories in. ```jsx -// .storybook/preview.js +// .storybook/preview.jsx import React, { Suspense } from 'react'; import { I18nextProvider } from 'react-i18next'; import i18n from '../src/i18n'; @@ -80,7 +80,7 @@ Hardcoding your locale is annoying and won’t be helpful to anyone viewing your To do this, we can declare a global variable named `locale` in `.storybook/preview.js` and assign it to a list of supported languages to choose from. ```js -// .storybook/preview.js +// .storybook/preview.jsx /* Snipped for brevity */ @@ -109,7 +109,7 @@ Looking back at Storybook, we can now see that we have a “Locale” switcher a Now let’s update our decorator to change our locale when we select a new language. ```jsx -// .storybook/preview.js +// .storybook/preview.jsx /* Snipped for brevity */ @@ -143,7 +143,7 @@ Some languages are not read from left to right like English is. Arabic, for exam First of all, let's add Arabic as an option in our locale switcher by adding an object into the items array of our globalTypes. ```js -// .storybook/preview.js +// .storybook/preview.jsx /* Snipped for brevity */ @@ -169,7 +169,7 @@ export const globalTypes = { Using i18next’s `dir(lng)` function and `languageChanged` event, we can set the document direction for the selected locale. ```js -// .storybook/preview.js +// .storybook/preview.jsx /* Snipped for brevity */ diff --git a/src/content/recipes/sass.md b/src/content/recipes/sass.md index 0f01f2bd..84d4125b 100644 --- a/src/content/recipes/sass.md +++ b/src/content/recipes/sass.md @@ -29,7 +29,7 @@ This will run a configuration script that will walk you through setting up the a If you have any global styles you would like to expose for your stories, you can now import them into your `preview.js` file: ```js -// .storybook/preview.js +// .storybook/preview.jsx import '../src/index.scss'; ``` diff --git a/src/content/recipes/styled-components.md b/src/content/recipes/styled-components.md index f1c19802..c2e99bf9 100644 --- a/src/content/recipes/styled-components.md +++ b/src/content/recipes/styled-components.md @@ -29,7 +29,7 @@ This will run a configuration script that will walk you through setting up the a In `.storybook/preview.js`, create a ` component that includes a `font-family`. Then apply it to your stories with the [`withThemeFromJSXProvider`](https://github.com/storybookjs/storybook/blob/next/code/addons/themes/docs/api.md#withthemefromjsxprovider) decorator by adding it to the `decorators` array. ```js -// .storybook/preview.js +// .storybook/preview.jsx import { withThemeFromJSXProvider } from '@storybook/addon-themes'; import { createGlobalStyle } from 'styled-components'; @@ -57,7 +57,7 @@ If you already have `` in your app, you can import it into `.sto To share your theme(s) with the components in Storybook, you'll need to provide them to the `withThemeFromJSXProvider` decorator along with `styled-components` `` component. ```js -// .storybook/preview.js +// .storybook/preview.jsx import { createGlobalStyle, ThemeProvider } from 'styled-components'; import { withThemeFromJSXProvider } from '@storybook/addon-themes'; diff --git a/src/content/recipes/tailwindcss.md b/src/content/recipes/tailwindcss.md index 2eaca97a..f0715df2 100644 --- a/src/content/recipes/tailwindcss.md +++ b/src/content/recipes/tailwindcss.md @@ -46,7 +46,7 @@ This will run a configuration script that will walk you through setting up the a Now you can import the `tailwind.css` file into your `.storybook/preview.js` file. This will make Tailwind’s style classes available to all of your stories. ```js -// .storybook/preview.js +// .storybook/preview.jsx import '../src/tailwind.css'; // replace with the name of your tailwind css file ``` @@ -110,7 +110,7 @@ This will run a configuration script that will walk you through setting up the a Add the [`withThemeByClassName`](https://github.com/storybookjs/addon-themes/blob/main/code/addons/themes/docs/api.md#withthemebyclassname) decorator to your Storybook from `@storybook/addon-themes` ```js -// .storybook/preview.js +// .storybook/preview.jsx import { withThemeByClassName } from '@storybook/addon-themes'; /* snipped for brevity */ @@ -131,7 +131,7 @@ export const decorators = [ Add the [`withThemeByDataAttribute`](https://github.com/storybookjs/addon-themes/blob/main/code/addons/themes/docs/api.md#withthemebydataattribute) decorator to your Storybook from `@storybook/addon-themes` ```js -// .storybook/preview.js +// .storybook/preview.jsx import { withThemeByDataAttribute } from '@storybook/addon-themes'; /* snipped for brevity */ diff --git a/src/content/recipes/vuetify.md b/src/content/recipes/vuetify.md index e7ca50a9..cbe3b61e 100644 --- a/src/content/recipes/vuetify.md +++ b/src/content/recipes/vuetify.md @@ -15,7 +15,7 @@ To get started, you'll need to add Vuetify’s fontloader and plugin to your Sto To do this, add the following to your `.storybook/preview.js` file: ```js -// .storybook/preview.js +// .storybook/preview.jsx import { setup } from '@storybook/vue3'; import { registerPlugins } from '../src/plugins'; @@ -75,7 +75,7 @@ export const withVuetifyTheme = (storyFn, context) => { Now, give this decorator to Storybook in your `preview.js` file. ```js -// .storybook/preview.js +// .storybook/preview.jsx import { setup } from '@storybook/vue3'; import { registerPlugins } from '../src/plugins'; @@ -98,7 +98,7 @@ Vuetify comes out of the box with a light and dark theme that you can override o To add our switcher, declare a [global type](/docs/vue/essentials/toolbars-and-globals) named `theme` in `.storybook/preview.js` and give it a list of supported themes to choose from. ```js -// .storybook/preview.js +// .storybook/preview.jsx export const globalTypes = { theme: { From 15a41b77a5e36623c627efb385c13076e576a74f Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Mon, 6 Nov 2023 14:30:10 -0500 Subject: [PATCH 24/28] Remove "both" --- src/content/recipes/@sveltejs/kit.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/recipes/@sveltejs/kit.md b/src/content/recipes/@sveltejs/kit.md index ee8b794a..86242c9d 100644 --- a/src/content/recipes/@sveltejs/kit.md +++ b/src/content/recipes/@sveltejs/kit.md @@ -6,7 +6,7 @@ This recipe assumes that you are using SvelteKit >= 1.0 as well as Storybook >= ## Feature support -With our package, Storybook automatically mirrors the project settings of both SvelteKit. Here's what you'll get: +With our package, Storybook automatically mirrors the project settings of SvelteKit. Here's what you'll get: - 📚 Supports imports that use the special `$lib` alias - 👓 Components can read current environment information from `$app/environment` From 4e6dac9c6845f60dac96fbf0784173eba861f592 Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Mon, 6 Nov 2023 14:35:16 -0500 Subject: [PATCH 25/28] Remove framework options --- src/content/recipes/next.md | 550 ------------------------------------ 1 file changed, 550 deletions(-) diff --git a/src/content/recipes/next.md b/src/content/recipes/next.md index 355c9362..a3d8429a 100644 --- a/src/content/recipes/next.md +++ b/src/content/recipes/next.md @@ -63,556 +63,6 @@ export default { ], }; ``` -## Framework Options - -You can be pass an options object for additional configuration if needed. - -For example: - -```js -// .storybook/main.js -import * as path from 'path'; - -export default { - // ... - framework: { - name: '@storybook/nextjs', - options: { - image: { - loading: 'eager', - }, - nextConfigPath: path.resolve(__dirname, '../next.config.js'), - }, - }, -}; -``` - -- `image`: Props to pass to every instance of `next/image` -- `nextConfigPath`: The absolute path to the `next.config.js` - -## Next.js's Image Component - -[next/image](https://nextjs.org/docs/api-reference/next/image) is [notoriously difficult](https://github.com/vercel/next.js/issues/18393) to get working with Storybook. This framework allows you to use Next.js's `Image` component with no configuration! - -### Local Images - -[Local images](https://nextjs.org/docs/basic-features/image-optimization#local-images) work just fine! Keep in mind that this feature was [only added in Next.js v11](https://nextjs.org/blog/next-11#automatic-size-detection-local-images). - -```js -import Image from 'next/image'; -import profilePic from '../public/me.png'; - -function Home() { - return ( - <> -

My Homepage

- Picture of the author -

Welcome to my homepage!

- - ); -} -``` - -### Remote Images - -[Remote images](https://nextjs.org/docs/basic-features/image-optimization#remote-images) also work just fine! - -```js -import Image from 'next/image'; - -export default function Home() { - return ( - <> -

My Homepage

- Picture of the author -

Welcome to my homepage!

- - ); -} -``` - -## Next.js Font Optimization - -[next/font](https://nextjs.org/docs/basic-features/font-optimization) is partially supported in Storybook. The packages `next/font/google` and `next/font/local` are supported. - -### next/font/google - -You don't have to do anything. `next/font/google` is supported out of the box. - -### next/font/local - -For local fonts you have to define the [src](https://nextjs.org/docs/api-reference/next/font#src) property. -The path is relative to the directory where the font loader function is called. - -If the following component defines your localFont like this: - -```js -// src/components/MyComponent.js -import localFont from 'next/font/local'; - -const localRubikStorm = localFont({ src: './fonts/RubikStorm-Regular.ttf' }); -``` - -You have to tell Storybook where the `fonts` directory is located. The `from` value is relative to the `.storybook` directory. The `to` value is relative to the execution context of Storybook. Very likely it is the root of your project. - -```js -// .storybook/main.js -export default { - ... - "staticDirs": [ - { - from: '../src/components/fonts', - to: 'src/components/fonts' - } - ], -} -``` - -### Not supported features of `next/font` - -The following features are not supported (yet). Support for these features might be planned for the future: - -- [Support font loaders configuration in next.config.js](https://nextjs.org/docs/basic-features/font-optimization#specifying-a-subset) -- [fallback](https://nextjs.org/docs/api-reference/next/font#fallback) option -- [adjustFontFallback](https://nextjs.org/docs/api-reference/next/font#adjustfontfallback) option -- [declarations](https://nextjs.org/docs/api-reference/next/font#declarations) option -- [preload](https://nextjs.org/docs/api-reference/next/font#preload) option gets ignored. Storybook handles Font loading its own way. -- [display](https://nextjs.org/docs/api-reference/next/font#display) option gets ignored. All fonts are loaded with display set to "block" to make Storybook load the font properly. - -### Mocking fonts during testing - -Occasionally fetching fonts from Google may fail as part of your Storybook build step. It is highly recommended to mock these requests, as those failures can cause your pipeline to fail as well. Next.js [supports mocking fonts](https://github.com/vercel/next.js/blob/725ddc7371f80cca273779d37f961c3e20356f95/packages/font/src/google/fetch-css-from-google-fonts.ts#L36) via a JavaScript module located where the env var `NEXT_FONT_GOOGLE_MOCKED_RESPONSES` references. - -For example, using [GitHub Actions](https://www.chromatic.com/docs/github-actions): - -```shell - - uses: chromaui/action@v1 - env: - #👇 the location of mocked fonts to use - NEXT_FONT_GOOGLE_MOCKED_RESPONSES: ${{ github.workspace }}/mocked-google-fonts.js - with: - projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} - token: ${{ secrets.GITHUB_TOKEN }} -``` - -Your mocked fonts will look something like this: - -```js -// mocked-google-fonts.js -//👇 Mocked responses of google fonts with the URL as the key -module.exports = { - 'https://fonts.googleapis.com/css?family=Inter:wght@400;500;600;800&display=block': ` - /* cyrillic-ext */ - @font-face { - font-family: 'Inter'; - font-style: normal; - font-weight: 400; - font-display: block; - src: url(https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZJhiJ-Ek-_EeAmM.woff2) format('woff2'); - unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; - } - /* more font declarations go here */ - /* latin */ - @font-face { - font-family: 'Inter'; - font-style: normal; - font-weight: 400; - font-display: block; - src: url(https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZ9hiJ-Ek-_EeA.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; - }`, -}; -``` - -## Next.js Routing - -[Next.js's router](https://nextjs.org/docs/routing/introduction) is automatically stubbed for you so that when the router is interacted with, all of its interactions are automatically logged to the Actions ctions panel if you have the [Storybook actions addon](https://storybook.js.org/docs/react/essentials/actions). - - - -When using Next.js 13+, you should only use `next/router` in the `pages` directory. In the `app` directory, it is necessary to use `next/navigation`. - - - -### Overriding defaults - -Per-story overrides can be done by adding a `nextjs.router` property onto the story [parameters](https://storybook.js.org/docs/react/writing-stories/parameters). The framework will shallowly merge whatever you put here into the router. - -```js -// SomeComponentThatUsesTheRouter.stories.js -import SomeComponentThatUsesTheRouter from './SomeComponentThatUsesTheRouter'; - -export default { - component: SomeComponentThatUsesTheRouter, -}; - -// If you have the actions addon, -// you can interact with the links and see the route change events there -export const Example = { - parameters: { - nextjs: { - router: { - pathname: '/profile/[id]', - asPath: '/profile/1', - query: { - id: '1', - }, - }, - }, - }, -}; -``` - -### Global Defaults - -Global defaults can be set in [preview.js](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) and will be shallowly merged with the default router. - -```js -// .storybook/preview.jsx - -export const parameters = { - nextjs: { - router: { - pathname: '/some-default-path', - asPath: '/some-default-path', - query: {}, - }, - }, -}; -``` - -### Default Router - -The default values on the stubbed router are as follows (see [globals](https://storybook.js.org/docs/react/essentials/toolbars-and-globals#globals) for more details on how globals work) - -```ts -const defaultRouter = { - push(...args) { - action('nextRouter.push')(...args); - return Promise.resolve(true); - }, - replace(...args) { - action('nextRouter.replace')(...args); - return Promise.resolve(true); - }, - reload(...args) { - action('nextRouter.reload')(...args); - }, - back(...args) { - action('nextRouter.back')(...args); - }, - forward() { - action('nextRouter.forward')(); - }, - prefetch(...args) { - action('nextRouter.prefetch')(...args); - return Promise.resolve(); - }, - beforePopState(...args) { - action('nextRouter.beforePopState')(...args); - }, - events: { - on(...args) { - action('nextRouter.events.on')(...args); - }, - off(...args) { - action('nextRouter.events.off')(...args); - }, - emit(...args) { - action('nextRouter.events.emit')(...args); - }, - }, - // The locale should be configured [globally](https://storybook.js.org/docs/react/essentials/toolbars-and-globals#globals) - locale: globals?.locale, - asPath: '/', - basePath: '/', - isFallback: false, - isLocaleDomain: false, - isReady: true, - isPreview: false, - route: '/', - pathname: '/', - query: {}, -}; -``` - -### Actions Integration Caveats - -If you override a function, you lose the automatic actions integration and have to build it out yourself. - -```js -// .storybook/preview.jsx - -export const parameters = { - nextjs: { - router: { - push() { - // The default implementation that logs the action into the Actions panel is lost - }, - }, - }, -}; -``` - -Doing this yourself looks something like this (make sure you install the `@storybook/addon-actions` package): - -```js -// .storybook/preview.jsx -import { action } from '@storybook/addon-actions'; - -export const parameters = { - nextjs: { - router: { - push(...args) { - // Custom logic can go here - // This logs to the Actions panel - action('nextRouter.push')(...args); - // Return whatever you want here - return Promise.resolve(true); - }, - }, - }, -}; -``` - -## Next.js Navigation - - - -Please note that [next/navigation](https://beta.nextjs.org/docs/upgrade-guide#step-5-migrating-routing-hooks) can only be used in components/pages in the `app` directory of Next.js 13+. - - - -### Set `nextjs.appDirectory` to `true` - -If your story imports components that use `next/navigation`, you need to set the parameter `nextjs.appDirectory` to `true` in your Story: - -```js -// SomeComponentThatUsesTheRouter.stories.js -import SomeComponentThatUsesTheNavigation from './SomeComponentThatUsesTheNavigation'; - -export default { - component: SomeComponentThatUsesTheNavigation, -}; - -export const Example = { - parameters: { - nextjs: { - appDirectory: true, - }, - }, -}, -``` - -If your Next.js project uses the `app` directory for every page (in other words, it does not have a `pages` directory), you can set the parameter `nextjs.appDirectory` to `true` in the [preview.js](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) file to apply it to all stories. - -```js -// .storybook/preview.jsx - -export const parameters = { - nextjs: { - appDirectory: true, - }, -}; -``` - -The parameter `nextjs.appDirectory` defaults to `false` if not set. - -### Overriding defaults - -Per-story overrides can be done by adding a `nextjs.navigation` property onto the story [parameters](https://storybook.js.org/docs/react/writing-stories/parameters). The framework will shallowly merge whatever you put here into the router. - -```js -// SomeComponentThatUsesTheNavigation.stories.js -import SomeComponentThatUsesTheNavigation from './SomeComponentThatUsesTheNavigation'; - -export default { - component: SomeComponentThatUsesTheNavigation, -}; - -// If you have the actions addon, -// you can interact with the links and see the route change events there -export const Example = { - parameters: { - nextjs: { - appDirectory: true, - navigation: { - pathname: '/profile', - query: { - user: '1', - }, - }, - }, - }, -}; -``` - -### Global Defaults - -Global defaults can be set in [preview.js](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) and will be shallowly merged with the default router. - -```js -// .storybook/preview.jsx - -export const parameters = { - nextjs: { - appDirectory: true, - navigation: { - pathname: '/some-default-path', - }, - }, -}; -``` - -### `useSelectedLayoutSegment` `useSelectedLayoutSegments` and `useParams` hook - -The `useSelectedLayoutSegment` `useSelectedLayoutSegments` and `useParams` hooks are supported in Storybook. You have to set the `nextjs.navigation.segments` parameter to return the segments or the params you want to use. - -```js -// SomeComponentThatUsesTheNavigation.stories.js -import SomeComponentThatUsesTheNavigation from './SomeComponentThatUsesTheNavigation'; - -export default { - component: SomeComponentThatUsesTheNavigation, - parameters: { - nextjs: { - appDirectory: true, - navigation: { - segments: ['dashboard', 'analytics'] - }, - }, - }, -}; - -export const Example = {}; - -// SomeComponentThatUsesTheNavigation.js -import { useSelectedLayoutSegment, useSelectedLayoutSegments, useParams } from 'next/navigation'; - -export default function SomeComponentThatUsesTheNavigation() { - const segment = useSelectedLayoutSegment(); // dashboard - const segments = useSelectedLayoutSegments(); // ["dashboard", "analytics"] - const params = useParams(); // {} - ... -} -``` - -To use `useParams`, you have to use a two string elements array for a segment, the first array element is the param key and the second array element is the param value. - -```js -// SomeComponentThatUsesParams.stories.js -import SomeComponentThatUsesParams from './SomeComponentThatUsesParams'; - -export default { - component: SomeComponentThatUsesParams, - parameters: { - nextjs: { - appDirectory: true, - navigation: { - segments: [ - ['slug', 'hello'], - ['framework', 'nextjs'], - ] - }, - }, - }, -}; - -export const Example = {}; - -// SomeComponentThatUsesParams.js -import { useSelectedLayoutSegment, useSelectedLayoutSegments, useParams } from 'next/navigation'; - -export default function SomeComponentThatUsesParams() { - const segment = useSelectedLayoutSegment(); // hello - const segments = useSelectedLayoutSegments(); // ["hello", "nextjs"] - const params = useParams(); // { slug: "hello", framework: "nextjs" } - ... -} -``` - -The default value of `nextjs.navigation.segments` is `[]` if not set. - -### Default Navigation Context - -The default values on the stubbed navigation context are as follows: - -```ts -const defaultNavigationContext = { - push(...args) { - action('nextNavigation.push')(...args); - }, - replace(...args) { - action('nextNavigation.replace')(...args); - }, - forward(...args) { - action('nextNavigation.forward')(...args); - }, - back(...args) { - action('nextNavigation.back')(...args); - }, - prefetch(...args) { - action('nextNavigation.prefetch')(...args); - }, - refresh: () => { - action('nextNavigation.refresh')(); - }, - pathname: '/', - query: {}, -}; -``` - -### Actions Integration Caveats - -If you override a function, you lose the automatic action tab integration and have to build it out yourself. - -```js -// .storybook/preview.jsx - -export const parameters = { - nextjs: { - appDirectory: true, - navigation: { - push() { - // The default implementation that logs the action into the Actions panel is lost - }, - }, - }, -}; -``` - -Doing this yourself looks something like this (make sure you install the `@storybook/addon-actions` package): - -```js -// .storybook/preview.jsx -import { action } from '@storybook/addon-actions'; - -export const parameters = { - nextjs: { - appDirectory: true, - navigation: { - push(...args) { - // Custom logic can go here - // This logs to the Actions panel - action('nextNavigation.push')(...args); - // Return whatever you want here - return Promise.resolve(true); - }, - }, - }, -}; -``` - -## Next.js Head - -[next/head](https://nextjs.org/docs/api-reference/next/head) is supported out of the box. You can use it in your stories like you would in your Next.js application. Please keep in mind, that the Head children are placed into the head element of the iframe that Storybook uses to render your stories. ## Get involved From 0b8a3235a5f8f2806523fd49fe8f6ed8ec267b61 Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Mon, 6 Nov 2023 14:35:29 -0500 Subject: [PATCH 26/28] Make small changes from suggestions --- src/content/recipes/vuetify.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/content/recipes/vuetify.md b/src/content/recipes/vuetify.md index cbe3b61e..f550d218 100644 --- a/src/content/recipes/vuetify.md +++ b/src/content/recipes/vuetify.md @@ -30,11 +30,12 @@ Here `registerPlugins` loads Vuetify’s fonts and registers all of its componen ## 2. Create a story wrapper component -Next you will need to wrap your stories in Vuetify's `v-app` component in order to use some of it's larger layout components like `v-app-bar`. +Next, you will need to wrap your stories in Vuetify's `v-app` component in order to use some of its larger layout components like `v-app-bar`. To do this, create a component in `.storybook/` called `StoryWrapper.vue` ```vue +