storybook: Blocks: Clean up `useGlobals` for docs and export it

Describe the bug I need to access the globals set by toolbar addon in the custom DocPage I have set for the docs addon. The toolbar addon documentation instructs to use the useGlobals hook to consume the globals within an addon. However, when I try to use the useGlobals hook in the DocPage it throws an error:

Uncaught TypeError: Cannot read property 'updateGlobals' of undefined
    at useGlobals (index.js:550)
    at page (button.stories.tsx:67)
    at renderWithHooks (react-dom.development.js:16260)
    at mountIndeterminateComponent (react-dom.development.js:18794)
    at beginWork$1 (react-dom.development.js:20162)
    at HTMLUnknownElement.callCallback (react-dom.development.js:336)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:385)
    at invokeGuardedCallback (react-dom.development.js:440)
    at beginWork$$1 (react-dom.development.js:25780)
    at performUnitOfWork (react-dom.development.js:24698)

To Reproduce Steps to reproduce the behavior:

  1. Add a custom doc page globally or on component or story level
  2. Use the useGlobals hook in the custom docs page
  3. Go to storybook and the docs tab
  4. Check the browser dev tools console for the error

Expected behavior Expected to render the doc page without errors and have access to the globals.

Code snippets Here’s the code from my DocsPage.tsx file:

import * as React from "react";

import {
  ArgsTable,
  Description,
  PRIMARY_STORY,
  Primary,
  Stories,
  Subtitle,
  Title,
} from "@storybook/addon-docs/blocks";

import { useGlobals } from "@storybook/api";

export const DocsPage = () => {
  const [globals] = useGlobals();

  return (
      <Title />
      <Subtitle />
      <Description />
      <Primary />
      <ArgsTable story={PRIMARY_STORY} />
      <Stories />
  );
};

And here’s how I set the doc page in preview.ts file with addParameters function:

addParameters({
  viewport,
  options: { storySort, theme },
  controls: { hideNoControlsWarning: true },
  docs: {
    page: DocsPage
  },
});

System Environment Info:

System: OS: macOS Mojave 10.14.6 CPU: (12) x64 Intel® Core™ i9-8950HK CPU @ 2.90GHz Binaries: Node: 12.18.2 - ~/.nvm/versions/node/v12.18.2/bin/node Yarn: 1.22.4 - ~/.yarn/bin/yarn npm: 6.14.5 - ~/.nvm/versions/node/v12.18.2/bin/npm Browsers: Chrome: 86.0.4240.111 Firefox: 72.0.2 Safari: 14.0

Additional Info I’m using @storybook/core@6.0.27 and @storybook/addon-essentials@6.0.27.

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 5
  • Comments: 18 (9 by maintainers)

Most upvoted comments

@williamliangwl Here is a workaround I found today!

import { addons } from '@storybook/addons';
import { DocsContainer } from '@storybook/addon-docs';
import { UPDATE_GLOBALS } from '@storybook/core-events';

export const globalTypes = {
	theme: {
		name: 'Theme',
		description: 'Choose a theme to apply',
		toolbar: {
			icon: 'paintbrush',
			items: [
				{ value: 'light', left: '⚪️', title: 'Default theme' },
				{ value: 'dark', left: '⚫️', title: 'Dark theme' },
			],
		},
	},
};

export const parameters = {
	docs: {
		container: props => {
			const channel = addons.getChannel();
			const hasDarkMode = props.context.globals.theme === 'dark';
			return (
				<>
					<Switch
						label={'Dark mode'}
						onChange={() => {
							channel.emit(UPDATE_GLOBALS, {
								globals: { theme: hasDarkMode ? 'light' : 'dark' },
							});
						}}
						checked={hasDarkMode}
					/>
					<DocsContainer {...props} />
				</>
			);
		},
	},
};

Hope it can help!

+1 My use case: need to controll theme from stories level to create visual testing stories for all themes.

Wondering if this is going to be added ?

I want to create an addon on Toolbar that affect the story rendering of both Canvas and Docs tab, so I plan to have the “communication” done through Globals

Or is there a workaround for that use case ?

Is there any updates on this?

For our use case, we need useGlobals because we have images which are illegible with dark mode enabled.

We’re trying to use the theme to switch between the images in a purpose built React component

AFAIK, storybook doesn’t support GitHub’s solution to use #gh-light-mode-only at the end of images?

Right. And there’s no real reason why it needs to take a PreparedStory as an argument (which you might not have). So there’s a bit of work to clean this up to be more useful. Maybe a good first issue? Should we use this ticket or make a new one?

I’d also like to see this. I have a theme switcher and want to show a color palette based on the selected theme.

Thank you for your reply! The reason I wanted to access globals in doc page was to set background color styles based on the selected theme. Since it’s not possible in doc page, I ended up setting some global CSS styles targeting the docs CSS classes in a story decorator. Not the prettiest solution but it works.

So I managed to work around it 👍 I’m not sure how big of a problem this is. Go ahead and close the issue if you feel it’s not that big of a deal.