There is no documentation how to integrate storybook and styled components on the new config system
previously I had a .storybook/config.js:
import { configure } from "@storybook/react"
import { action } from "@storybook/addon-actions"
import { addDecorator } from '@storybook/react';
import React from 'react';
import GlobalStyle from '../src/components/GlobalStyle';
function withGlobalStyles(storyFn) {
return (
<React.Fragment>
<GlobalStyle />
{storyFn()}
</React.Fragment>
);
}
addDecorator(withGlobalStyles);
// automatically import all files ending in *.stories.js
configure(require.context("../src", true, /\.stories\.js$/), module)
// Gatsby's Link overrides:
// Gatsby defines a global called ___loader to prevent its method calls from creating console errors you override it here
global.___loader = {
enqueue: () => {},
hovering: () => {},
}
// Gatsby internal mocking to prevent unnecessary errors in storybook testing environment
global.__PATH_PREFIX__ = ""
// This is to utilized to override the window.___navigate method Gatsby defines and uses to report what path a Link would be taking us to if it wasn't inside a storybook
window.___navigate = pathname => {
action("NavigateTo:")(pathname)
}
How do this translates to a .storybook/main.js config?
Hi @cristianaortiga !
Just to clarify - are you referring to a change in the storybook config system? Or did some change in Gatsby caused a problem for you? If so, could you please share what did you try so far and what exactly failed to work for you?
@vladar or anyone else. Technically this is not a Gatsby issue, but more of Storybook issue, with the release of Storybook 5.3 there were some configuration changes and this issue raises a valid question on how you could integrate both frameworks. Issues have popped regarding both frameworks and how to integrate them, i personally helped one person in the past. With that you and or anyone else on the OSS team if you don't mind keeping this open for a while longer while this is better triaged it would be awesome. @cristianaortiga i'm keeping tabs on this and also i'm going over the documentation. Currently i have a pr that is bumping the LearnStorybook site's packages and story format. That particular pr is going to be subject to change as Storybook 5.3 just released and i need to update it and see if i can find a way to make them work together. In the meantime if you happen to stumble on a way to fix it, please feel free to share as not only me but the rest of both communities might benefit from it
@jonniebigodes Thanks for providing more context! We do have a section in docs about Storybook so we should definitely update it if things had changed.
Would be great to get more info on this and of course PRs are welcome!
@vladar i've used that piece of documentation in the past and that will need to be updated. When me or @cristianaortiga finds a suitable solution to get both frameworks working together i think a pr will be made. @cristianaortiga if i can make them work together i'll report back and provide a detailed description on the steps i took and if you're willing as you brought it to Gatsby's attention i'll leave it to you to make the pr and update the documentation so that both communities benefit from it and with that probably get some free swag, are you ok with that?
Sure @jonniebigodes, that seems fair!
@cristianaortiga we're in good shape, i have it running, tomorrow i'll make some more tests and report back with a detailed comment on how i was able to make both packages work together. And then you'll pick from there and make the pr updating the documentation, in the meantime i would like for you to go over the how to contribute docs so that you get yourself aquainted with the process on how to make a contribution to Gatsby.
@cristianaortiga i'm going to detail the steps i took to triage this and make both frameworks work together, with the added bonus of using Styled Components. The reproduction used is a "mashed redux"(pardon the bad pun) version of the LearnStorybook tutorial and the Gatsby documentation on how to use Styled Components. Here we go.
gatsby-plugin-styled-components, styled-components babel-plugin-styled-components.npx -p @storybook/cli sb initAfter the installation process finished i added some extra Storybook packages, more specifically @storybook/addon-a11y, @storybook/addon-viewport and @storybook/addon-knobs.
Updated the configuration file(.storybook/main.js) in order for make Storybook look inside the components folder as oposed to the default config, which will introspect all of the src folder. I did this for one key thing, Gatsby treats the pages folder as a special folder. And if you write a story somewhere and run Storybook in development mode for instance, Storybook will fail and you'll get accosted by some weird error messages, probably something like the following:
ERR! Module not found: Error: Can't resolve '..\..\public\static\d\3962212716.json' in '\test_cristianaortiga\test_storybook_gatsby_5_3\src\components'
(node:12120) UnhandledPromiseRejectionWarning: ModuleNotFoundError: Module not found: Error: Can't resolve '..\..\public\static\d\3962212716.json' in '\test_cristianaortiga\test_storybook_gatsby_5_3\src\components'
at factory.create (\test_cristianaortiga\test_storybook_gatsby_5_3\node_modules\@storybook\core\node_modules\webpack\lib\Compilation.js:925:10)
at factory (\test_cristianaortiga\test_storybook_gatsby_5_3\node_modules\@storybook\core\node_modules\webpack\lib\NormalModuleFactory.js:401:22)
at resolver (\test_cristianaortiga\test_storybook_gatsby_5_3\node_modules\@storybook\core\node_modules\webpack\lib\NormalModuleFactory.js:130:21)
at asyncLib.parallel (\test_cristianaortiga\test_storybook_gatsby_5_3\node_modules\@storybook\core\node_modules\webpack\lib\NormalModuleFactory.js:224:22)
at \test_cristianaortiga\test_storybook_gatsby_5_3\node_modules\neo-async\async.js:2830:7
at \test_cristianaortiga\test_storybook_gatsby_5_3\node_modules\neo-async\async.js:6877:13
at normalResolver.resolve (\test_cristianaortiga\test_storybook_gatsby_5_3\node_modules\@storybook\core\node_modules\webpack\lib\NormalModuleFactory.js:214:25)
at doResolve (\test_cristianaortiga\test_storybook_gatsby_5_3\node_modules\enhanced-resolve\lib\Resolver.js:213:14)
at hook.callAsync (\test_cristianaortiga\test_storybook_gatsby_5_3\node_modules\enhanced-resolve\lib\Resolver.js:285:5)
at _fn0 (eval at create (\test_cristianaortiga\test_storybook_gatsby_5_3\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:15:1)
at resolver.doResolve (\test_cristianaortiga\test_storybook_gatsby_5_3\node_modules\enhanced-resolve\lib\UnsafeCachePlugin.js:44:7)
at hook.callAsync (\test_cristianaortiga\test_storybook_gatsby_5_3\node_modules\enhanced-resolve\lib\Resolver.js:285:5)
at _fn0 (eval at create (\test_cristianaortiga\test_storybook_gatsby_5_3\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:15:1)
at hook.callAsync (\test_cristianaortiga\test_storybook_gatsby_5_3\node_modules\enhanced-resolve\lib\Resolver.js:285:5)
at _fn0 (eval at create (\test_cristianaortiga\test_storybook_gatsby_5_3\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:27:1)
at resolver.doResolve (\test_cristianaortiga\test_storybook_gatsby_5_3\node_modules\enhanced-resolve\lib\DescriptionFilePlugin.js:67:43)
With that my .storybook/main.js now looks like:
// .storybook/main.js
module.exports = {
//stories: ["../stories/**/*.stories.js"],
stories: ["../src/components/**/*.stories.js"], // introspects the `components` folder
// registers the installed addons(registration order matters)
addons: [
"@storybook/addon-a11y",
"@storybook/addon-actions",
"@storybook/addon-links",
"@storybook/addon-viewport",
"@storybook/addon-knobs",
],
}
main.js file. Probably 90% of the time you wont' need nothing more, but there are some cases like this one that will require some extra work. What this means is that everything that affects the way the component stories "look and feel" on a global scale, or if some addons are needed, then that configuration should be in a file called preview.js, more specifically adding system wide decorators, arguments or use a global css, or in this particular case use Styled components.preview.js inside the .storybook folder with the following:// .storybook/preview.js
import React from 'react';
import { addDecorator, addParameters } from '@storybook/react';
import { withA11y } from '@storybook/addon-a11y';
import { action } from '@storybook/addon-actions';
// simple layout component that generates a mocked Global Style in Styled components
import GlobalStyle from '../src/components/GlobalStyle'
// system wide decorator that all of the stories will use
addParameters({
options: { panelPosition: 'bottom' },
viewport: {
viewports: [
{
name: 'Testing breakpoint',
styles: {
width: `600px`,
height: '768px',
},
},
],
},
});
// Gatsby's Link overrides:
// Gatsby defines a global called ___loader to prevent its method calls from creating console errors you override it here
global.___loader = {
enqueue: () => {},
hovering: () => {},
};
// Gatsby internal mocking to prevent unnecessary errors in storybook testing environment
global.__PATH_PREFIX__ = '';
// This is to utilized to override the window.___navigate method Gatsby defines and uses to report what path a Link would be taking us to if it wasn't inside a storybook
window.___navigate = pathname => {
action('NavigateTo:')(pathname);
};
// system wide decorator to allow the addon to be used
addDecorator(withA11y);
//
// system wide decorator that will inject the global style component into Storybook
// the story function in conjunction with the children prop will make so that all the "descendants"
// will inherit the styles
addDecorator(story => (
<>
<GlobalStyle />
{story()}
</>
));
.storybook folder called webpack.config.js (using this will change Storybook to full control mode, meaning that you're responsible for controlling what is built and configured) with the following content:// .storybook/webpack.config.js
module.exports = ({ config }) => {
// set the NODE_ENV to 'production' by default, to allow babel-plugin-remove-graphql-queries to remove static queries
process.env.NODE_ENV = 'production';
// Transpile Gatsby module because Gatsby includes un-transpiled ES6 code.
config.module.rules[0].exclude = [/node_modules\/(?!(gatsby)\/)/];
// use installed babel-loader which is v8.0-beta (which is meant to work with @babel/core@7)
config.module.rules[0].use[0].loader = require.resolve('babel-loader');
// use @babel/preset-react for JSX and env (instead of staged presets)
config.module.rules[0].use[0].options.presets = [
require.resolve('@babel/preset-react'),
require.resolve('@babel/preset-env'),
];
config.module.rules[0].use[0].options.plugins = [
// use @babel/plugin-proposal-class-properties for class arrow functions
require.resolve('@babel/plugin-proposal-class-properties'),
// use babel-plugin-remove-graphql-queries to remove static queries from components when rendering in storybook
require.resolve('babel-plugin-remove-graphql-queries'),
];
// Prefer Gatsby ES6 entrypoint (module) over commonjs (main) entrypoint
config.resolve.mainFields = ['browser', 'module', 'main'];
return config;
};
With that the config part is over, onto the components and stories.
src\components folder and inside it i added some components:GlobalStyle.js that will be used by both Gatsby and Storybook with the following inside it:import React from "react"
import { createGlobalStyle } from "styled-components"
const GlobalStyle = createGlobalStyle`
body {
color: ${props => (props.theme === "purple" ? "purple" : "white")};
margin: 3rem auto;
max-width: 600px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
`
export default ({ children }) => (
<React.Fragment>
<GlobalStyle theme="purple" />
{children}
</React.Fragment>
)
Task.js with the following inside:import React from "react"
import styled, { css } from "styled-components"
const TaskWrapper = styled.div`
font-size: 14px;
line-height: 20px;
display: flex;
flex-wrap: wrap;
height: 3rem;
width: 100%;
${props =>
props.disabled &&
css`
background: #aaa;
`}
transition: all ease-out 150ms;
`
const TaskInput = styled.input`
width: 100%;
text-overflow: ellipsis;
${props =>
props.disabled &&
css`
color: #aaa;
`}
`
const Task = ({ taskInfo }) => (
<TaskWrapper>
<TaskInput value={taskInfo.node.title} readonly placeholder="Input title" />
</TaskWrapper>
)
export default Task
Tasks.js which will be basically a composite component of Task with the following:import React from "react"
import styled from "styled-components"
import Task from './Task'
const TasksWrapper = styled.div`
font-size: 14px;
line-height: 20px;
display: flex;
flex-wrap: wrap;
height: 3rem;
width: 100%;
`
const Tasks = ({taskList }) => {
if (taskList.length === 0) {
return (
<TasksWrapper>
<h1>Good news, you have no tasks! All good</h1>
</TasksWrapper>
)
}
return (
<TasksWrapper>
{taskList.map(task => (
<Task taskInfo={task} key={task.node.id}/>
))}
</TasksWrapper>
)
}
export default Tasks
User.js with the following:import React from "react"
import styled from "styled-components"
const UserWrapper = styled.div`
display: flex;
align-items: center;
margin: 0 auto 12px auto;
&:last-child {
margin-bottom: 0;
}
`
const Avatar = styled.img`
flex: 0 0 96px;
width: 96px;
height: 96px;
margin: 0;
`
const Description = styled.div`
flex: 1;
margin-left: 18px;
padding: 12px;
`
const Username = styled.h2`
margin: 0 0 12px 0;
padding: 0;
`
const Excerpt = styled.p`
margin: 0;
`
const User = ({userInfo}) => (
<UserWrapper>
<Avatar src={userInfo.avatar} alt="" />
<Description>
<Username>{userInfo.username}</Username>
<Excerpt>{userInfo.excerpt}</Excerpt>
</Description>
</UserWrapper>
)
export default User
IndexScreen.js with the following inside:import React from "react"
import Tasks from "./Tasks"
import User from './User'
import { useStaticQuery, graphql } from "gatsby"
const PureIndexScreen = ({ data }) => {
const {allTasksJson}=data
const {edges}= allTasksJson
return <Tasks taskList={edges}/>
}
const IndexScreen = props => {
const AllTasksDataResult = useStaticQuery(graphql`
query fetchAllTasks {
allTasksJson {
edges {
node {
id
title
state
updated_at
}
}
}
}
`)
return (
<div>
<h1>a minimal task list with gatsby and Storybook</h1>
<User userInfo={props.userData}/>
<PureIndexScreen {...props} data={AllTasksDataResult} />
</div>
)
}
export default IndexScreen
This is a special component, for two reasons, one, it contains a GraphQL query and you'll see shortly how you can handle it inside Storybook and two it will "act" as traditional Gatsby page, to avoid having to deal with error i mentioned above.
We have the components and Storybook configured, onto the stories.
I created a Storybook story for each component, so that you could see it all in effect.
User.stories.js:import React from "react"
import User from "./User"
import { withKnobs, object } from "@storybook/addon-knobs"
/**
* standard Storybook CSF configuration
* component will relate to which component to be used
* excludeStories is used tell Storybook that everything that ends with Data is to be ignored or otherwise would be turned into a Story and generate some errors
* decorators is where all the decorators that belong to the component's story should be placed.
* title is self explanatory
*/
export default {
component: User,
excludeStories: /.*Data$/,
decorators: [withKnobs],
title: "Simple Component|User",
}
// dummy data to be used by the component
// notice the usage of export, which means that this data can be used in other stories/tests
//(do not use it inside a component or Gatsby will break the build)
export const UserInformationData = {
username: "Jane Doe",
avatar:
"https://s3.amazonaws.com/uifaces/faces/twitter/adellecharles/128.jpg",
excerpt:
"I'm Jane Doe. Lorem ipsum dolor sit amet, consectetur adipisicing elit.",
}
// The default story of the component (note the usage of Default), this is a trick to bypass some es6 syntax
// as default is a reserved word
// This story will use the knobs addon that will allow you to modify the data while Storybook is running
export const Default = () => (
<User
userInfo={object("userInfo", {
...UserInformationData,
})}
/>
)
// Another simple story to check the behaviour of the component
export const AnotherUser = () => (
<User
userInfo={{
...UserInformationData,
username: "Another random user",
excerpt: "Random description",
}}
/>
)
Task.stories.js contains the following:import React from "react"
import Task from "./Task"
import { withKnobs, object } from "@storybook/addon-knobs"
/**
* standard Storybook CSF configuration
* component will relate to which component to be used
* excludeStories is used tell Storybook that everything that ends with Data is to be ignored or otherwise would be turned into a Story and generate some errors
* decorators is where all the decorators that belong to the component's story should be placed.
* title is self explanatory
*/
export default {
component:Task,
excludeStories: /.*Data$/,
decorators: [withKnobs],
title: "Simple Component|Task",
}
// dummy data to be used by the component
// notice the usage of export, which means that this data can be used in other stories/tests
//(do not use it inside a component or Gatsby will break the build)
export const taskData = {
node: {
id: "1",
title: "Dummy Task",
state: "Task_INBOX",
updated_at: "2020-01-01",
},
}
// The default story of the component (note the usage of Default), this is a trick to bypass some es6 syntax
// as default is a reserved word
// This story will use the knobs addon that will allow you to modify the data while Storybook is running
export const Default = () => (
<Task taskInfo={object("taskInfo", { ...taskData })} />
)
Tasks.stories.js contains the following:import React from "react"
import Tasks from "./Tasks"
import { taskData } from "./Task.stories"
/**
* standard Storybook CSF configuration
* component will relate to which component to be used
* excludeStories is used tell Storybook that everything that ends with Data is to be ignored or otherwise would be turned into a Story and generate some errors
* title is self explanatory
*/
export default {
component: Tasks,
excludeStories: /.*Data$/,
title: "Composite Component|Tasks",
}
// creates a dummy array of data to be used by the component
// Notice that the array will "spread" the task information inside the other story
export const defaultTasksData = [
{
node: {
...taskData.node,
id: "1",
title: "Task 1",
},
},
{
node: {
...taskData.node,
id: "2",
title: "Task 2",
},
},
{
node: {
...taskData.node,
id: "3",
title: "Task 3",
},
},
{
node: {
...taskData.node,
id: "4",
title: "Task 4",
},
},
{
node: {
...taskData.node,
id: "5",
title: "Task 5",
},
},
{
node: {
...taskData.node,
id: "6",
title: "Task 6",
},
},
]
// The default story of the component (note the usage of Default), this is a trick to bypass some es6 syntax
// as default is a reserved word
export const Default = () => <Tasks taskList={defaultTasksData} />
// A simple story for the component mocking a empty set of tasks
export const EmptyTasks = () => <Tasks taskList={[]} />
IndexScreen.stories.jsimport React from "react"
import IndexScreen from "./IndexScreen"
import { defaultTasksData } from './Tasks.stories'
import { UserInformationData } from './User.stories'
// dummy data to be used by the component
// notice the usage of export, which means that this data can be used in other stories/tests
//(do not use it inside a component or Gatsby will break the build)
export default {
component: IndexScreen,
excludeStories: /.*Data$/,
title: "Screen Component|index",
}
// the default story for the screen
// it will use the information that is present in the other stories (user.stories.js and tasks.stories.js)
export const Default=()=><IndexScreen userData={UserInformationData} {...defaultTasksData}/>
After all of this, issuing yarn storybook (i use yarn, if you use npm, you'll need to use npm run storybook) to start Storybook in development mode and waiting for the build to complete, i'm presented with this:
ERROR in ./src/components/IndexScreen.js
Module not found: Error: Can't resolve '..\..\public\static\d\3962212716.json' in '\test_cristianaortiga\test_storybook_gatsby_5_3\src\components'
@ ./src/components/IndexScreen.js 3:0-73 18:27-42
@ ./src/components/IndexScreen.stories.js
@ ./src/components sync ^\.\/(?:(?:(?!\.)(?:(?:(?!(?:|[\\\/])\.).)*?)[\\\/])?(?!\.)(?=.)[^\\\/]*?\.stories\.js[\\\/]?)$
@ ./.storybook/generated-entry.js
@ multi ./node_modules/@storybook/core/dist/server/common/polyfills.js ./node_modules/@storybook/core/dist/server/preview/globals.js ./.storybook/preview.js ./node_modules/@storybook/addon-knobs/dist/preset/addDecorator.js ./.storybook/generated-entry.js ./node_modules/webpack-hot-middleware/client.js?reload=true&quiet=true
Should you encounter this issue in your side, this is due to the fact that the IndexScreen component uses a GraphQL query and is expecting something to be present that is not, the data relevant to the component does not exist anywhere. The trick to bypass this is the following, run yarn develop, (once again i'm using yarn, if you use npm, adjust accordingly). to generate a Gatsby development build and with that create the piece of data that is required and then run Storybook with yarn storybook.
After that, opening up http://localhost:6006 in your browser you should be presented with:

In order to make this reproduction complete i added the serve package to my Gatsby site to see how Storybook would behave if i issued a Storybook production build. With that i changed my scripts aswell to incorporate this change and now it looks like
{
.....
"scripts":{
"build-storybook": "build-storybook",
"preview-storybook":"serve storybook-static"
}
}
Issued yarn build-storybook it ran to completion and then yarn preview-storybook and opening up http://localhost:5000 i'm presented with mocked production deployment version of Storybook.
The whole code behind this comment is in this repo, i would sugest you go over it at your own pace and tinker with it, before deep diving into the pr.
A nice touch to include in the documentation update would be mentioning the fix to the error stated above. I think that could help out not only the Gatsby community but also the Storybook community.
I'll be on the lookout for the pr and continue to help you with it. And i really hope this goes through and you get your much deserved swag.
Finally, sorry for the extremely long post, but i intended to provide you a full blown implementation that you could use as a baseline to when you update the documentation, also don't forget to mention this issue when you submit the pr.
Hiya!
This issue has gone quiet. Spooky quiet. 👻
We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.
If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!
As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!
Thanks for being a part of the Gatsby community! 💪💜
@cristianaortiga do you still have time to address this?
Hiya!
This issue has gone quiet. Spooky quiet. 👻
We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.
If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!
As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!
Thanks for being a part of the Gatsby community! 💪💜
Hiya!
This issue has gone quiet. Spooky quiet. 👻
We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.
If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!
As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!
Thanks for being a part of the Gatsby community! 💪💜
Hey again!
It’s been 30 days since anything happened on this issue, so our friendly neighborhood robot (that’s me!) is going to close it.
Please keep in mind that I’m only a robot, so if I’ve closed this issue in error, I’m HUMAN_EMOTION_SORRY. Please feel free to reopen this issue or create a new one if you need anything else.
As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!
Thanks again for being part of the Gatsby community! 💪💜
@jonniebigodes Is https://github.com/gatsbyjs/gatsby/issues/20624#issuecomment-575284226 still the latest advice on setting up Storybook? I know that current Gatsby docs are not up to date with latest config system, so I know I want to use the new hotness.
Also do the styled-components steps apply to styled-jsx?
@bsgreenb to the most of it yes, it should work without issue. Regarding the styled-jsx that's something that i can't say for sure that it will work out of the box. I know for sure that the learnstorybook site works with styled components and if not mistaken the official storybook site also is built with styled components, with the caveat they use their own design system. At the most you probably just need to make some tweaks and it should be good to work with. If you want i can expand the example that i used in #20624 and add style-jsx and see if it works in both development mode and also with a deployed storybook. Do you mind waiting a bit
@jonniebigodes Definitely can wait, also if there's any way I can help lemme know. I'll go ahead and follow the comment steps
@jonniebigodes I should also add that we try to use typescript everywhere. I will attempt to follow your comments instructions for our unique typescript+styled-jsx etc setup and see if any issues arise
storybook installed successfully on our setup. I had to make some changes
for typescript which I can document. I added you to repo so you can
see the PR. wasn't too hard, but hit a few bumps which I left as todos in comments.
On Mon, Apr 27, 2020 at 9:32 AM jonniebigodes notifications@github.com
wrote:
@bsgreenb https://github.com/bsgreenb i've fiddled with it and it seems
that it nothing too much is required to make the packages play nice asides
from what is mentioned. So far only js no ts. I have the code in here
https://github.com/jonniebigodes/gatsby-storybook-styled-js-no-typescript
and a deployed storybook here
https://inspiring-easley-8f0a75.netlify.app/?path=/story/*—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/gatsbyjs/gatsby/issues/20624#issuecomment-620095593,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAHPJ6KPDW3UXQQNS7NJERTROWXTNANCNFSM4KHEWCGA
.
I think I've found a much more efficient way to setup Storybook, by making use of the Create React App preset (which the Gatsby Storybook Instructions already recommend for TypeScript). With this preset, there's no need for a custom webpack config, etc.
https://gist.github.com/bsgreenb/3968d1664395c72e73df5020ddb275d2
This worked for my typescript setup, but would also save a lot of config on the regular javascript case presumably.
Ultimately, I would recommend that we ship either:
It might seem odd that CRA's storybook preset is more up to date than the @storybook/preset-typescript, which is what is used by gatsby-plugin-typescript. But this is because CRA has a cutting edge storybook preset, whereas storybook maintainers do not have a fully up to date pluggable typescript preset.
Update: I got it even simpler, zero config typescript, no preset, with Storyook 6 (on next branch)
main.ts:
export default {
stories: [
"../src/ui/**/*.stories.ts",
"../src/ui/**/*.stories.tsx",
"../src/ui/**/*.stories.mdx",
],
addons: [
{
name: "@storybook/addon-docs",
options: {
configureJSX: true,
},
},
"@storybook/addon-a11y",
"@storybook/addon-actions",
"@storybook/addon-controls",
"@storybook/addon-links",
"@storybook/addon-storysource",
"@storybook/addon-toolbars",
"@storybook/addon-viewport",
"@storybook/addon-backgrounds/register",
],
babel: {
plugins: [
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-class-properties",
"babel-plugin-remove-graphql-queries",
[
"styled-jsx/babel",
{ optimizeForSpeed: true, plugins: ["styled-jsx-plugin-postcss"] },
],
],
},
};
Most helpful comment
@cristianaortiga i'm going to detail the steps i took to triage this and make both frameworks work together, with the added bonus of using Styled Components. The reproduction used is a "mashed redux"(pardon the bad pun) version of the LearnStorybook tutorial and the Gatsby documentation on how to use Styled Components. Here we go.
gatsby-plugin-styled-components,styled-componentsbabel-plugin-styled-components.npx -p @storybook/cli sb initAfter the installation process finished i added some extra Storybook packages, more specifically
@storybook/addon-a11y,@storybook/addon-viewportand@storybook/addon-knobs.Updated the configuration file(
.storybook/main.js) in order for make Storybook look inside thecomponentsfolder as oposed to the default config, which will introspect all of thesrcfolder. I did this for one key thing, Gatsby treats thepagesfolder as a special folder. And if you write a story somewhere and run Storybook in development mode for instance, Storybook will fail and you'll get accosted by some weird error messages, probably something like the following:With that my
.storybook/main.jsnow looks like:main.jsfile. Probably 90% of the time you wont' need nothing more, but there are some cases like this one that will require some extra work. What this means is that everything that affects the way the component stories "look and feel" on a global scale, or if some addons are needed, then that configuration should be in a file calledpreview.js, more specifically adding system wide decorators, arguments or use a global css, or in this particular case use Styled components.With that out of the way i created a
preview.jsinside the.storybookfolder with the following:.storybookfolder calledwebpack.config.js(using this will change Storybook to full control mode, meaning that you're responsible for controlling what is built and configured) with the following content:With that the config part is over, onto the components and stories.
src\componentsfolder and inside it i added some components:GlobalStyle.jsthat will be used by both Gatsby and Storybook with the following inside it:Task.jswith the following inside:Tasks.jswhich will be basically a composite component ofTaskwith the following:User.jswith the following:IndexScreen.jswith the following inside:This is a special component, for two reasons, one, it contains a GraphQL query and you'll see shortly how you can handle it inside Storybook and two it will "act" as traditional Gatsby page, to avoid having to deal with error i mentioned above.
We have the components and Storybook configured, onto the stories.
I created a Storybook story for each component, so that you could see it all in effect.
User.stories.js:Task.stories.jscontains the following:Tasks.stories.jscontains the following:IndexScreen.stories.jsAfter all of this, issuing
yarn storybook(i use yarn, if you use npm, you'll need to use npm run storybook) to start Storybook in development mode and waiting for the build to complete, i'm presented with this:Should you encounter this issue in your side, this is due to the fact that the
IndexScreencomponent uses a GraphQL query and is expecting something to be present that is not, the data relevant to the component does not exist anywhere. The trick to bypass this is the following, runyarn develop, (once again i'm using yarn, if you use npm, adjust accordingly). to generate a Gatsby development build and with that create the piece of data that is required and then run Storybook withyarn storybook.After that, opening up
http://localhost:6006in your browser you should be presented with:In order to make this reproduction complete i added the serve package to my Gatsby site to see how Storybook would behave if i issued a Storybook production build. With that i changed my scripts aswell to incorporate this change and now it looks like
Issued
yarn build-storybookit ran to completion and thenyarn preview-storybookand opening uphttp://localhost:5000i'm presented with mocked production deployment version of Storybook.The whole code behind this comment is in this repo, i would sugest you go over it at your own pace and tinker with it, before deep diving into the pr.
A nice touch to include in the documentation update would be mentioning the fix to the error stated above. I think that could help out not only the Gatsby community but also the Storybook community.
I'll be on the lookout for the pr and continue to help you with it. And i really hope this goes through and you get your much deserved swag.
Finally, sorry for the extremely long post, but i intended to provide you a full blown implementation that you could use as a baseline to when you update the documentation, also don't forget to mention this issue when you submit the pr.