Storybook: Some props not found Typescript

Created on 18 Sep 2019  路  19Comments  路  Source: storybookjs/storybook

Describe the bug
Some component's props are not showed in the stories, i though it was just if i have union as props but it also work with some standard props interfaces

To Reproduce
Steps to reproduce the behavior:
Install storybook 5.2 and '@storybook/addon-storysource/loader'
Expected behavior
See the props

Screenshots
If applicable, add screenshots to help explain your problem.

Code snippets
i have this simple component :

const SimpleCheckbox = (props: CheckBoxProps & { labelSize?: 'normal' | 'small' }) => { const [checked, setChecked] = useState(false); return <Checkbox label="Choice" checked={checked} onChange={() => setChecked(!checked)} {...props} />; };

and here's my story

storiesOf('Checkbox', module) .addParameters({component: SimpleCheckbox}).....

and i don't get any prop on my doc.

I have installed react-docgen-typescript-loader

and here's my webpack config inside .storybook

const path = require('path');
const createCompiler = require('@storybook/addon-docs/mdx-compiler-plugin');
module.exports = ({ config }) => {
  // Only way to override webpack mode inside build-storybook
  if (process.env.NODE_ENV === 'development') {
    config.mode = process.env.NODE_ENV;
  }

  const rules = config.module.rules;

  rules.push({
    test: /\.(stories|story)\.mdx$/,
    use: [
      {
        loader: 'babel-loader',
      },
      {
        loader: '@mdx-js/loader',
        options: {
          compilers: [createCompiler({})],
        },
      },
    ],
  });

  rules.push({
    test: /\.(ts|tsx)$/,
    use: [
      {
        loader: require.resolve('babel-loader'),
      },
    ],
  });

  rules.push({
    test: /\.tsx?$/,
    include: path.resolve(__dirname, '../src'),
    use: [
      {
        loader: require.resolve('ts-loader'),
      }, {
        loader: require.resolve('react-docgen-typescript-loader'),
      },
    ],
  });

  rules.push({
    test: /\.mdx$/,
    use: [
      'babel-loader',
      '@mdx-js/loader',
    ],
  });

  rules.push({
    test: /\.stories\.tsx?$/,
    loaders: [
      {
        loader: require.resolve('@storybook/addon-storysource/loader'),
        options: { parser: 'typescript' },
      },
    ],
    enforce: 'pre',
  });

  config.resolve.extensions.push('.ts', '.tsx');
  return config;
};

System:
Environment Info:

System:
OS: macOS 10.14.6
CPU: (4) x64 Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
Binaries:
Node: 10.16.3 - /usr/local/bin/node
npm: 6.9.0 - /usr/local/bin/npm
Browsers:
Chrome: 77.0.3865.75
Safari: 12.1.2
npmPackages:
@storybook/addon-docs: ^5.3.0-alpha.0 => 5.3.0-alpha.0
@storybook/addon-info: ^5.2.1 => 5.2.1
@storybook/addon-storyshots: ^5.2.1 => 5.2.1
@storybook/addon-storysource: ^5.2.1 => 5.2.1
@storybook/addon-viewport: ^5.2.1 => 5.2.1
@storybook/react: ^5.2.1 => 5.2.1

Additional context
Add any other context about the problem here.

docs props inactive question / support typescript

Most helpful comment

~Not to hijack this issue, but I'm having difficulty getting _any_ props recognized in my project with Typescript. I'm just adding docs in https://github.com/gymnasium/gym-ui/pull/62 now. The typescript preset caused all kinds of problems in my project, so I modified the webpack config, but to no avail.~

~Right now the only component I have wired up is Button, but it's not finding any props:
https://deploy-preview-62--gymnasium-storybook.netlify.com/?path=/docs/button--default~

~I followed the recommendation in the docs here to set up typescript~

~Would love any insights you might be able to offer!~

