Describe the bug
When composing a story using new CSF format, all stories show no code available
.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Like in the screenshots and docs, code previews should be available to view and copy.
Screenshots
System:
Environment Info:
System:
OS: macOS 10.14.6
CPU: (8) x64 Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz
Binaries:
Node: 12.4.0 - ~/.nvm/versions/node/v12.4.0/bin/node
Yarn: 1.17.3 - /usr/local/bin/yarn
npm: 6.9.0 - ~/.nvm/versions/node/v12.4.0/bin/npm
Browsers:
Chrome: 76.0.3809.132
Firefox: 68.0.2
Safari: 12.1.2
npmPackages:
@storybook/addon-actions: ^5.2.0 => 5.2.0
@storybook/addon-docs: ^5.2.0 => 5.2.0
@storybook/addon-links: ^5.2.0 => 5.2.0
@storybook/addon-notes: ^5.2.0 => 5.2.0
@storybook/addons: ^5.2.0 => 5.2.0
@storybook/react: ^5.2.0 => 5.2.0
Can you share your preset and config files?
// addons.js
import '@storybook/addon-actions/register'
import '@storybook/addon-links/register'
// config.js
import { configure } from '@storybook/react'
configure(require.context('../src/stories', true, /\.stories\.(js|mdx)$/), module)
// presets.js
module.exports = [
{
name: '@storybook/addon-docs/react/preset',
options: {
configureJSX: true,
babelOptions: {},
sourceLoaderOptions: null,
},
},
]
I have very similar situation but with typescript configuration. Everything is working fine except code part.
I'm not using presets. My stories are placed in src/components
directory.
My webpack.config.js:
const path = require("path");
module.exports = ({ config }) => {
config.module.rules.push({
test: /\.(ts|tsx)$/,
use: [
{
loader: require.resolve('babel-loader'),
options: {
presets: [['react-app', { flow: false, typescript: true }]]
}
},
{
loader: require.resolve('react-docgen-typescript-loader')
}
]
});
config.module.rules.push({
test: /\.(stories|story)\.[tj]sx?$/,
loader: require.resolve('@storybook/source-loader'),
include: [path.resolve(__dirname, '../src/components')],
enforce: 'pre',
options: {
injectParameters: true,
inspectLocalDependencies: false,
inspectDependencies: false
}
});
config.resolve.extensions.push('.ts', '.tsx');
return config;
};
facing the same issue
I do have the same issue using typescript preset, ended up in moving to write in MDX
I've found bug in my config. I changed test: /\.(stories|story)\.[tj]sx?$/,
in source-loader
config to test: /\.[tj]sx?$/
. After that source code appears in stories.
~Also I think docs are wrong. Source-loader test regexp should be set to match sources and stories instead of stories only.~
EDIT: source-loader shouldn't be set for something else than stories. In my case regexp wasn't matching stories files.
@mattwaler sorry for the slow reply. this line from your preset is disabling the source loader, so there's no code to show:
sourceLoaderOptions: null,
@goszczynskip i don't think so. source-loader is about loading the source for stories only. if you set it to load the source for your components it will slow down your builds etc. i suspect there's some other problem with your setup.
@shilman You are right. There was other problem. I've just used regexp with starting dot but my stories are like: story.tsx
.
My working configuration with Typescript, MDX and sources. Maybe someone wants to copy it.
const path = require('path');
const createCompiler = require('@storybook/addon-docs/mdx-compiler-plugin');
const docgenLoader = {
loader: require.resolve('react-docgen-typescript-loader'),
options: {
propFilter: prop => {
// Filter out props from styled-components
if (prop.name === 'as' || prop.name === 'ref' || prop.name === 'theme') {
return false;
}
if (prop.parent == null) {
return true;
}
// Filter out props which type definition is placed in react package
return prop.parent.fileName.indexOf('node_modules/@types/react') < 0;
}
}
};
const babelLoader = {
loader: require.resolve('babel-loader'),
options: {
presets: [['react-app', { flow: false, typescript: true }]]
}
};
const mdxLoader = {
loader: '@mdx-js/loader',
options: {
compilers: [createCompiler({})]
}
};
module.exports = ({ config }) => {
config.module.rules.push({
test: /\.(mdx)$/,
use: [babelLoader, docgenLoader, mdxLoader]
});
config.module.rules.push({
test: /\.(ts|tsx)$/,
use: [babelLoader, docgenLoader]
});
config.module.rules.push({
test: /(stories|story)\.[tj]sx?$/,
loader: require.resolve('@storybook/source-loader'),
include: [path.resolve(__dirname, '../src/components')],
enforce: 'pre',
options: {
injectParameters: true,
inspectLocalDependencies: false,
inspectDependencies: false
}
});
config.resolve.extensions.push('.ts', '.tsx');
return config;
};
@mattwaler sorry for the slow reply. this line from your preset is disabling the source loader, so there's no code to show:
sourceLoaderOptions: null,
thx. this works for me.
Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!
Same problem here. We use a custom Webpack config for TypeScript support in stories.
module.exports = ({ config }) => {
config.module.rules.push({
test: /\.(ts|tsx)$/,
use: "babel-loader"
});
config.resolve.extensions.push(".ts", ".tsx");
return config;
};
Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!
Still got no code available while using CSF format (Docs mode). But, when I switched to Canvas mode, the story source existed.
webpack.config.js
// Core(s)
const path = require('path');
const createMDXCompiler = require('@storybook/addon-docs/mdx-compiler-plugin');
// Summary
module.exports = async ({ config }) => {
config.module.rules.push(
{
test: /\.stories\.mdx$/,
use: [
{
loader: 'babel-loader',
// May or may not need this line depending on your app's setup
options: {
plugins: ['@babel/plugin-transform-react-jsx']
}
},
{
loader: '@mdx-js/loader',
options: {
compilers: [createMDXCompiler({})]
}
}
]
},
{
test: /\.stories\.tsx?$/,
use: [
{
loader: require.resolve('@storybook/source-loader'),
options: {
parser: 'typescript',
prettierConfig: {
arrowParens: 'avoid',
printWidth: 80,
tabWidth: 2,
bracketSpacing: true,
trailingComma: 'none',
singleQuote: true,
semi: true,
jsxBracketSameLine: false
}
}
}
],
enforce: 'pre',
include: path.resolve(__dirname, '../src')
},
{
test: /\.tsx?$/,
use: [
{
loader: require.resolve('babel-loader'),
options: {
presets: [
[
require.resolve('babel-preset-react-app'),
{ flow: false, typescript: true }
]
]
}
},
require.resolve('react-docgen-typescript-loader')
]
},
{
test: /\.s[ac]ss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
include: path.resolve(__dirname, '../')
}
);
config.resolve.extensions.push('.ts', '.tsx');
return config;
};
button.tsx
import React, { ReactNode, FunctionComponentElement } from 'react';
export type Props = {
/**
* Children
*/
children?: ReactNode;
};
export function Button({ children }: Props): FunctionComponentElement<Props> {
return <button type="button">{children}</button>;
}
export default Button;
button.stories.tsx
import React, { FunctionComponent } from 'react';
import { text } from '@storybook/addon-knobs';
import { Button } from './button';
export default { title: 'Genesis|Button', component: Button };
export const withText: FunctionComponent = () => <Button>Hello Button</Button>;
export const withEmoji: FunctionComponent = () => (
<Button>
<span role="img" aria-label="so cool">
馃榾 馃槑 馃憤 馃挴
</span>
</Button>
);
export const withKnobs: FunctionComponent = () => (
<Button>{text('children', 'Test Children')}</Button>
);
:bowing_man:
@jeffryang24 your webpack config adds source-loader, but addon-docs also adds source-loader. I'd suggest removing yours, or disabling the one in addon-docs per https://github.com/storybookjs/storybook/blob/next/addons/docs/README.md#preset-options
@jeffryang24 your webpack config adds source-loader, but addon-docs also adds source-loader. I'd suggest removing yours, or disabling the one in addon-docs per https://github.com/storybookjs/storybook/blob/next/addons/docs/README.md#preset-options
I see... Will try to disable one of them. Will report the result back, probably this night (GMT+7)... :bowing_man:
I have a running storybook installation as per instructions here: https://gist.github.com/shilman/bc9cbedb2a7efb5ec6710337cbd20c0c
Currently I also see no code preview in the stories when using CSF - it only works properly when using MDX instead.
@patrick-radulian I have updated the gist, specifically this part, to reflect recent changes in addon-docs
:
{
name: "@storybook/addon-docs/preset",
options: {
configureJSX: true,
}
}
I also tested it with a clean setup & verified that it's working
@jeffryang24 your webpack config adds source-loader, but addon-docs also adds source-loader. I'd suggest removing yours, or disabling the one in addon-docs per https://github.com/storybookjs/storybook/blob/next/addons/docs/README.md#preset-options
Hmm... Actually, I don't use the default preset, @storybook/addon-docs/preset
and I don't have presets.js
. I follow the manual installation from the docs (before this new doc with main.js
:laughing:). I will try update the storybook to v5.2.8
@jeffryang24 your webpack config adds source-loader, but addon-docs also adds source-loader. I'd suggest removing yours, or disabling the one in addon-docs per https://github.com/storybookjs/storybook/blob/next/addons/docs/README.md#preset-options
Here's my full config: https://gist.github.com/jeffryang24/2147d8dbed6189ba6cc9a022ec79ac11 :bowing_man:. Still got no luck... Oh, yes. My project is a monorepo and has only one tsconfig.json in the root dir.... Does it cause this issue?
Still got no code available while using CSF format (Docs mode). But, when I switched to Canvas mode, the story source existed.
webpack.config.js
// Core(s) const path = require('path'); const createMDXCompiler = require('@storybook/addon-docs/mdx-compiler-plugin'); // Summary module.exports = async ({ config }) => { config.module.rules.push( { test: /\.stories\.mdx$/, use: [ { loader: 'babel-loader', // May or may not need this line depending on your app's setup options: { plugins: ['@babel/plugin-transform-react-jsx'] } }, { loader: '@mdx-js/loader', options: { compilers: [createMDXCompiler({})] } } ] }, { test: /\.stories\.tsx?$/, use: [ { loader: require.resolve('@storybook/source-loader'), options: { parser: 'typescript', prettierConfig: { arrowParens: 'avoid', printWidth: 80, tabWidth: 2, bracketSpacing: true, trailingComma: 'none', singleQuote: true, semi: true, jsxBracketSameLine: false } } } ], enforce: 'pre', include: path.resolve(__dirname, '../src') }, { test: /\.tsx?$/, use: [ { loader: require.resolve('babel-loader'), options: { presets: [ [ require.resolve('babel-preset-react-app'), { flow: false, typescript: true } ] ] } }, require.resolve('react-docgen-typescript-loader') ] }, { test: /\.s[ac]ss$/, use: ['style-loader', 'css-loader', 'sass-loader'], include: path.resolve(__dirname, '../') } ); config.resolve.extensions.push('.ts', '.tsx'); return config; };
button.tsx
import React, { ReactNode, FunctionComponentElement } from 'react'; export type Props = { /** * Children */ children?: ReactNode; }; export function Button({ children }: Props): FunctionComponentElement<Props> { return <button type="button">{children}</button>; } export default Button;
button.stories.tsx
import React, { FunctionComponent } from 'react'; import { text } from '@storybook/addon-knobs'; import { Button } from './button'; export default { title: 'Genesis|Button', component: Button }; export const withText: FunctionComponent = () => <Button>Hello Button</Button>; export const withEmoji: FunctionComponent = () => ( <Button> <span role="img" aria-label="so cool"> 馃榾 馃槑 馃憤 馃挴 </span> </Button> ); export const withKnobs: FunctionComponent = () => ( <Button>{text('children', 'Test Children')}</Button> );
cc: @shilman
Could be #7829? Since I used typescript for this project. https://gist.github.com/jeffryang24/2147d8dbed6189ba6cc9a022ec79ac11 :bowing_man:
@shilman Thanks, you are right - I've just commented out a different addon (addon-storysource) and kept only docs running. I do in fact see the code preview now, but with a (rather minor) issue:
The bigger issue I've run into though, is the warnings I receive when storybook starts up / refreshes:
With Button.stories.tsx looking like this:
import React from "react";
import { Button } from "./Button";
export default {
title: "Design System|Atoms/Button",
component: Button
}
export const Default = () => <Button>Default button</Button>;
export const Positive = () => <Button type="positive">Positive button</Button>;
export const Danger = () => <Button type="danger">Danger button</Button>;
@jeffryang24 your webpack config adds source-loader, but addon-docs also adds source-loader. I'd suggest removing yours, or disabling the one in addon-docs per https://github.com/storybookjs/storybook/blob/next/addons/docs/README.md#preset-options
Already found the culprit. I just made another sandbox for reproducing the issue, and finally found the root problem. When I set the parser
option for @storybook/source-loader
, the "No code available" issue appeared, but when I commented the parser
option, the "Show Code" panel appeared and it rendered the source code perfectly. I don't know why I can't set the parser to typescript
, probably #7829?
Here's the repo for reproducing the issue: https://github.com/jeffryang24/sandbox/tree/master/javascript-typescript/storybook-addon-docs-repro
I have renamed stories.tsx
to Component.stories.tsx
and it worked.
It looks like the preset ignores values provided from configure/require.context
in config.js
. Or maybe it uses heuristics
// config.js
import { addParameters, configure } from '@storybook/react';
addParameters({
options: {
storySort: (a, b) => (a[1].kind === b[1].kind ? 0 : a[1].id.localeCompare(b[1].id)),
},
});
configure(
[
requireContext('../src', true, /stories\.tsx$/),
],
module
);
// main.js
module.exports = {
presets: [
'@storybook/preset-create-react-app',
{
name: '@storybook/addon-docs/preset',
options: {
configureJSX: true,
},
},
],
addons: [
'@storybook/addon-a11y/register',
'@storybook/addon-actions/register',
'@storybook/addon-knobs/register',
],
};
Found the source: https://github.com/storybookjs/storybook/blob/21b8a7fb2ca2ace85be14accabc5e046f9189377/addons/docs/src/frameworks/common/preset.ts#L36-L45
So, if your story filename is different, no code would be shown.
I just ran into this same problem as well when using TypeScript. Turns out the problem was the TypeScript types. My guess is that whatever is loading/parsing the code isn't able to parse TypeScript (probably cuz it doesn't know it's TypeScript), and as a result ti fails. And then when it fails the "no code available" shows up.
EDIT: So I did more digging. After getting it to work by removing the Typescript types, I changed my parser to typescript
like so in my .storybook/presets.js
file:
module.exports = [
{
name: '@storybook/addon-docs/react/preset',
options: {
sourceLoaderOptions: {
parser: 'typescript',
},
},
},
];
This broke it again, I was no longer able to view the source code. After a lot of code spelunking I got to this line of code by @shilman: https://github.com/storybookjs/storybook/blame/8e8a4683afcefacab83b4169f8235254c0a2c2b0/addons/docs/src/blocks/Source.tsx#L39. When the parser is typescript
the locationsMap
is empty. When not, the locationsMap
has the correct story ID mappings.
I don't quite understand the comment or what locationsMap
is bad, so not quite sure where to go from here, but I'll do more digging if I can. The code is properly parsed by TypeScript, so there's some other part of the stack that's failing.
Ok, I traced it down to a bug in @storybook/source-loader
. The parsed AST from JS slightly differs from that from TS and the code was only handling the JS version. Luckily @shilman has already fixed the bug! It's in a RC of @storybook/source-loader
I believe, but 5.3.0
hasn't officially been released, which is why @storybook/addon-docs
hasn't updated to it (or maybe they all have the same versions).
Once @storybook/source-loader
v5.3.0 is released and the docs addon is updated, this should be fixed. 馃憦馃従 The bug was fixed back in October, so not quite sure what the timeline would be on it
Just upgraded to 5.3.3
and verified the code shows for me
馃帀 closing this! 馃帀
In my project I am overriding the default storybook webpack config with my own custom webpack config. This meant that any of the default module.rules from storybook webpack config were not being applied. Due to this the source-loader rule was also not being applied, and DocsPage was showing 'No code available' .
I re-added the source-loader rule and it works fine.
ran into the same issue like @Vanuan on v6.0.21. It works if the storyname includes the name of the component. However, our folder structure is like this:
/MyComponent
--> index.vue
--> stories.js
I am no webpack expert, could someone point me into a direction how to fix this without changing folder structure? 馃槂
EDIT:
It worked by manually adding source-loader:
config.module.rules.push({
test: /(.*\.)?stories\.js$/,
loaders: [ '@storybook/source-loader' ],
});
@andre-brdoch Maybe try changing loaders[x][y].test
to a constant, e.g. "stories.js".
Or, if you're willing to contribute, change this line: https://github.com/storybookjs/storybook/blob/57798a108e183d97f94fd4cc396e45e1d4b04d23/addons/docs/src/frameworks/common/preset.ts#L65
To the following:
test: /\.?(stories|story)\.[tj]sx?$/,
@Vanuan
@andre-brdoch Maybe try changing
loaders[x][y].test
to a constant, e.g. "stories.js".Or, if you're willing to contribute, change this line:
To the following:
test: /\.?(stories|story)\.[tj]sx?$/,
but that would match, for example,
History.tsx
.
Assuming this tests a path and not a filename alone:
test: /(/|\.)(stories|story)\.[tj]sx?$/,
Add the following to /.storybook/webpack.config.js
:
// /.storybook/webpack.config.js
module.exports = ({ config }) => {
config.module.rules.push({
test: /(\/|\.)(stories|story)\.[tj]sx?$/,
use: '@storybook/source-loader',
})
return config
}
@pwfisher Good catch!
@pwfisher @Vanuan what if you just add \/story.[tj]sx?
i'm afraid that the source-loader would get run twice on e.g. Foo.stories.tsx
because addon-docs
already adds a rule for that.
Most helpful comment
@mattwaler sorry for the slow reply. this line from your preset is disabling the source loader, so there's no code to show: