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

Get decorator to fire when user interacts with MDX Docs tab #12290

Closed
DanWahlin opened this issue Aug 28, 2020 · 9 comments
Closed

Get decorator to fire when user interacts with MDX Docs tab #12290

DanWahlin opened this issue Aug 28, 2020 · 9 comments

Comments

@DanWahlin
Copy link

DanWahlin commented Aug 28, 2020

Is your feature request related to a problem? Please describe.
A decorator function is triggered when the user clicks on the Canvas tab or loads the Canvas panel. However, when they click on the MDX Docs tab the same decorator function doesn't fire. We're using a global decorator (see below) to capture the story file name that the user is on for a custom source code viewer.

Describe the solution you'd like
It'd be great to have the decorator fire when the user clicks on Canvas or on Docs.

Describe alternatives you've considered
Considered adding some custom DOM code to handle emitting but would prefer to use the channel within a decorator.

Are you able to assist bring the feature to reality?
No (not without hacking something in anyway)

Additional context
This is the decorator currently being used that fires as expected when the user clicks on the Canvas tab. When they click the Docs tab the wrapper function doesn't fire though as mentioned. This may be the intended behavior but this type of functionality is needed for our solution.

If there's already something in place to handle this I'd be very interested - searched quite a bit but it's certainly possible I missed a potential built-in solution. Thanks in advance for your help!

import { addons, makeDecorator } from '@storybook/addons'

export default makeDecorator({
  name: 'withSourceInfo',
  parameterName: 'sourcecode',
  wrapper: (getStory, context) => {
   // fires when user clicks on Canvas tab but not on Docs tab
    const channel = addons.getChannel();
    channel.emit('sourcecode/selectedStory', context.parameters.fileName);
    return getStory(context);
  },
});
@shilman
Copy link
Member

shilman commented Aug 28, 2020

I'd expect that the decorator would be called every time a story is rendered. So if an MDX docs page has 5 stories that use that decorator, I'd expect the decorator to be called 5 times.

Storybook does not use decorators at the docs page level. It uses a container component, documented here:

https://github.com/storybookjs/storybook/blob/next/addons/docs/docs/recipes.md#overwriting-docs-container

If you wanted to fire an event when the page is rendered, you could do it with a custom container.

@shilman shilman added addon: docs and removed mdx labels Aug 28, 2020
@DanWahlin
Copy link
Author

DanWahlin commented Aug 28, 2020

Thanks for the response @shilman. I'm a little confused on the "So if an MDX docs page has 5 stories that use that decorator, I'd expect the decorator to be called 5 times." statement since you said that Storybook doesn't use decorators at the docs page level right after that. I'm probably being a bit dense. :-)

Am I correct in thinking the following:

  1. Decorators work in Canvas panels.
  2. Decorators don't work in Docs panels (even if they're defined globally, on a Meta, or Story).

I'm not seeing my decorator called at all in the Docs panel which would match with your mention of container components being used there. For example, I tried something simple within an MDX file (see below) but don't see the decorator getting called at all (it sounds like from your second statement expected behavior give it's a Docs panel). But, it works as expected in a Canvas panel which aligns with #1 and #2 above.

<!-- my.stories.mdx -->
<Story name="Demo" decorators={[(Story) => <div style={{ border: '5px solid red' }}><Story/></div>]}>
  <MyComponent />
</Story>

@DanWahlin DanWahlin reopened this Aug 28, 2020
@shilman
Copy link
Member

shilman commented Aug 28, 2020

Every time a story renders, its decorators should also be called.

A docs page can have zero or more stories on it. If it has no stories on it, no decorators will get called. The docs page itself always has a container and its container will be rendered as a wrapper every time the page rendered regardless of whether the page contains stories.

I would expect your "border decorator" above to be called. I just verified this one is called in examples/addon-docs.stories.mdx:

<Story
  name="decorator story"
  decorators={[
    (StoryFn) => (
      <div style={{ backgroundColor: 'pink' }}>
        <StoryFn />
      </div>
    ),
  ]}
>
  <>Story decorators</>
</Story>

@DanWahlin
Copy link
Author

DanWahlin commented Aug 28, 2020

Thanks - appreciate the info. I'm seeing that behavior work properly on the Canvas panel but not the Docs panel...which is the challenge. Based on your earlier statement that may be expected behavior, but still not sure on that.

I'm assuming when you tried it you saw the pink border in the Canvas and Docs panels? I'll have to look at that demo you mention.

@shilman
Copy link
Member

shilman commented Aug 29, 2020

Yep it's pink in both tabs.

@DanWahlin
Copy link
Author

Thanks @shilman! Really appreciate your time and responses. That's good to hear but a little worrisome because it means there's definitely something blocking that from happening in our project. Thanks for checking into it and for the info. I'll start peeling back layers to figure out what interrupted that process (we have quite a bit of complexity in there now :-)).

@shilman
Copy link
Member

shilman commented Aug 29, 2020

@DanWahlin Happy to pair for a few min if it helps. Are your docs stories rendering inline or in iframes? Shouldn't make a difference but it's another variation

@DanWahlin
Copy link
Author

You are seriously too kind. :-) I'll DM you.

@DanWahlin
Copy link
Author

For anyone that runs into this it was a super simple fix. My stories were running fine in Canvas and Docs modes but the decorator wasn't firing in Docs mode as mentioned above. All that was required to get it working in Docs mode was the following import (which makes total sense thanks to @shilman walking me through what's going on):

import { Story } from '@storybook/addon-docs/blocks';

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

2 participants