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

UI: Add storyStatus to sidebar UI #23342

Merged
merged 22 commits into from
Jul 12, 2023
Merged

Conversation

ndelangen
Copy link
Member

What I did

  • change the UI sidebar to show the status of stories
  • make groups/components show the accumulated status via a color
  • improve/add various stories I used to test this feature

How to test

  • You need a way to set statuses on stories. Right now this API is so new, nothing uses it yet. So create your own addon that adds it:
    • rename manager.ts in ui/.storybook to manager.tsx
    • set it's contents to:
      import { addons, types } from '@storybook/manager-api';
      import { IconButton, Icons } from '@storybook/components';
      import startCase from 'lodash/startCase.js';
      import React, { Fragment } from 'react';
      
      addons.setConfig({
        sidebar: {
          renderLabel: ({ name, type }) => (type === 'story' ? name : startCase(name)),
        },
      });
      
      addons.register('lalala', (api) => {
        addons.add('lalala', {
          title: 'lalala',
          type: types.TOOL,
          render() {
            return (
              <Fragment>
                <IconButton
                  title="lalala"
                  onClick={() => {
                    const { id } = api.getCurrentStoryData();
      
                    api.experimental_updateStatus('lalala', {
                      [id]: {
                        description: 'lalala',
                        status: 'error',
                        title: 'lalala',
                        data: {},
                      },
                    });
                  }}
                >
                  <Icons icon="failed" />
                </IconButton>
                <IconButton
                  title="lalala"
                  onClick={() => {
                    const { id } = api.getCurrentStoryData();
      
                    api.experimental_updateStatus('lalala', {
                      [id]: {
                        description: 'lalala',
                        status: 'warn',
                        title: 'lalala',
                        data: {},
                      },
                    });
                  }}
                >
                  <Icons icon="changed" />
                </IconButton>
                <IconButton
                  title="lalala"
                  onClick={() => {
                    const { id } = api.getCurrentStoryData();
      
                    api.experimental_updateStatus('lalala', {
                      [id]: {
                        description: 'lalala',
                        status: 'success',
                        title: 'lalala',
                        data: {},
                      },
                    });
                  }}
                >
                  <Icons icon="passed" />
                </IconButton>
      
                <IconButton
                  title="foobar"
                  color="red"
                  onClick={() => {
                    const { id } = api.getCurrentStoryData();
      
                    api.experimental_updateStatus('foobar', {
                      [id]: {
                        description: 'foobar',
                        status: 'error',
                        title: 'foobar',
                        data: {},
                      },
                    });
                  }}
                >
                  <Icons icon="failed" />
                </IconButton>
                <IconButton
                  title="foobar"
                  onClick={() => {
                    const { id } = api.getCurrentStoryData();
      
                    api.experimental_updateStatus('foobar', {
                      [id]: {
                        description: 'foobar',
                        status: 'warn',
                        title: 'foobar',
                        data: {},
                      },
                    });
                  }}
                >
                  <Icons icon="changed" />
                </IconButton>
                <IconButton
                  title="foobar"
                  onClick={() => {
                    const { id } = api.getCurrentStoryData();
      
                    api.experimental_updateStatus('foobar', {
                      [id]: {
                        description: 'foobar',
                        status: 'success',
                        title: 'foobar',
                        data: {},
                      },
                    });
                  }}
                >
                  <Icons icon="passed" />
                </IconButton>
              </Fragment>
            );
          },
        });
      });
  • start the UI storybook
  • navigate to a story
  • click the button from the custom addon in the toolbar to set status
  • the first 3 fake being set from addon "A" and the last 3 fake being set from addon "B"
  • when setting both "A" and "B" on a single story, the highest priority status should be shown.
  • when you click on the icon to the right of the story name in the sidebar, you should see an tooltip with all both "A" and "B"
  • expect all groups above the story with status to also have a changed color, but no icon.

Checklist

  • Make sure your changes are tested (stories and/or unit, integration, or end-to-end tests)
  • Make sure to add/update documentation regarding your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Maintainers

  • If this PR should be tested against many or all sandboxes,
    make sure to add the ci:merged or ci:daily GH label to it.
  • Make sure this PR contains one of the labels below.

["cleanup", "BREAKING CHANGE", "feature request", "bug", "documentation", "maintenance", "dependencies", "other"]

Copy link
Member

@tmeasday tmeasday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works great!

Do we have a design for what should happen in the search? Do statuses show up @MichaelArestad?

Either way I think it'd be good to add some tests for search results with + without statuses.

code/ui/manager/src/components/sidebar/Tree.tsx Outdated Show resolved Hide resolved
Comment on lines +227 to +233
data-selected={isSelected}
data-ref-id={refId}
data-item-id={item.id}
data-parent-id={item.parent}
data-nodetype={item.type === 'docs' ? 'document' : 'story'}
data-highlightable={isDisplayed}
className="sidebar-item"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a breaking change? I assume you do this so the attributes wrap the icon/tooltip. You could alternatively just put the icon/tooltip inside the DocumentNode/StoryNode?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't consider it a breaking change.. I had to make it because the leaf-node is an anchor tag with a href.
I can't put another button or anchor inside, that's invalid.
So I moved these attributes and background styling up to the wrapper, made that display:flex and added the icon (it's clickable!) besides the link.

{(item.renderLabel as (i: typeof item) => React.ReactNode)?.(item) || item.name}
</BranchNode>
);
if (item.type === 'component' || item.type === 'group') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this check redundant? TS says so. I would prefer to throw if the runtime type doesn't match, don't you think?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it's redundant, I thought it made the code more clear.

Are you saying I should remove the if-statement, or add a throw at the end, if there were no matches?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you think it's clearer, I guess that's good. But yeah, I think throwing at the end rather than null is probably better if TS thinks its impossible. WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be impossible, but I see no reason to risk throwing an error. Because throwing here would mean react completely unmounts the whole manager app.

code/ui/manager/src/components/sidebar/Tree.tsx Outdated Show resolved Hide resolved
@ndelangen
Copy link
Member Author

AFAIK the search shouldn't show status

@ndelangen ndelangen requested a review from tmeasday July 11, 2023 19:53
Copy link
Member

@tmeasday tmeasday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM if @MichaelArestad can confirm:

AFAIK the search shouldn't show status

@ndelangen
Copy link
Member Author

@MichaelArestad If you think I should add indicators for the search UI, or you'd like to iterate on the exact design details, I'd love to do that in a follow-up PR.

@ndelangen ndelangen merged commit 2e2f7dd into release/7.2 Jul 12, 2023
@ndelangen ndelangen deleted the norbert/story-status-ui branch July 12, 2023 11:29
@MichaelArestad
Copy link
Contributor

@ndelangen Thanks. I need time to specify what we should do with search results. Right now, I think you made the right choice to move on.

@martinsik
Copy link

martinsik commented Aug 16, 2024

Is there any documentation on how to use this feature?

@ndelangen
Copy link
Member Author

No, It's still marked as experimental, for now.

We'll revisit the documentation in 9.0.

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

Successfully merging this pull request may close these issues.

4 participants