storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
83.94k stars 9.21k forks source link

'No code available' when using CSF stories in MDX docs - Angular #18234

Open sir-captainmorgan21 opened 2 years ago

sir-captainmorgan21 commented 2 years ago

Describe the bug We are embedding CSF stories into our MDX docs. The stories render fine, but the code snippets either say "No code available" or the "Show Code" button is available, but clicking it does nothing. We are building Angular components, but I dont know if this bug exists for other frameworks. This is the case for both inlineStories: true and inlineStories: false

To Reproduce I cant duplicate the repo because it is company work, but the production deployed storybook is at storybook.snagajob.com. More specifically you can here to see both "No code available" and "Show Code" not working: https://storybook.snagajob.com/?path=/story/design-system-button-docs--page

Code repro below:

stories.ts

import { SAJIconsModule } from '@snagajob/icons';
import { moduleMetadata, Story, Meta } from '@storybook/angular';
import { SAJButtonModule } from '..';
import { SAJButtonDirective } from './button.directive';

export default {
  title: 'Design System/Button/Stories/Primary',
  component: SAJButtonDirective,
  decorators: [
    moduleMetadata({
      imports: [
        SAJButtonModule,
        SAJIconsModule
      ],
    })
  ],
  parameters: {
    previewTabs: {
      'storybook/docs/panel': {
        hidden: true,
      }
    }
  }
} as Meta<SAJButtonDirective>;

const Template: Story<SAJButtonDirective> = (args: SAJButtonDirective) => ({
  props: args,
  template: `
    <div class="mb-8"><button sajButton [color]="color" [style]="style" [size]="size">Button</button></div>
    <div><a sajButton href="www.snagajob.com" [color]="color" [style]="style" [size]="size">Link</a></div>
  `
});

export const Filled = Template.bind({});

export const Outlined = Template.bind({});
Outlined.args = {
  style: 'outlined'
}

export const Borderless = Template.bind({});
Borderless.args = {
  style: 'borderless'
}

doc.mdx

<Canvas>
  <Story id="design-system-button-stories-primary--filled"/>
  <Story id="design-system-button-stories-primary--outlined"/>
  <Story id="design-system-button-stories-primary--borderless"/>
</Canvas>

System

System:
    OS: macOS 12.3.1
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
  Binaries:
    Node: 16.15.0 - ~/.nvm/versions/node/v16.15.0/bin/node
    npm: 8.5.5 - ~/.nvm/versions/node/v16.15.0/bin/npm
  Browsers:
    Chrome: 101.0.4951.64
    Firefox: 96.0
    Safari: 15.4
  npmPackages:
    @storybook/addon-a11y: ^6.4.19 => 6.4.19 
    @storybook/addon-essentials: ^6.4.22 => 6.4.22 
    @storybook/addon-interactions: ^6.4.19 => 6.4.19 
    @storybook/angular: ~6.4.22 => 6.4.22 
    @storybook/builder-webpack5: ~6.4.12 => 6.4.17 
    @storybook/manager-webpack5: ~6.4.12 => 6.4.17 
    @storybook/testing-library: ^0.0.9 => 0.0.9 

Thanks ahead of time @shilman :)

DzmVasileusky commented 2 years ago

Same here

But I'm using just plain MDX

Note: Show Code is sometimes working, sometimes not, pretty unstable. I can open it initially then switch to canvas and back and it will work/be broken.

I've added storybook with nx g @nrwl/angular:storybook-configuration ui-kit and running it with nx run ui-kit:storybook

So its pretty much basic configuration with some little changes

Project structure:

.storybook
- main.js
- tsconfig.js
...
libs
- ui-kit
-- .storybook
--- main.js
--- preview.js
--- tsconfig.json
--- typings.d.ts
-- src
--- stories
---- button.stories.mdx

global main.js

module.exports = {
    stories: [],
    addons: ['@storybook/addon-essentials']
    // uncomment the property below if you want to apply some webpack config globally
    // webpackFinal: async (config, { configType }) => {
    //   // Make whatever fine-grained changes you need that should apply to all storybook configs

    //   // Return the altered config
    //   return config;
    // },
};

global tsconfig.json

{
    "extends": "../tsconfig.base.json",
    "exclude": [
        "../**/*.spec.js",
        "../**/*.test.js",
        "../**/*.spec.ts",
        "../**/*.test.ts",
        "../**/*.spec.tsx",
        "../**/*.test.tsx",
        "../**/*.spec.jsx",
        "../**/*.test.jsx"
    ],
    "include": ["../**/*"]
}

local main.js

const rootMain = require('../../../.storybook/main');

module.exports = {
    ...rootMain,

    core: { ...rootMain.core, builder: 'webpack5' },

    stories: [
        ...rootMain.stories,
        '../src/stories/*.stories.mdx',
        '../src/stories/**/*.stories.mdx',
        '../src/stories/**/*.stories.@(js|jsx|ts|tsx)',
        '../src/modules/**/components/**/*.stories.mdx',
        '../src/modules/**/components/**/*.stories.@(js|jsx|ts|tsx)'
    ],
    addons: [...rootMain.addons],
    webpackFinal: async (config, { configType }) => {
        // apply any global webpack configs that might have been specified in .storybook/main.js
        if (rootMain.webpackFinal) {
            config = await rootMain.webpackFinal(config, { configType });
        }

        // add your own webpack tweaks if needed

        return config;
    }
};

local preview.js

export const parameters = {
    backgrounds: {
        default: 'light'
    }
};

local tsconfig.json

