Storybook: Docs - React Typescript - No code available

Created on 21 Mar 2020  路  8Comments  路  Source: storybookjs/storybook

Describe the bug
Introducing @storybook/addon-docs to my repo, everything in the Docs tab works fine except for the source code which is not available.

To Reproduce
Started creating a repro repo using the cra-ts gist but got stuck in unrelated issues when ejecting to simulate my own main repo, hence no steps available at this point, please refer to below information.

Expected behavior
The source code should be displayed in the Docs tab.

Screenshots
My Docs tab (as you can see just about everything works fine, except for the lack of source code):
image

Code snippets
main.js

module.exports = {
  stories: ['../src/**/Alert.stories.tsx'],
  addons: [
    '@storybook/addon-actions/register',
    '@storybook/addon-viewport/register',
    '@storybook/addon-a11y/register',
    '@storybook/addon-backgrounds/register',
    {
      name: '@storybook/addon-docs',
      options: {
        configureJSX: true,
      },
    },
  ],
}

preview.js

import { addDecorator, addParameters } from '@storybook/react'
import { withA11y } from '@storybook/addon-a11y'
import centered from '@storybook/addon-centered/react'

// import '../src/Styles/_global.scss'

// addDecorator(centered)
addDecorator(withA11y)

addParameters({
  backgrounds: [
    { name: 'light', value: '#eff0f9', default: true },
    { name: 'dark', value: '#392b64' },
  ],
})

webpack.config.js

const path = require('path')
const fs = require('fs')
const { mergeDeepLeft } = require('ramda')

// Make sure any symlinks in the project folder are resolved:
// https://github.com/facebook/create-react-app/issues/637
const appDirectory = fs.realpathSync(process.cwd())
const resolveApp = relativePath => path.resolve(appDirectory, relativePath)

const storybookCfg = {
  module: {
    rules: [
      {
        test: /\.(ts|tsx)$/,
        include: [resolveApp('src')],
        loaders: [
          {
            loader: require.resolve('babel-loader'),
            options: {
              presets: [['react-app', { flow: false, typescript: true }]],
            },
          },
          {
            // This is used to display TypeScript types under the "Docs" tab in Storybook.
            loader: require.resolve('react-docgen-typescript-loader'),
            options: {
              // Provide the path to your tsconfig.json so that your stories can
              // display types from outside each individual story.
              tsconfigPath: path.resolve(__dirname, '../tsconfig.json'),
            },
          },
        ],
      },
      {
        test: /\.(js|jsx)$/,
        include: [resolveApp('src'), resolveApp('.storybook')],

        loaders: [
          {
            loader: require.resolve('babel-loader'),
            options: {
              presets: [['react-app']],
            },
          },
        ],
      },
      {
        test: /\.module\.scss$/,
        loaders: [
          require.resolve('style-loader'),
          {
            loader: require.resolve('css-loader'),
            options: {
              importLoaders: 1,
              modules: {
                localIdentName: '[name]__[local]___[hash:base64:5]',
              },
            },
          },
          {
            loader: require.resolve('postcss-loader'),
            options: {
              ident: 'postcss',
              plugins: () => [
                require('postcss-flexbugs-fixes'),
                require('postcss-preset-env')({
                  autoprefixer: {
                    flexbox: 'no-2009',
                  },
                  stage: 3,
                }),
              ],
            },
          },
          {
            loader: require.resolve('sass-loader'),
            options: {
              importLoaders: 2,
              modules: true,
              localIdentName: '[name]__[local]___[hash:base64:5]',
            },
          },
        ],
      },
      {
        test: /\.scss$/,
        exclude: /\.module\.scss$/,
        loaders: [
          require.resolve('style-loader'),
          {
            loader: require.resolve('css-loader'),
            options: {
              importLoaders: 1,
            },
          },
          {
            loader: require.resolve('postcss-loader'),
            options: {
              ident: 'postcss',
              plugins: () => [
                require('postcss-flexbugs-fixes'),
                require('postcss-preset-env')({
                  autoprefixer: {
                    flexbox: 'no-2009',
                  },
                  stage: 3,
                }),
              ],
            },
          },
          {
            loader: require.resolve('sass-loader'),
            options: {
              importLoaders: 2,
            },
          },
        ],
      },
      {
        test: /\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani)(\?.*)?$/,
        loader: 'file-loader',
        query: { name: 'static/media/[name].[hash:8].[ext]' },
      },
      {
        test: /\.(mp4|webm|wav|mp3|m4a|aac|oga)(\?.*)?$/,
        loader: 'url-loader',
        query: { limit: 10000, name: 'static/media/[name].[hash:8].[ext]' },
      },
    ],
  },
}

module.exports = ({ config }) => {
  config.resolve.extensions.push('.ts', '.tsx', '.module.scss', '.scss')
  config.output.publicPath = process.env.PUBLIC_URL

  return mergeDeepLeft(storybookCfg, config)
}

Alert.stories.tsx

import React from 'react'
import Alert from './Alert'

export default {
  title: 'Components/Alert',
  component: Alert,
}

export const warning = () => (
  <Alert testSelector="alert-selector" title="This is an alert." />
)

