storybook-dark-mode 的分支,修復在新視窗 iframe 中查看 story 時應用適當類別的問題。

在 Github 上檢視

storybook-dark-mode

一個 Storybook 附加元件,讓使用者可以在深色和淺色模式之間切換。

Example

安裝

安裝下列 npm 模組

npm i --save-dev storybook-dark-mode

或使用 yarn

yarn add -D storybook-dark-mode

然後,將以下內容新增至 .storybook/main.js

module.exports = {
  addons: ['storybook-dark-mode']
};

設定

將以下內容新增至 .storybook/preview.js 檔案來設定深色和淺色模式

import { themes } from '@storybook/theming';

export parameters = {
  darkMode: {
    // Override the default dark theme
    dark: { ...themes.dark, appBg: 'black' },
    // Override the default light theme
    light: { ...themes.normal, appBg: 'red' }
  }
};

預設主題

初始色彩配置的優先順序

  1. 如果使用者先前設定了色彩主題,則會使用該主題
  2. 您在 Storybook 中為 current 參數設定的值
  3. 作業系統的色彩配置偏好設定

一旦設定了初始色彩配置,後續的重新載入將會使用此值。若要清除快取的色彩配置,您必須在 Chrome 控制台中執行 localStorage.clear()

export parameters = {
  darkMode: {
    // Set the initial theme
    current: 'light'
  }
};

深色/淺色類別

此外掛程式會將深色和淺色類別名稱套用至管理器。這讓您可以輕鬆地為 Storybook UI 撰寫支援深色模式的主題覆寫。

您可以使用 darkClasslightClass 參數覆寫在淺色和深色模式之間切換時套用的類別名稱。

export parameters = {
  darkMode: {
    darkClass: 'lights-out',
    lightClass: 'lights-on'
  }
};

預覽類別目標

此外掛程式會將深色/淺色類別套用至預覽 iframe 的 <body> 元素。這可以使用 classTarget 參數進行設定。此值將傳遞至 iframe 內的 querySelector()

如果 <body> 是根據父系的類別進行樣式設定,則這很有用,在這種情況下,可以將其設定為 html

export parameters = {
  darkMode: {
    classTarget: 'html'
  }
}

Story 整合

預覽類別名稱

如果您開啟 stylePreview 選項,則此外掛程式會將 darkClasslightClass 類別套用至預覽 iframe。

export parameters = {
  darkMode: {
    stylePreview: true
  }
};

React

如果您的元件使用自訂主題供應器,您可以使用提供的 Hook 進行整合。

import { useDarkMode } from 'storybook-dark-mode';
import { addDecorator } from '@storybook/react';

// your theme provider
import ThemeContext from './theme';

// create a component that uses the dark mode hook
function ThemeWrapper(props) {
  // render your custom theme provider
  return (
    <ThemeContext.Provider value={useDarkMode() ? darkTheme : defaultTheme}>
      {props.children}
    </ThemeContext.Provider>
  );
}

export const decorators = [renderStory => <ThemeWrapper>{renderStory()}</ThemeWrapper>)];

主題旋鈕

如果您想要讓 UI 的深色模式與元件的深色模式分開,請實作此全域裝飾器

import { themes } from '@storybook/theming';

// Add a global decorator that will render a dark background when the
// "Color Scheme" knob is set to dark
const knobDecorator = (storyFn) => {
  // A knob for color scheme added to every story
  const colorScheme = select('Color Scheme', ['light', 'dark'], 'light');

  // Hook your theme provider with some knobs
  return React.createElement(ThemeProvider, {
    // A knob for theme added to every story
    theme: select('Theme', Object.keys(themes), 'default'),
    colorScheme,
    children: [
      React.createElement('style', {
        dangerouslySetInnerHTML: {
          __html: `html { ${
            colorScheme === 'dark' ? 'background-color: rgb(35,35,35);' : ''
          } }`
        }
      }),
      storyFn()
    ]
  });
}

export const decorators = [knobDecorator];

事件

您也可以透過附加元件通道監聽 DARK_MODE 事件。

import addons from '@storybook/addons';
import { addDecorator } from '@storybook/react';

// your theme provider
import ThemeContext from './theme';

// get channel to listen to event emitter
const channel = addons.getChannel();

// create a component that listens for the DARK_MODE event
function ThemeWrapper(props) {
  // this example uses hook but you can also use class component as well
  const [isDark, setDark] = useState(false);

  useEffect(() => {
    // listen to DARK_MODE event
    channel.on('DARK_MODE', setDark);
    return () => channel.off('DARK_MODE', setDark);
  }, [channel, setDark]);

  // render your custom theme provider
  return (
    <ThemeContext.Provider value={isDark ? darkTheme : defaultTheme}>
      {props.children}
    </ThemeContext.Provider>
  );
}

export const decorators = [renderStory => <ThemeWrapper>{renderStory()}</ThemeWrapper>)];

貢獻者 ✨

感謝這些出色的人士 ( 表情符號鍵)

此專案遵循 all-contributors 規格。歡迎任何形式的貢獻!

由以下人員製作
  • sergeysova
    sergeysova
  • probablyup
    probablyup
標籤