{
    "extends": "../tsconfig.json",
    "compilerOptions": {
        "emitDecoratorMetadata": true
    },
    "exclude": ["../**/*.spec.ts"],
    "files": [
        "./typings.d.ts"
    ],
    "include": ["../src/**/*", "*.js"]
}

local typings.d.ts (added to allow mdx import for TS)

declare module '*.mdx' {
    const content: string;
    export = content;
}

button.stories.mdx

import { MatButtonModule } from '@angular/material/button';
import { Canvas, Meta, Story } from '@storybook/addon-docs';
import { moduleMetadata } from '@storybook/angular';

<Meta
    argTypes={{
        disabled: {
            description: 'Disabled state',
            options: ['', 'disabled'],
            control: {
                labels: {
                    '': 'Active',
                    disabled: 'Disabled'
                },
                type: 'radio'
            }
        },
        size: {
            description: 'Size of the button',
            options: ['', 'cui-button-small'],
            control: {
                labels: {
                    '': 'Default',
                    'cui-button-small': 'Small'
                },
                type: 'select'
            }
        },
        style: {
            description: 'Style of the button',
            options: ['cui-button-primary', 'cui-button-outline', 'cui-button-white', 'cui-button-ghost'],
            control: {
                labels: {
                    'cui-button-primary': 'Primary',
                    'cui-button-outline': 'Outline',
                    'cui-button-white': 'White',
                    'cui-button-ghost': 'Ghost'
                },
                type: 'select'
            }
        }
    }}
    decorators={[
        moduleMetadata({
            imports: [MatButtonModule]
        })
    ]}
    title="Components/Button"
/>

export const ButtonTemplate = (args) => ({
    props: args,
    template: `<button mat-button class="${args.style} ${args.size}" ${args.disabled}>Button</button>`
});

# Button

-   [Overview](#overview)
-   [Modifications](#modification)
    -   [Sizes](#sizes)
    -   [Styles](#styles)
        -   [Primary](#primary)
        -   [Outline](#outline)
        -   [White](#white)
        -   [Ghost](#ghost)
    -   [Disabled](#disabled)

## Overview

<Canvas>
    <Story
        name="Overview"
        args={{
            disabled: '',
            size: '',
            style: 'cui-button-primary'
        }}
    >
        {ButtonTemplate.bind({})}
    </Story>
</Canvas>

# Modifications

## Sizes

<Canvas>
    <Story
        name="Sizes"
        args={{
            disabled: '',
            size: 'cui-button-small',
            style: 'cui-button-primary'
        }}
    >
        {ButtonTemplate.bind({})}
    </Story>
</Canvas>

## Styles

### Primary

<Canvas>
    <Story
        name="Styles"
        args={{
            disabled: '',
            size: '',
            style: 'cui-button-primary'
        }}
    >
        {ButtonTemplate.bind({})}
    </Story>
</Canvas>

### Outline

<Canvas>
    <Story
        name="Outline"
        args={{
            disabled: '',
            size: '',
            style: 'cui-button-outline'
        }}
    >
        {ButtonTemplate.bind({})}
    </Story>
</Canvas>

### White

<Canvas>
    <Story
        name="White"
        args={{
            disabled: '',
            size: '',
            style: 'cui-button-white'
        }}
    >
        {ButtonTemplate.bind({})}
    </Story>
</Canvas>

### Ghost

<Canvas>
    <Story
        name="Ghost"
        args={{
            disabled: '',
            size: '',
            style: 'cui-button-ghost'
        }}
    >
        {ButtonTemplate.bind({})}
    </Story>
</Canvas>

## Disabled

<Canvas>
    <Story
        name="Conditions"
        args={{
            disabled: 'disabled',
            size: '',
            style: 'cui-button-primary'
        }}
    >
        {ButtonTemplate.bind({})}
    </Story>
</Canvas>

<Canvas>
    <h1>Test Simple HTML</h1>
</Canvas>

Versions

"@angular/animations": "13.3.3",
"@angular/cdk": "13.3.3",
"@angular/common": "13.3.3",
"@angular/compiler": "13.3.3",
"@angular/core": "13.3.3",
"@angular/forms": "13.3.3",
"@angular/localize": "13.3.3",
"@angular/material": "13.3.3",
"@angular/platform-browser": "13.3.3",
"@angular/platform-browser-dynamic": "13.3.3",
"@angular/router": "13.3.3",
"@nrwl/angular": "13.10.2",
"@nrwl/cli": "13.10.2",
"@nrwl/storybook": "^14.1.5",
"@storybook/addon-essentials": "~6.4.12",
"@storybook/angular": "~6.4.12",
"@storybook/builder-webpack5": "~6.4.12",
"@storybook/core-server": "~6.4.12",
"@storybook/manager-webpack5": "~6.4.12",

npm -v 7.19.1 node -v v16.5.0

DzmVasileusky commented 2 years ago

It is working very unstable That's what I just got Снимок экрана 2022-05-25 в 22 08 07

DzmVasileusky commented 2 years ago
export const parameters = {
    ...
    docs: {
        inlineStories: true
    }
};

Made it different. It is working initially but when switching to Canvas and back to Docs it is not available

DzmVasileusky commented 2 years ago

Have added a repro https://github.com/DzmVasileusky/storybook-angular-nx-issue

stevenbriscoeca commented 2 years ago

storybook-doc-bug

Just adding here a gif that is related, I need to toggle an option so the show code appears...seems like a storybook bug

sir-captainmorgan21 commented 2 years ago

I actually cant replicate this anymore. I did notice that clicking "show code" can take a bit to actually show the code, so maybe some loading indicator would be ideal there?

alirezamirian commented 1 year ago

For me the issue goes away as soon as a change is made in the mdx file, causing a hot-reload.