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

[Bug]: DocsPage does not respect story sort #19605

Closed
iansan5653 opened this issue Oct 24, 2022 · 4 comments
Closed

[Bug]: DocsPage does not respect story sort #19605

iansan5653 opened this issue Oct 24, 2022 · 4 comments

Comments

@iansan5653
Copy link

iansan5653 commented Oct 24, 2022

Describe the bug

The DocsPage feature seems to be ignoring the sort order of my stories. For example, I have this Avatar component which exports five stories:

const metadata: Meta = {
  component: Avatar
}

export default metadata

export function Default() { /*...*/ }

export function Square() { /*...*/ }

export function CustomSize() { /*...*/ }

export function CustomAltText() { /*...*/ }

export function CustomStyling() { /*...*/ }

This looks correct in the story navigation sidebar:

The sidebar section for 'Avatar'. Under the component name is (in order): Docs, Default, Square, Custom Size, Custom Alt Text, and Custom Styling.

However, on the automatically generated Docs page, the stories seem to be rendered in random order:

The docs page for 'Avatar'. The default story is 'Custom Alt Text', followed by (in order): Custom Size, Custom Styling, Default, and Square.

As you can see from the screenshot, the default (top) story is not "Default" as I would expect. Instead it's "Custom Alt Text" and the rest of the stories follow in apparently random order.

To Reproduce

This repository has no changes at all from the npx sb@next repro output but it does still reproduce the problem. For example, see the Button stories - the first story should be Primary but instead it's Large.

System

System:
    OS: Linux 5.4 Ubuntu 20.04.5 LTS (Focal Fossa)
    CPU: (4) x64 Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz
  Binaries:
    Node: 16.18.0 - ~/.nodejs/current/bin/node
    Yarn: 3.2.4 - /usr/bin/yarn
    npm: 8.19.2 - ~/.nodejs/current/bin/npm
  npmPackages:
    @storybook/addon-docs: ^7.0.0-alpha.42 => 7.0.0-alpha.42 
    @storybook/addon-essentials: ^7.0.0-alpha.42 => 7.0.0-alpha.42 
    @storybook/addon-interactions: ^7.0.0-alpha.42 => 7.0.0-alpha.42 
    @storybook/addon-links: ^7.0.0-alpha.42 => 7.0.0-alpha.42 
    @storybook/react: ^7.0.0-alpha.42 => 7.0.0-alpha.42 
    @storybook/react-webpack5: ^7.0.0-alpha.42 => 7.0.0-alpha.42 
    @storybook/testing-library: ^0.0.13 => 0.0.13

Additional context

There is no storySort configured - I am using the default sort order. But the issue still happens even with a custom sort order.

@richard-jfc
Copy link

It seems that the stories returned by

const primaryCsfFile = this.store.processCSFFileWithCache<TFramework>(
are returned in alphabetical order.

I patched around it by changing

Object.keys(namedExports).forEach((key) => {
to

  __namedExportsOrder.forEach((key) => { 

Unfortunately I don't know the codebase well enough to understand whether processCSFFileWithCache should already be returning sorted exports.

@zigang93
Copy link
Contributor

I had same problem.. well it is not random.. actually is sort by alphabetical

@iansan5653
Copy link
Author

iansan5653 commented Nov 17, 2022

Just sharing my workaround. This is pretty hacky and relies on Storybook internals which may break, but it allows me to customize which story becomes the primary one. I do this by defining a custom docs page component:

import React, {useContext} from 'react'

import {Title, Subtitle, Description, Primary, ArgsTable, Stories, DocsContext, Heading} from '@storybook/addon-docs'

/** For each component, we'll extract the story with this name and use it as the primary. */
const PRIMARY_STORY_NAME = "Default"

export const DocsPage = () => {
  const context = useContext(DocsContext)

  // The 'primary' story is rendered at the top of the page. The default implementation picks
  // the first story in the alphabet; we look for one with a standard name instead and then
  // override the private field on the context object to update it.
  // This will probably break with updates to Storybook, but ideally Storybook will simultaneously
  // add configuration for the primary story so we can just set this properly.
  let primaryStoryId
  try {
    primaryStoryId = context.storyIdByName(PRIMARY_STORY_NAME) // Throws if missing

    // Even though we pass the primary story name to the ArgsTable, it still gets confused
    // and renders the wrong controls unlesss we also set the primaryStory private value
    context.primaryStory = context.storyById(primaryStoryId)
    // The Stories block is wierdly doesn't read primary story from any field or props,
    // instead just assuming the first story is primary. So even though we set that field
    // we still have to sort the stories to put the primary one first
    // see: https://github.com/storybookjs/storybook/blob/65957e6789bc57d506ca63e6f3be3927f110565e/code/ui/blocks/src/blocks/Stories.tsx
    context.componentStoriesValue = context
      .componentStories()
      // This leaves the rest of the stories in alpha order. We could instead define a custom sort here
      .sort((a, b) => (a.name === PRIMARY_STORY_NAME ? -1 : b.name === PRIMARY_STORY_NAME ? 1 : 0))
  } catch {}

  const primaryStoryFound = primaryStoryId !== undefined
  return (
    <>
      <Title />
      <Subtitle />
      <Description />

      {primaryStoryFound && <Primary name={PRIMARY_STORY_NAME} />}

      <Heading>Props</Heading>
      <ArgsTable story={primaryStoryFound ? PRIMARY_STORY_NAME : undefined} />

      <Stories includePrimary={!primaryStoryFound} />
    </>
  )
}

Which I then set in my preview.js:

export const parameters = {
  docs: {
    page: DocsPage
  }
}

@shilman
Copy link
Member

shilman commented Nov 19, 2022

closing as dupe to #19163

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

No branches or pull requests

4 participants