storybookjs / storybook

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

[Bug]: Storybook Angular not setting required Inputs() correctly #28706

Open atomicrobokid opened 3 months ago

atomicrobokid commented 3 months ago

Describe the bug

I have a very simple component with a story. The component has an input: @Input({ required: true }) public title: string;

Compodoc successfully generates the correct object:

   {
      "required": true,
      "name": "title",
      "deprecated": false,
      "deprecationMessage": "",
      "optional": false,
      "line": 20,
      "type": "string",
      "decorators": []
    }

However it appears the Storybook does not pick up the required property automatically (implied by the docs that Storybook will infer required fields) and set the argType in the table to required.

If I manually add the required flag to the argTypes in the story meta, it works (with some caveats)

Story meta (shortened for brevity)

const meta: Meta<TestComponent> = {
  title: 'TestComponent',
  component: TestComponent,
  argTypes: {
    title: {
      // @ts-ignore
      type: { required: true },
      control: { type: 'text' },
    },
  },
};

So here we see the second issue. I have to add @ts-ignore as it throws a Typescript error Type { required: true; } is not assignable to type - however it works, so feels like something is missing from the @storybook/angular Meta type

I've noticed that if you set argType with a name, typescript doesn't complain:

type: { name: 'string', required: true },

Feels strange having to set the name to one of the accepted types, as it doesn't appear to actually do anything. Could maybe make name optional?

Reproduction link

https://stackblitz.com/edit/storybook-angular-required-fields?file=src%2Fstories%2Fbutton.stories.ts

Reproduction steps

  1. Go to the above link (might need to manually navigate to the Primary button story in the preview)
  2. Note the required field is appearing after manually setting type: { required: true}
  3. Remove @ts-ignore to see first issue - Angular Meta definition doesn't see type as valid
  4. Remove the argType.primary config entirely so it reverts to Storybooks inferred setup for the control
  5. Notice how the field is not marked as required even though compodoc marks it as required: true

System

Storybook Environment Info:

  System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 18.20.3 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 10.2.3 - /usr/local/bin/npm <----- active
    pnpm: 8.15.6 - /usr/local/bin/pnpm
  npmPackages:
    @storybook/addon-docs: ^8.3.0-alpha.2 => 8.3.0-alpha.2 
    @storybook/addon-essentials: ^8.3.0-alpha.2 => 8.3.0-alpha.2 
    @storybook/addon-interactions: ^8.3.0-alpha.2 => 8.3.0-alpha.2 
    @storybook/addon-links: ^8.3.0-alpha.2 => 8.3.0-alpha.2 
    @storybook/addon-onboarding: ^8.3.0-alpha.2 => 8.3.0-alpha.2 
    @storybook/angular: ^8.3.0-alpha.2 => 8.3.0-alpha.2 
    @storybook/blocks: ^8.3.0-alpha.2 => 8.3.0-alpha.2 
    @storybook/test: ^8.3.0-alpha.2 => 8.3.0-alpha.2 
    storybook: ^8.3.0-alpha.2 => 8.3.0-alpha.2 

Additional context

Feels like there's two issue here but closely related:

  1. The Meta type from @storybook/angular needs to be able to see type: {} as valid if just required is set
  2. Probably more important to me, Storybook needs to infer from compodoc that if a field is marked as required in the component and the property "required": true exists in the documentation.json then automatically mark that control as required without having to manually add that info to the control. Much nicer dev experience
greptile-apps[bot] commented 3 months ago

Disclaimer This information might be inaccurate, due to it being generated automatically To address the issue of Storybook Angular not setting required Inputs correctly, follow these steps:

  1. Update Meta Type: Modify the Meta type in @storybook/angular to accept type with a required property.

    // Path: /code/frameworks/angular/src/types.ts
    export interface ArgType {
     type?: { name?: string; required?: boolean };
     // other properties...
    }
  2. Infer Required Fields: Enhance the logic to infer required fields from compodoc.

    // Path: /code/frameworks/angular/src/client/preview/angular/compodoc.ts
    function inferArgTypesFromCompodoc(compodocJson) {
     return compodocJson.reduce((acc, doc) => {
       acc[doc.name] = {
         type: { name: doc.type, required: doc.required },
         // other properties...
       };
       return acc;
     }, {});
    }
  3. Example Usage: Update your story to use the new Meta type.

    // Path: /code/frameworks/angular/template/stories/basics/component-with-provider/di.component.stories.ts
    const meta: Meta<DiComponent> = {
     component: DiComponent,
     argTypes: {
       title: { type: { name: 'string', required: true }, control: 'text' },
     },
    };
    export default meta;

References

/docs/_snippets/api-doc-block-argtypes-parameter.md /code/frameworks/angular/template/stories/basics/component-with-provider/di.component.stories.ts /code/lib/blocks/src/examples/ArgTypesWithSubcomponentsParameters.stories.tsx /docs/_snippets/button-story-with-parameters.md /docs/_snippets/component-story-auto-title.md /code/core/src/csf-tools/CsfFile.test.ts /docs/_snippets/component-story-sort-controls.md /docs/_snippets/button-story-controls-radio-group.md /docs/_snippets/arg-types-in-meta.md /docs/_snippets/component-story-conditional-controls-toggle.md /docs/_snippets/arg-types-options.md /code/renderers/server/template/cli/button.stories.json /docs/_snippets/button-story-hypothetical-example.md /.github/DISCUSSION_TEMPLATE/ideas.yml /docs/_snippets/button-story-baseline.md /code/frameworks/angular/template/stories/core/README.mdx /code/renderers/vue3/src/public-types.test.ts /code/frameworks/angular/template/stories/basics/component-with-enums/enums.component.stories.ts /.github/DISCUSSION_TEMPLATE/rfc.yml /docs/_snippets/checkbox-story-grouped.md /docs/_snippets/storybook-preview-with-angular-polyfills.md /code/frameworks/angular/template/stories/basics/README.mdx /docs/_snippets/api-doc-block-story-parameter.md /docs/_snippets/arg-types-control.md /code/frameworks/angular/template/stories/basics/angular-forms/customControlValueAccessor/custom-cva-component.stories.ts

#### About Greptile This response provides a starting point for your research, not a precise solution. Help us improve! Please leave a ๐Ÿ‘ if this is helpful and ๐Ÿ‘Ž if it is irrelevant. [Ask Greptile](https://app.greptile.com/chat/github/storybookjs/storybook/next) ยท [Edit Issue Bot Settings](https://app.greptile.com/apps/github)