edit: update - I was modifying the _wrong_ webpack config in my project. 馃う鈥嶁檪 Everything seems good now. My .storybook/webpack.config.js:

module.exports = ({ config, mode }) => {
  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.resolve.extensions.push('.ts', '.tsx');
  return config;
};

All 19 comments

@F-Moody just to clarify: this is about the props table in addon-docs?

I'm not seeing any prop tables on the DocsPage either with a similar config.
Using CRA and typescript, also swapped out babel-loader for ts-loader as specified in the typescript preset, but to no avail, it loaded, but still no prop tables.

const path = require('path');
const createCompiler = require('@storybook/addon-docs/mdx-compiler-plugin');

module.exports = ({ baseConfig, env, config }) => {
  // loads mdx stories
  config.module.rules.push({
    test: /\.(stories|story)\.mdx$/,
    use: [
      {
        loader: require.resolve('babel-loader'),
        options: {
          presets: [['react-app', { flow: false, typescript: true }]],
        },
      },
      {
        loader: require.resolve('@mdx-js/loader'),
        options: {
          compilers: [createCompiler({})],
        },
      },
    ],
  });

  // load docgen docs? I've tried swapping babel-loader for ts-lint and excluding stories, I get the same result
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    exclude: path.resolve(__dirname, '../node_modules/'),
    use: [
      {
        loader: require.resolve('babel-loader'),
        options: {
          presets: [['react-app', { flow: false, typescript: true }]],
        },
      },
      {
        loader: require.resolve('react-docgen-typescript-loader'),
      },
    ],
  });

  // adds story source
  config.module.rules.push({
    test: /\.stories\.(ts|tsx)$/,
    exclude: path.resolve(__dirname, '../node_modules/'),
    use: [
      {
        loader: require.resolve('@storybook/source-loader'),
      },
    ],
  });

  config.resolve.extensions.push('.ts', '.tsx');
  return config;
};

~Not to hijack this issue, but I'm having difficulty getting _any_ props recognized in my project with Typescript. I'm just adding docs in https://github.com/gymnasium/gym-ui/pull/62 now. The typescript preset caused all kinds of problems in my project, so I modified the webpack config, but to no avail.~

~Right now the only component I have wired up is Button, but it's not finding any props:
https://deploy-preview-62--gymnasium-storybook.netlify.com/?path=/docs/button--default~

~I followed the recommendation in the docs here to set up typescript~

~Would love any insights you might be able to offer!~

edit: update - I was modifying the _wrong_ webpack config in my project. 馃う鈥嶁檪 Everything seems good now. My .storybook/webpack.config.js:

module.exports = ({ config, mode }) => {
  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.resolve.extensions.push('.ts', '.tsx');
  return config;
};

@F-Moody just to clarify: this is about the props table in addon-docs?

@shilman Yes, no props shown there

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!

I use '@storybook/preset-typescript' with CRA and styled-components. And I see no props table neither with type nor interface.

And there's a strange hooks message instead of props table. This is probably some styled-components hook because I don't have any in my Button component.

image

The only table I can get is regular Button.propTypes on a regular React.FC component (not styled-components). Without any TypeScript integration.

@ElForastero In CRA, use @storybook/preset-create-react-app for TS support. We need to document this better... 馃槶

I've documented TS presets here: https://github.com/storybookjs/storybook/pull/8649

Any feedback on the changes is appreciated, since I'm still trying to get to the bottom of all this.

If you switch over to using presets, please let me know if:

  • it solves your problem,
  • it breaks something else,
  • there's no change

Also, whether or not you're using presets, please let me know if you see any opportunities to improve the docs here.

Many thanks!!!

@F-Moody @zzwong @ddaniel-dt @rickdunkin @sami616 @jonathanherdt @NateRadebaugh @ElForastero @mbifulco @alexwhin @bigmoves @coreybruyere @PilotConway @stale

@shilman Unfortunately, there's no change with @storybook/preset-create-react-app preset instead of @storybook/preset-typescript.

