storybookjs / storybook

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

Addons panel position resets on story change #6114

Open malykhinvi opened 5 years ago

malykhinvi commented 5 years ago

Describe the bug Panel position is being reset to what is specified in the global options.

To Reproduce Steps to reproduce the behavior:

  1. Run CRA example (note: panelPosition: 'right' is set in the options)
  2. Open /?path=/story/button--with-text
  3. Switch addons panel to the bottom mode
  4. Open /?path=/story/button--with-some-emoji
  5. Addons panel position is reset to the right mode

Expected behavior Addons panel should be still displayed in the bottom.

Code snippets Looks like the problem is here:

// lib/ui/src/core/context.js
api.on(STORY_CHANGED, id => {
  const options = api.getParameters(id, 'options');

  api.setOptions(options);
});
// lib/ui/src/core/layout.js
const updatedLayout = {
  ...layout,
  ...pick(options, Object.keys(layout)),
  ...checkDeprecatedLayoutOptions(options),
};

setOptions is being called after every story change, and panelPosition is being reset to what is specified in the options, as ...pick(options, Object.keys(layout)), overrides whatever is in layout.

System:

malykhinvi commented 5 years ago

Should that be fixed, considering addonPanelInRight is deprecated? If it should, what is the proper fix? Should we override layout, derived from options with the current one (now it works in opposite direction, if I understand correctly)?

malykhinvi commented 5 years ago

In fact, that issue has nothing to do with deprecated options, but there is a general problem related to option overwrite on story change. Probably related to https://github.com/storybooks/storybook/issues/5857

malykhinvi commented 5 years ago

@shilman after small investigation, I updated the title and description of the bug. There are several ways to fix it, but what is the expected behaviour in the following cases:

1. Only global options are defined

  1. Global panelPosition: 'right'
  2. User changes position to 'bottom'
  3. User switches to another story
  4. panelPosition: 'bottom', correct?

2. There are custom options, specified for the set of stories

  1. Global panelPosition: 'right'; Stories A and B use global options; Story C overrides options - panelPosition: 'bottom'
  2. User is on story A and changes position to 'bottom';
  3. User switches to story B
  4. panelPosition: 'bottom', correct?

3. There are custom options, specified for the set of stories

  1. Global panelPosition: 'right'; Stories A and B use global options; Story C overrides options - panelPosition: 'bottom'
  2. User is on story A and changes position to 'bottom';
  3. User switches to story C
  4. panelPosition: 'right', correct?

4. There are custom options, specified for the set of stories

  1. Global panelPosition: 'right'; Stories A and B use global options; Story C overrides options - panelPosition: 'bottom'
  2. User is on story A and changes position to 'bottom';
  3. User switches to story C
  4. User switches to story B
  5. panelPosition: 'bottom', correct?

Proposal If I were to fix this issue, and the outcomes of the usecases above are correct, then I would change logic in the layout.js, so that:

Let me know, if that makes sense, or if I'm thinking in the completely wrong direction 😄

shilman commented 5 years ago

@malykhinvi I agree this is complex and thanks so much for taking it on!! 🙏

Here's my opinion:

  1. global layout options should update state on startup and never again
  2. story layout options should update state every time the story is navigated to
  3. navigating away from a story should not affect state
  4. user can set state manually using UI

Applying these heuristics to your cases above:

  1. Agree
  2. Agree
  3. This should end up in panelPosition: 'bottom'
  4. Agree

cc @tmeasday I think you have other ideas about state management

tmeasday commented 5 years ago

I think this issue could be discussed as part of #5857, but thanks for unpacking it with us @malykhinvi.

To start, I disagree that global and local parameters should be treated differently. Certainly we don't have a way to do so right now and I think it's unnecessarily complex too. I think doing it either way will surprise some users so I would prefer to keep it simple.

(example question: what about chapter level parameters?)

The question in my mind is how the "memory" of a layout option should work. Should it be stateful at all? (yes, probably) and should it override the parameters? (yes, probably too).

So I would probably divide options into two categories (as discussed on #5857) -- those that are modifiable in the UI and thus stateful, and those that are not (such as the title of the SB).

The simple thing to do in my mind is just ensure that if a user has a changed a stateful UI option, the story now has no way to override it. So I would disagree about the outcome of case 3.

dhananjaysa92 commented 1 year ago

IS this still active? checking