Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Story source code shows "MDXCreateElement" instead of actual source code #11542

Closed
NicolaSansom opened this issue Jul 14, 2020 · 45 comments
Closed

Comments

@NicolaSansom
Copy link

NicolaSansom commented Jul 14, 2020

Describe the bug
The output of Show Code tabs mismatches the source

To Reproduce

  1. Create a new .mdx story:
# Alert 

<Preview>
  <Story name="Alert with one option">
    {() => {
      const [visible, toggleVisible] = useState(false);
      return (
        <div>
          <button onClick={() => toggleVisible(!visible)}>Open Alert with one action</button>
          <Alert
            visible={visible}
            toggleVisible={() => toggleVisible(false)}
            title="Title"
            description="Description"
          />
        </div>
      );
    }}
  </Story>
</Preview>
  1. Click on 'Show Code'
  2. Scroll down to screenshot of output

Expected behavior
Output match contents of the <Story>

Screenshots
image

Code snippets
Full Story

import { Story, Preview, Props } from '@storybook/addon-docs/blocks';
import { withA11y } from '@storybook/addon-a11y';
import { useState } from 'react';
import OverlayAlert from './OverlayAlert';

<Meta title="Components/Overlay - Alert" component={OverlayAlert} decorators={[withA11y]} />

# Overlay - Alert

<Preview>
  <Story name="Alert with one option">
    {() => {
      const [visible, toggleVisible] = useState(false);
      return (
        <div>
          <button onClick={() => toggleVisible(!visible)}>Open Alert with one action</button>
          <Alert
            visible={visible}
            toggleVisible={() => toggleVisible(false)}
            title="Title"
            description="Description"
          />
        </div>
      );
    }}
  </Story>
</Preview>

Main.js

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

Show code output

<MDXCreateElement
  mdxType="div"
  originalType="div"
>
  <MDXCreateElement
    mdxType="button"
    onClick={() => {}}
    originalType="button"
  >
    Open Alert with one action
  </MDXCreateElement>
  <MDXDefaultShortcode
    description="Description"
    title="Title"
    toggleVisible={function noRefCheck() {}}
  />
</MDXCreateElement>

System:
Environment Info:

System:
OS: macOS 10.15.5
CPU: (12) x64 Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
Binaries:
Node: 10.15.2 - /usr/local/bin/node
Yarn: 1.17.3 - /usr/local/bin/yarn
npm: 6.4.1 - /usr/local/bin/npm
Browsers:
Chrome: 83.0.4103.116
Firefox: 74.0
Safari: 13.1.1
npmPackages:
@storybook/addon-a11y: ^6.0.0-rc.3 => 6.0.0-rc.3
@storybook/addon-actions: ^6.0.0-rc.3 => 6.0.0-rc.3
@storybook/addon-controls: ^6.0.0-beta.15 => 6.0.0-beta.15
@storybook/addon-docs: ^6.0.0-rc.3 => 6.0.0-rc.3
@storybook/addon-links: ^6.0.0-rc.3 => 6.0.0-rc.3
@storybook/addon-viewport: ^6.0.0-rc.3 => 6.0.0-rc.3
@storybook/addons: ^6.0.0-rc.3 => 6.0.0-rc.3
@storybook/preset-create-react-app: ^3.1.2 => 3.1.3
@storybook/react: ^6.0.0-rc.3 => 6.0.0-rc.3
@storybook/theming: ^6.0.0-rc.3 => 6.0.0-rc.3

@fgaleano
Copy link

I'm encountering the same issue using React and CSF stories.

The code shown in "Show Code" is the computed output of the component and not the content of the actual story. It shows props that have default values but were not actually passed to the component in the story code.

I haven't tried using addon-storysource in Canvas mode to confirm that plugin does pick up the story's content like it used in the past. But I was expecting the same behavior in Docs.

@shilman
Copy link
Member

shilman commented Jul 15, 2020

Yes will offer the ability to configure, hopefully this week

@robbertkl
Copy link
Contributor

It seems to only occur when using an intermediate variable (including the template/bind pattern):

export const test = args => <Button {...args} />;

<Preview>
  <Story name="button">
    {test}
  </Story>
</Preview>

☝️ Does not work (shows MDXCreateElement)

<Preview>
  <Story name="button">
    {args => <Button {...args} />}
  </Story>
</Preview>

☝️ Does work (shows Button)

@yyynnn
Copy link

yyynnn commented Jul 28, 2020

@robbertkl nah, not working

@robbertkl
Copy link
Contributor

@yyynnn Thanks for your very helpful comment, are you a troll?

The 2nd example I gave does work (shows the correct in the source), both on rc.3 (for which this issue was originally filed) and on rc.16(the current @next).

@yyynnn
Copy link

yyynnn commented Jul 28, 2020

@robbertkl sorry
never meant to be

after some rm-rf magic + update to rc.16 it started working

someone should update the docs probably

@robbertkl
Copy link
Contributor

Another thing I've noticed is decorators can cause this as well, but only component (and possibly story) decorators, not global ones:

When I have working source code display (by avoiding an intermediate variable), and add a decorator to <Meta decorators={[]} it shows my decorator's wrapping elements in the source, as MDXCreateElements. However, when I add the same decorator as a global one (in .storybook/preview.js with export const decorators) it does not show up in the source and it shows the correct story source code.

(running 6.0.13, the current @latest)

@shilman
Copy link
Member

shilman commented Sep 1, 2020

As a workaround you can set the docs.source.type story parameter to "code".

@estreske
Copy link

estreske commented Sep 1, 2020

@shilman Thanks for workaround. Is it possible for you to provide a quick code snippet for the workaround in MDX?

@Luciferzhangyi
Copy link

Luciferzhangyi commented Sep 2, 2020

@shilman Thanks for the work around. But seems not working for me. After I set docs.source.type to "code". It shows Template.bind({})

@git-arbitrarysystems
Copy link

@shilman Thanks for the work around. But seems not working for me. After I set docs.source.type to "code". It shows Template.bind({})

This is still an issue in version 6.1.0-alpha.3. However if i use {args => <TestComponent {...args} />} instead of Template.bind({}) it works correctly.

TestComponent.stories.mdx

import { Meta, Story, Canvas, ArgsTable } from "@storybook/addon-docs/blocks";
import { TestComponent } from "./TestComponent";

<Meta title="Generated/TestComponent" component={TestComponent} />

# TestComponent

This is the default description for a component in mdx format

<Canvas>
    <Story name="Primary" args={{ value: "primary" }}>
        {args => <TestComponent {...args} />}
    </Story>
</Canvas>

## Properties

<ArgsTable of={TestComponent} />

@molebox
Copy link

molebox commented Sep 9, 2020

Another thing I've noticed is decorators can cause this as well, but only component (and possibly story) decorators, not global ones:

When I have working source code display (by avoiding an intermediate variable), and add a decorator to <Meta decorators={[]} it shows my decorator's wrapping elements in the source, as MDXCreateElements. However, when I add the same decorator as a global one (in .storybook/preview.js with export const decorators) it does not show up in the source and it shows the correct story source code.

(running 6.0.13, the current @latest)

Just wanted to drop in and say that removing the decorators from the components (per the answer quoted) worked for me

@keann
Copy link

keann commented Oct 9, 2020

The trick with an inline function mentioned by @robbertkl works only for the root element, while others provided via Args are still shown as MDXCreateElement:

Source

<Canvas>
  <Story
    name="SvgIcon"
    args={{
      children: <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" />,
      color: 'lightgreen',
      size: 40,
    }}
  >
    {(args) => <SvgIcon {...args} />}
  </Story>
</Canvas>

Preview

<SvgIcon
  color="lightgreen"
  size={40}
>
  <MDXCreateElement
    d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"
    mdxType="path"
    originalType="path"
  />
</SvgIcon>

(SB@6.0.26)

@pconrad
Copy link

pconrad commented Apr 18, 2021

This issue is still happening for me with Storybook 6.2.8, and I can't seem to find any work around.

UPDATE: I did find that the set docs.source.type story parameter to "code" did work. But it was not at all obvious what this meant to a newcomer to Storybook. If that's you, here's what I had to do:

In the file .storybook/preview.js, I previously had:

import "../src/index.css";
import "bootstrap/dist/css/bootstrap.css";

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
};

I changed this to:

import "../src/index.css";
import "bootstrap/dist/css/bootstrap.css";

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
  docs: {
    source: {
      type: "code"
    }
  }
};

Then the Show Code feature showed the real code, e.g.:

args => {
  return <BrowserRouter>
      <AppNavbar {...args} />
    </BrowserRouter>;
}

instead of:

<MDXCreateElement
  mdxType="BrowserRouter"
  originalType={() => {}}
>
  <MDXCreateElement
    label="Example"
    mdxType="AppNavbar"
    originalType={function noRefCheck() {}}
  />
</MDXCreateElement>

@jimmynotjim
Copy link

Landed here due to the same issue as everyone above. Can confirm that the suggested fix from @robbertkl works in my case. I'd be happy to update the MDX documentation in a PR if it'll be accepted.

{(args) => <Component {args} />}

@sarahbethfederman
Copy link

sarahbethfederman commented Apr 27, 2021

It's pretty important to be able to see what the passed args are for developers to be able to make use of the code examples, so the above solution doesn't work for us.

I've moved us over to defining the stories in tsx and importing them into the mdx as above and it's working much better, esp with stuff like styled components, and now we get typing :)

@classicfork
Copy link

@pconrad Solution worked for our Storybook mdx files and we are using the template binding. It cleared all the MDXCreateElement tags and it now displays our source code accurately.

@shilman
Copy link
Member

shilman commented May 24, 2021

Shiver me timbers!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.3.0-alpha.41 containing PR #14652 that references this issue. Upgrade today to the @next NPM tag to try it out!

npx sb upgrade --prerelease

Closing this issue. Please re-open if you think there's still more to do.

@shilman shilman closed this as completed May 24, 2021
@shilman shilman reopened this May 24, 2021
@sarahbethfederman
Copy link

Just a note, I've just realized that importing the stories in tsx like so (approach suggested by @smathson )

<Canvas withSource="open">
  <Story name="Text component" story={stories.Interactive} />
</Canvas>

This causes there to be no add-on panel to be shown at all in the canvas view, though argtables work fine in the docs mode. @shilman is this expected behavior?

@shilman
Copy link
Member

shilman commented May 28, 2021

Son of a gun!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.3.0-beta.3 containing PR #15071 that references this issue. Upgrade today to the @next NPM tag to try it out!

npx sb upgrade --prerelease

Closing this issue. Please re-open if you think there's still more to do.

@shilman shilman closed this as completed May 28, 2021
@shilman
Copy link
Member

shilman commented May 28, 2021

Jeepers creepers!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.3.0-beta.4 containing PR #15071 that references this issue. Upgrade today to the @next NPM tag to try it out!

npx sb upgrade --prerelease

GewoonMaarten added a commit to nl-design-system/denhaag that referenced this issue Jun 23, 2021
storybook will not display the right code. See storybookjs/storybook#11542
GewoonMaarten added a commit to nl-design-system/denhaag that referenced this issue Jun 23, 2021
storybook will not display the right code. See storybookjs/storybook#11542
@marti6jm
Copy link

I'm on 6.3.4 and running into this issue. I see that the fix has been tagged in one of the 6.3.0 beta releases but not one of the proper releases. Does that mean it hasn't made it into storybook proper?

@shilman
Copy link
Member

shilman commented Aug 2, 2021

@marti6jm everything that goes into a 6.3 prerelease makes it into the 6.3 final release unless some other PR explicitly removes it (which is rare ... and not the case here). Do you have a reproduction repo I can look at?

@robertwt7
Copy link

Hey there @shilman

Mine shows correctly now when I press showCode, however when my component still detects the childElement.type as MDXCreateElement, do you know how to avoid this?

I have this code that basically says my Tabs component only accept Tab children:

      let error = null
      if (childElement.type.displayName !== 'Tab') {
        error = new Error(`${TABS_DISPLAY_NAME} children should be a type of Tab, found children: ${childElement.type?.displayName}`)
        return error 

It returns error.

Right now I can do this on separate file:

export const TemplateWithChildren = ({ size, ...othersProps }: TemplateProps): JSX.Element => {
  const [value, setValue] = useState<string | number>('a')
  return (
    <div style={{ width: '400px' }}>
      <Tabs value={value} onChange={(value) => setValue(value)} {...othersProps} defaultValue='a' size={size}>
        <Tab value='a'><Text bold>Tab A</Text></Tab>
        <Tab value='b'><Text bold>Tab B</Text></Tab>
        <Tab value='c'><Text bold>Tab C</Text></Tab>
      </Tabs>
    </div>
  )
}

// Import in stories.mdx

<Canvas>
<Story name="Medium" args={{
  size: "Medium",
  animation: false
}}>
  {TemplateWithChildren.bind()}
</Story>
</Canvas>

However when I press show code, it shows me TemplateWIthChildren.bind().

Seems like i'm out of workaround..

We're on the latest version:

    "@storybook/addon-docs": "^6.3.7",
    "@storybook/addon-essentials": "^6.3.7",
    "@storybook/addon-links": "^6.3.7",
    "@storybook/builder-webpack5": "^6.3.7",
    "@storybook/channels": "^6.3.7",
    "@storybook/client-api": "^6.3.7",
    "@storybook/manager-webpack5": "^6.3.7",
    "@storybook/react": "^6.3.7",

@shilman
Copy link
Member

shilman commented Sep 11, 2021

@robertwt7 There are multiple ways to handle this. maybe try a different pattern, such as https://github.com/storybookjs/storybook/blob/next/addons/docs/docs/recipes.md#csf-stories-with-mdx-docs

I'm not sure which ones work well with generated source code, but they should all get around the issue you're having with the MDX-generated code.

@robertwt7
Copy link

@shilman thanks for your answer, really appreciate it. When I used csf stories I end up getting no code available when rendering, I notice that it might be some of our webpack problem that is related to #8104.

I end up putting them on the same file like this:

### Medium Size

<Canvas>
<Story name="Medium" args={{
  animation: false,
  size: 'Medium'
}}>
  {TemplateWithChildren.bind({})}
</Story>
</Canvas>

It renders perfectly, I just have one last question if you don't mind.

Currently when I click show code, it shows this:


args => {
  const [value, setValue] = useState('a');
  return <div style={{
    width: '400px'
  }}>
      <Tabs value={value} onChange={value => setValue(value)} defaultValue='a' {...args}>
        <Tabs.Item value='a'><Text bold>Tab A</Text></Tabs.Item>
        <Tabs.Item value='b'><Text bold>Tab B</Text></Tabs.Item>
      </Tabs>
    </div>;
}

Is this expected? I thought that the args will be mapped (animation and size props) so that the docs will be clear.

@matthew-dean
Copy link

Arrrgh, nothing on this thread seems to be working (on 6.4.19)... I have a component like:

<Story
    name="TextComposition"
    args={{
      children: (
        <>
          <Text type='hero' as='h1'>Look at this source!</Text>
          <p>The &lt;Text /&gt; component is designed so that it can apply to individual bits of text, but it can also serve as a text block for laying out simple paragraphs (&lt;p&gt;) and headings (&lt;h3&gt;).</p>
          <Text type='subtitle1'>This is a subtitle</Text>
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. At nisi sit vulputate rhoncus, ultrices sed. Augue nisi maecenas malesuada accumsan tristique tellus tortor eget erat. Tincidunt euismod nec in imperdiet mollis eget varius sollicitudin. Et lorem eu elit pretium. Faucibus in nec dis pretium aliquam. Arcu, iaculis blandit elementum viverra.</p>
          <div>
            <div>An arbitrary div block</div>
            <div>Items should not get </div>
            <div>spaced.</div>
          </div>
        </>
      )
    }}>
    {Template.bind({})}
  </Story>

However, the code shows:

<MDXCreateElement
      mdxType="p"
      originalType="p"
    >
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. At nisi sit vulputate rhoncus, ultrices sed. Augue nisi maecenas malesuada accumsan tristique tellus tortor eget erat. Tincidunt euismod nec in imperdiet mollis eget varius sollicitudin. Et lorem eu elit pretium. Faucibus in nec dis pretium aliquam. Arcu, iaculis blandit elementum viverra.
    </MDXCreateElement>
    <MDXCreateElement
      mdxType="div"
      originalType="div"
    >
      <MDXCreateElement
        mdxType="div"
        originalType="div"
      >
        An arbitrary div block
      </MDXCreateElement>
      <MDXCreateElement
        mdxType="div"
        originalType="div"
      >
        Items should not get{' '}
      </MDXCreateElement>
      <MDXCreateElement
        mdxType="div"
        originalType="div"
      >
        spaced.
      </MDXCreateElement>
    </MDXCreateElement>

This only happens in the MDX format.

@slackjaw47
Copy link

slackjaw47 commented Apr 5, 2022

@matthew-dean I've added this to the <Meta /> object and it fixes the issue.

parameters={{ docs: { source: { type: 'code', }, }, }}

If you're using the default export then adding the parameters key should work as well. Hope this helps.

@ekfuhrmann
Copy link

ekfuhrmann commented Oct 6, 2022

Just to add on this thread, I'm running into a similar issue on v6.5.12.

My Input is the following:

import {
  Canvas,
  Meta,
  Story,
  Props,
  Preview,
  ArgsTable,
} from '@storybook/addon-docs';
import { Button } from '../components/Button';
import * as Icons from '../components/Icons';
import { CloseIcon, DeleteIcon, ArrowRightIcon } from '../components/Icons';

export const IconElementMapping = Object.fromEntries(
  Object.entries(Icons).map(([name, Component]) => [name, <Component />]),
);

export const iconOptions = {
  options: ['No Icon'].concat(Object.keys(Icons)),
  mapping: {
    'No Icon': undefined,
    ...IconElementMapping,
  },
};

<Meta
  title='Inputs/Buttons'
  component={Button}
  argTypes={{
    startIcon: iconOptions,
    endIcon: iconOptions,
  }}
  parameters={{
    viewMode: 'docs',
  }}
/>

# Buttons

Buttons represents a clickable element that the user can interact with.

<Canvas withToolbar withSource='open'>
  <Story
    name='Buttons'
    args={{
      children: 'Label',
      onClick: undefined,
    }}>
    {(args) => <Button {...args} />}
  </Story>
</Canvas>

<ArgsTable story='Buttons' />

...

While everything works well including an interactive ArgsTable, the moment I add a startIcon or an endIcon via the ArgsTable, my code output is the following:

<Button endIcon={<MDXCreateElement mdxType="Icon" originalType={() => {}}/>}>
  Label
</Button>

Instead of the expected output being:

<Button endIcon={<AddIcon />}>
  Label
</Button>

@sneko
Copy link

sneko commented Jan 4, 2023

2023, still happening.

I set:

  docs: {
    source: {
      type: 'code',
    },
  }

And I get:

args => {
  return <RetrievePasswordForm {...args} />;
}

It basically returns the Template... any way to work around this please?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment