storybook-dark-mode icon indicating copy to clipboard operation
storybook-dark-mode copied to clipboard

Allow target attribute to be changed

Open bruceharrison1984 opened this issue 3 years ago • 3 comments

Currently we have classTarget to specify what element to append a class to. It would be nice to specify the attribute that is being overridden.

In my case, my main theme is set via a data-theme attribute on the html element. I am using DaisyUI for my frontend.

AFAIK, there isn't a way to customize the classTarget to point it at another attribute.

bruceharrison1984 avatar Nov 16 '21 22:11 bruceharrison1984

After a trivial amount of playing around, the following global decorator lets you override the target attribute. It would still be nice if this was a first class feature though!

// preview.js
import { useDarkMode } from 'storybook-dark-mode';
import { useEffect } from 'react';

export const decorators = [
  (Story) => {
    const isDarkMode = useDarkMode();
    useEffect(() => document.documentElement.dataset.theme = isDarkMode ? "dark" : "light", [isDarkMode]);
    return <Story />;
  }
];

bruceharrison1984 avatar Nov 16 '21 22:11 bruceharrison1984

Important note: if you're using the code snippet above in conjunction with the @storybook/testing-react addon, you'll need to mock window.matchMedia before importing useDarkMode from storybook-dark-mode. You can do this like so:

// .storybook/decorators/mock-window-matchmedia.js
Object.defineProperty(window, 'matchMedia', {
  writable: true,
  value: query => ({
    matches: false,
    media: query,
    onchange: null,
    addListener: () => {}, // deprecated
    removeListener: () => {}, // deprecated
    addEventListener: () => {},
    removeEventListener: () => {},
    dispatchEvent: () => {},
  }),
})
// .storybook/decorators/dark-mode.js:
import './mock-window-matchmedia'; // ⚠️ Important! Import this first
import { useDarkMode } from 'storybook-dark-mode';
import { useEffect } from 'react';

export default function decorateContrastMode(Story) {
  const isDarkMode = useDarkMode();
  useEffect(() => document.documentElement.dataset.theme = isDarkMode ? "dark" : "light", [isDarkMode]);
  return <Story />;
}
// .storybook/preview.js:
import decorateContrastMode from './decorators/contrast-mode'

export const decorators = [decorateContrastMode]

raybrownco avatar Nov 05 '22 03:11 raybrownco

If anyone wants to submit a PR to add this decorator to the package feel free to ping me!

hipstersmoothie avatar Dec 05 '22 20:12 hipstersmoothie