Alert.tsx

import React from 'react'

interface AlertProps {
  /** they see me commenting */
  testSelector?: string
  title?: string
}

/** Alert stuff */
const Alert = ({ testSelector = 'hej', title }: AlertProps) => {
  return (
    <div data-testid={testSelector}>
      <div>
        <p>
          <strong>{title}</strong>
        </p>
      </div>
    </div>
  )
}

export default Alert

System:
Environment Info:

System:
OS: Windows 10 10.0.18362
CPU: (12) x64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
Binaries:
Node: 12.16.1 - C:\Program Files\nodejs\node.EXE
npm: 6.14.2 - ~\source\repos\Common-Component-Library\node_modules.bin\npm.CMD
Browsers:
Edge: 44.18362.449.0

Additional context
I've studied similar issues meticulously and tried the suggested fixes, in particular https://github.com/storybookjs/storybook/issues/8104
Worth mentioning is that it doesn't matter if I use CSF or storiesOf, same issue applies.

docs source question / support

Most helpful comment

You might need to add source-loader to the .tsx? rules since it looks like you're overriding them: https://github.com/storybookjs/storybook/tree/next/addons/docs#manual-configuration

All 8 comments

You might need to add source-loader to the .tsx? rules since it looks like you're overriding them: https://github.com/storybookjs/storybook/tree/next/addons/docs#manual-configuration

Confirmed solution. Appended

{
  loader: require.resolve('@storybook/source-loader'),
},

to the tsx-matching block in webpack.config.js and that worked wonders. 馃挴

Before we close I have one more clarifying question to help others who may end up in a similar situation:

Are you saying that by specifying a tsx-loader I am overwriting some out of the box @storybook/source-loader configuration?

Thanks a lot for the support. 馃檹

@jgarplind you're running mergeDeepLeft(storybookCfg, config) and it appears that's overwriting the typescript rules. i think the devil's in the details about how you merge the rules, so i wouldn't generalize that statement.

also, for clarification, it's the addon-docs preset that's configuring source-loader AFAIK.

@shilman @jgarplind I have the same problem with not showing the Show code, however, I'm not using typescript and also not using a custom webpack config.

This is my config:

module.exports = {
  stories: ['../src/**/*.stories.(jsx|mdx)', '../docs/**/*.stories.(jsx|mdx)'],
  addons: [
    '@storybook/preset-create-react-app',
    '@storybook/addon-actions',
    '@storybook/addon-links',
    '@storybook/addon-knobs/register',
    '@storybook/addon-viewport/register',
    '@storybook/addon-storysource/register',
    '@storybook/addon-a11y/register',
    '@storybook/addon-notes/register',
    '@storybook/addon-options/register',
    '@storybook/addon-backgrounds/register',
    '@storybook/addon-docs/register',
  ],
  presets: [
    {
      name: '@storybook/addon-docs/preset',
      options: {
        configureJSX: true,
      },
    },
  ],
};

@elderalves try changing it to:

module.exports = {
  stories: ['../src/**/*.stories.(jsx|mdx)', '../docs/**/*.stories.(jsx|mdx)'],
  addons: [
    '@storybook/preset-create-react-app',
    '@storybook/addon-actions',
    '@storybook/addon-links',
    '@storybook/addon-knobs/register',
    '@storybook/addon-viewport/register',
    '@storybook/addon-storysource/register',
    '@storybook/addon-a11y/register',
    '@storybook/addon-notes/register',
    '@storybook/addon-options/register',
    '@storybook/addon-backgrounds/register',
    '@storybook/addon-docs', // removed "register"
  ],
};

If that doesn't work, let me know if you have a repro repo I can look at

@shilman I changed and it still doesn't show... It's a private repo.

for example... my Button.stories.jsx looks like it:

import React from 'react';
import { Box } from '@material-ui/core';
import { Download } from 'mdi-material-ui';
import { action } from '@storybook/addon-actions';
import {
  withKnobs, boolean,
} from '@storybook/addon-knobs';

// COMPONENTS
import Button from '../Button';
import { AppProvider } from '../../../../.storybook/components';

// DOC
import docs from './Button.docs.mdx';

export default {
  title: 'Components|Button',
  component: Button,
  decorators: [withKnobs],
  parameters: {
    docs: { page: docs },
  },
};


export const Primary = () => (
  <AppProvider>
    <Button
      disabled={boolean('Disabled', false)}
      appearance="primary"
      onClick={action('clicked')}
    >
      Click here
    </Button>
  </AppProvider>
);

is it right?

@jgarplind you're running mergeDeepLeft(storybookCfg, config) and it appears that's overwriting the typescript rules. i think the devil's in the details about how you merge the rules, so i wouldn't generalize that statement.

also, for clarification, it's the addon-docs preset that's configuring source-loader AFAIK.

Thanks, from my side this issue can be closed.

For anyone facing this problem in general, even without using typescript:

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hansthinhle picture hansthinhle  路  57Comments

dependencies[bot] picture dependencies[bot]  路  142Comments

ilias-t picture ilias-t  路  73Comments

EdenTurgeman picture EdenTurgeman  路  81Comments

Olian04 picture Olian04  路  78Comments