storybookjs/storybook

[Feature Request]: Track `passedArgs` separately from `initialArgs` in `StoryContext` so code snippets in docs pages show only the props user specified.

Open

#23,317 建立於 2023年7月5日

在 GitHub 查看
 (5 留言) (2 反應) (0 負責人)TypeScript (89,909 star) (10,058 fork)batch import
argsblock: sourcebughelp wantedsev:S3

描述

Is your feature request related to a problem? Please describe

This feature request is related to #22930.

Currently additional args from the ArgEnhancers in addons (e.g., @storybook/addon-actions and @storybook/addon-interactions) are merged into StoryContext.initialArgs, which initially only contains user-specified args. This unfortunately causes <Source /> in a docs page to have additional props that have been added, not by the user but by addons, show up.

Describe the solution you'd like

I think this could be improved by tracking the args that the user has explicitly specified in their stories, say passedArgs, separate from the merged initialArgs in StoryContext. And then use this information when producing code snippets in docs pages.

Concretely, the solution I'd like would be something like the following:

Add passedArgs to StoryContextForEnhancers type found in @storybook/csf:

type StoryContextForEnhancers<TRenderer extends Renderer = Renderer, TArgs = Args> = StoryIdentifier & {
    component?: (TRenderer & {
        T: any;
    })['component'];
    subcomponents?: Record<string, (TRenderer & {
        T: any;
    })['component']>;
    parameters: Parameters;
    initialArgs: TArgs;
    passedArgs?: TArgs;  // this
    argTypes: StrictArgTypes<TArgs>;
};

Add passedArgs to contextForEnhancers in preparePartialAnnotations found at code/lib/preview-api/src/modules/store/csf/prepareStory.ts

// Pull out args[X] into initialArgs for argTypes enhancers
  const passedArgs: Args = {
    ...projectAnnotations.args,
    ...componentAnnotations.args,
    ...storyAnnotations?.args,
  } as Args;

  const contextForEnhancers: StoryContextForEnhancers<TRenderer> = {
    componentId: componentAnnotations.id,
    title: componentAnnotations.title,
    kind: componentAnnotations.title, // Back compat
    id: storyAnnotations?.id || componentAnnotations.id,
    // if there's no story name, we create a fake one since enhancers expect a name
    name: storyAnnotations?.name || '__meta',
    story: storyAnnotations?.name || '__meta', // Back compat
    component: componentAnnotations.component,
    subcomponents: componentAnnotations.subcomponents,
    tags,
    parameters,
    initialArgs: passedArgs,
    passedArgs, // this
    argTypes: passedArgTypes,
  };

Pass context.passedArgs to produce a source string.

// code/renderers/react/src/docs/jsxDecorator.tsx
// Inside `jsxDecorator` function

...

// Exclude decorators from source code snippet by default
  const storyJsx = context?.parameters.docs?.source?.excludeDecorators
    ? (context.originalStoryFn as ArgsStoryFn<ReactRenderer>)(context.passedArgs, context)  // `context.passedArgs` instead of `context.args`
    : storyFn({ args: context.passedArgs });  // `context.passedArgs` instead of `context.args`

  const sourceJsx = mdxToJsx(storyJsx);

  const rendered = renderJsx(sourceJsx, options);
  if (rendered) {
    jsx = rendered;
  }

...

When I tested this locally, the docs page doesn't show any unspecified props in code snippets, and in story pages, @storybook/addon-actions still works correctly.

Now, I've probably missed a lot of things, so I need some reviews / comments on the proposed fix from the core team!

Thanks.

Describe alternatives you've considered

No response

Are you able to assist to bring the feature to reality?

yes, I can

Additional context

No response

貢獻者指南