Storybook: addon-docs not showing all props for styled-component

Created on 12 Aug 2020  路  4Comments  路  Source: storybookjs/storybook

Describe the bug

Please note this is for the pre-release version as styled-components were not able to be documented until this issue was resolved.

When documenting a styled-component, not all props are rendered out into the props table.

To Reproduce
Steps to reproduce the behavior:

  1. Clone the repro repo
  2. npx sb@next upgrade --prerelease
  3. yarn add babel-loader --dev
  4. update the main.js stories glob from ../src/**/*.stories.(ts|tsx|js|jsx|mdx) to ../src/**/*.stories.@(ts|tsx|js|jsx|mdx)
  5. View the button story
  6. The props table is missing the disabled and type props

Expected behavior

The props table should include all props.

Screenshots

image

Code snippets

// Button.tsx
interface Props {
  /**
   * Indicates if the button is disabled
   */
  disabled?: boolean;
  /**
   * Type of button
   */
  type: "submit" | "button" | "reset";
}

/**
 * Button component
  * @returns a button component
 */
export const Button = styled.button.attrs<Props>((props) => ({
  type: props.type
}))`
  ...
`

System:

Environment Info:

  System:
    OS: Windows 10 10.0.18363
    CPU: (8) x64 Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
  Binaries:
    Node: 12.16.1 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.4 - C:\Program Files\nodejs\yarn.CMD
    npm: 6.13.4 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: 84.0.4147.105
    Edge: Spartan (44.18362.449.0)
  npmPackages:
    @storybook/addon-actions: ^6.0.2 => 6.0.2
    @storybook/addon-docs: ^6.0.2 => 6.0.2
    @storybook/addon-links: ^6.0.2 => 6.0.2
    @storybook/addons: ^6.0.2 => 6.0.2
    @storybook/preset-create-react-app: ^3.1.4 => 3.1.4
    @storybook/react: ^6.0.2 => 6.0.2
P3 argstable bug compatibility with other tools

Most helpful comment

I think this is the same issue I ran into with low-level styled components:

$ fgrep -e @storybook -e styled -e '"react"' package.json 
    "@storybook/addon-essentials": "^6.0.16",
    "@storybook/react": "6.0.16",
    "react": "16.13.1",
    "styled-components": "5.1.1",

Example/index.js:

import PropTypes from 'prop-types';
import styled from 'styled-components';

export const Example = styled.p`
  background-color: ${props => props.color};
  height: 100px;
  width: 100px;
`;

Example.propTypes = {
  /** background color */
  color: PropTypes.string.isRequired,
};

Example/index.stories.js:

import React from 'react';
import {Example} from '.';

export default {
  component: Example,
  title: 'Example',
};

export const Default = args => <Example {...args} />;
Default.args = {
  color: 'red',
};

image

If I wrap the component in a dummy wrapper...

import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';

const _Example = styled.p`
  background-color: ${props => props.color};
  height: 100px;
  width: 100px;
`;

export const Example = args => <_Example {...args} />

Example.propTypes = {
  /** background color */
  color: PropTypes.string.isRequired,
};

...then the documentation and the auto-generated controls work:
image

But of course I don't want to do that, because it adds another level in the React component browser every time I use the component. Dumping the component to the browser console could hint at the root cause: it is an object and not a function that returns react components:
image

All 4 comments

I think this is the same issue I ran into with low-level styled components:

$ fgrep -e @storybook -e styled -e '"react"' package.json 
    "@storybook/addon-essentials": "^6.0.16",
    "@storybook/react": "6.0.16",
    "react": "16.13.1",
    "styled-components": "5.1.1",

Example/index.js:

import PropTypes from 'prop-types';
import styled from 'styled-components';

export const Example = styled.p`
  background-color: ${props => props.color};
  height: 100px;
  width: 100px;
`;

Example.propTypes = {
  /** background color */
  color: PropTypes.string.isRequired,
};

Example/index.stories.js:

import React from 'react';
import {Example} from '.';

export default {
  component: Example,
  title: 'Example',
};

export const Default = args => <Example {...args} />;
Default.args = {
  color: 'red',
};

image

If I wrap the component in a dummy wrapper...

import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';

const _Example = styled.p`
  background-color: ${props => props.color};
  height: 100px;
  width: 100px;
`;

export const Example = args => <_Example {...args} />

Example.propTypes = {
  /** background color */
  color: PropTypes.string.isRequired,
};

...then the documentation and the auto-generated controls work:
image

But of course I don't want to do that, because it adds another level in the React component browser every time I use the component. Dumping the component to the browser console could hint at the root cause: it is an object and not a function that returns react components:
image

I've encountered the same in trying to migrate a Design System to Storybook 6.

@sdalonzo an upvote on the original issue is the best way to help get this fixed (aside from contributing a fix)

@stefanb2 if you want a function that returns react components, you could do it this way:

import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';

const _Example = styled.p`
  background-color: ${props => props.color};
  height: 100px;
  width: 100px;
`;

export function Example({ children, ...props}) {
  return <_Example {...props}>{children}</_Example>
}

Example.propTypes = {
  /** background color */
  color: PropTypes.string.isRequired,
};

and in the file example.stories.js you use it this way:

import React from "react"
import { Example } from "../components/Example"
import { action } from "@storybook/addon-actions"

export default {
  title: "Example",
  component: Example,
}

export const BackgroundColor = (args) => (
  <Example {...args} onClick={action("Clicked!")}>
    This is a button
  </Example>
)
BackgroundColor.args = {
  color: "#aaff33",
}
Was this page helpful?
0 / 5 - 0 ratings