@ElForastero I wrote a short walkthrough of how to set it up. Can you go through and see whether your setup matches. I've confirmed that this works:

https://gist.github.com/shilman/bc9cbedb2a7efb5ec6710337cbd20c0c

@shilman Hmm... I have repeated steps in your gist. Everything works fine, except for default exports.
If there are no named exports, default exports don't work.

Story

import React from 'react';
import Button from './Test';

export default {
  title: 'base/Button',
  component: Button,
};

export const primary = () => <Button>Push me</Button>;

Component.

This one doesn't work.

import React, { FC } from "react";

interface ButtonProps {
  /**
   * Simple click handler
   */
  onClick?: () => void;
}

/**
 * The world's most _basic_ button
 */
const Button: FC<ButtonProps> = ({ children, onClick }) => (
  <button onClick={onClick} type="button">
    {children}
  </button>
);

export default Button;

But this works fine

Note an export statement near the Button.

import React, { FC } from "react";

interface ButtonProps {
  /**
   * Simple click handler
   */
  onClick?: () => void;
}

/**
 * The world's most _basic_ button
 */
export const Button: FC<ButtonProps> = ({ children, onClick }) => (
  <button onClick={onClick} type="button">
    {children}
  </button>
);

export default Button;

Screenshots:

No named export

image

With named export

image

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!

@ElForastero mind opening an issue at https://github.com/strothj/react-docgen-typescript-loader/ ?

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!

Hey there, it's me again! I am going close this issue to help our maintainers focus on the current development roadmap instead. If the issue mentioned is still a concern, please open a new ticket and mention this old one. Cheers and thanks for using Storybook!

hey @shilman, @ElForastero,

I faced the same problem and although it's not fixing the root cause, I found out that when using default export, if your component has the same name as the component file, you don't need the name export and the props are visible in the addon docs.

So, the following will work, hope it helps anyone facing the same.

Component
file name: ./components/Button.tsx

import React, { FC } from "react";

interface ButtonProps {
  /**
   * Simple click handler
   */
  onClick?: () => void;
}

const Button: FC<ButtonProps> = ({ children, onClick }) => (
  <button onClick={onClick} type="button">
    {children}
  </button>
);

export default Button;

Story

import React from 'react';
import Button from '../components/Button';

export default {
  title: 'base/Button',
  component: Button,
};

export const primary = () => <Button>Push me</Button>;

Cheers,

@joanrm20 thanks for that! also, for anybody reading this, you might try the recommended 6.0 setup (should work in 5.3 too) and I expect that also to fix the problem:

https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#react-prop-tables-with-typescript

I could manage to show properties at below conditions:

  • Keep interfaces for properties in same file. External type definitions may not be parsed
  • For FunctionComponents add props twice like this :
    const Button: FC<ButtonProps> = ({ children, onClick }:ButtonProps)
  • Some times default exported Components are also not parsed. So use named exports.

This is a quick and dirty fix to get React Components to be better documented. But I would be happy to get external type definitions are also documented and don't have to enter type definitions twice.
If the sample code from @joanrm20 does not work it may be work as follows:

Component
_file name: ./components/Button.tsx_

import React, { FC } from "react";
// 1- Keep interface definition in components file. 
interface ButtonProps {
  /**
   * Simple click handler
   */
  onClick?: () => void;
}
//2- Use named export
//3- Second assignment of ButtonProps
export const Button: FC<ButtonProps> = ({ children, onClick }:ButtonProps) => (
  <button onClick={onClick} type="button">
    {children}
  </button>
);

export default Button;

Can we get named export and file name conditions removed ?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ZigGreen picture ZigGreen  路  3Comments

rpersaud picture rpersaud  路  3Comments

dnlsandiego picture dnlsandiego  路  3Comments

purplecones picture purplecones  路  3Comments

wahengchang picture wahengchang  路  3Comments