context.globals 在 DocsContainer 中不起作用 |故事书

问题描述 投票:0回答:1

我想将我的 MDX 文档包装在 themeProvider 中,当全局变量(globaltypes)的上下文发生变化时,它会更新。

我遵循了这个:

故事书 Github 和这个讨论

当我这样做时它确实起作用了:

docs: {
      container: ({ children, context }) => {
        const selectedTheme = themes["brandA"]["dark"];

        return (
          <DocsContainer context={context}>
            <ThemeProvider theme={selectedTheme}>
              <GlobalStyles />
              {children}
            </ThemeProvider>
          </DocsContainer>
        );
      },

但是当我这样做时它不起作用:

const selectedTheme = themes[context.globals.brand][context.globals.mode];

即使它在装饰器中也是这样工作的。

这是我的整个文件:

import React, { useContext } from "react";
import ReactDOM from "react-dom";
window.React = React;

import { ThemeProvider } from "styled-components";
import GlobalStyles from "../src/styles/GlobalStyles.jsx";
import themes from "../src/styles/Themes.js";

import mytheme from "./myTheme.js";

import { DocsContainer } from "@storybook/blocks";

const customViewports = {
  laptop: {
    name: "Laptop",
    styles: {
      width: "1280px",
      height: "100%",
    },
  },
  desktop: {
    name: "Desktop",
    styles: {
      width: "1440px",
      height: "100%",
    },
  },
  widescreen: {
    name: "Widescreen",
    styles: {
      width: "1920px",
      height: "100%",
    },
  },
};

export const themeProviderDecorator = (Story, context) => {
  const currentTheme = themes[context.globals.brand][context.globals.mode];
  return (
    <ThemeProvider theme={currentTheme}>
      <GlobalStyles />
      <div
        style={{
          padding: "24px",
          backgroundColor: "var(--background-color)",
        }}
      >
        <Story />
      </div>
    </ThemeProvider>
  );
};

/** @type { import('@storybook/react').Preview } */
const preview = {
  //controlos da brand e mode
  globalTypes: {
    brand: {
      description: "Select a brand",
      defaultValue: "brandDefault",
      toolbar: {
        // icon: "paintbrush",
        title: "🟣 Default Brand",
        dynamicTitle: true,
        items: [
          {
            value: "brandDefault",
            title: "🟣 Default Brand" /* left: "🟣" */,
          },
          { value: "brandA", title: "🟢 Brand A" /* left: "🟢" */ },
          { value: "brandB", title: "🔵 Brand B" /* left: "🔵" */ },
        ],
      },
    },
    mode: {
      description: "Select a mode",
      defaultValue: "light",
      toolbar: {
        title: "🟣 Light",
        dynamicTitle: true,
        items: [
          { value: "light", title: " Light", icon: "sun" },
          { value: "dark", title: " Dark", icon: "moon" },
          //pode ter mais modos além de apenas "light" e "dark", como por exemplo, "high contrast".
        ],
      },
    },
  },

  decorators: [themeProviderDecorator],

  parameters: {
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
    options: {
      title: "React",
    },
    layout: "fullscreen", //para as stories não terem margins (Assim o decorator com o backgroung color, não fica estranho)
    viewport: {
      viewports: customViewports,
    },
    docs: {
      container: ({ children, context }) => {
        // const selectedTheme = themes[context.globals.brand][context.globals.mode];
        const selectedTheme = themes["brandA"]["dark"];

        return (
          <DocsContainer context={context}>
            <ThemeProvider theme={selectedTheme}>
              <GlobalStyles />
              {children}
            </ThemeProvider>
          </DocsContainer>
        );
      },
      canvas: {
        sourceState: "shown",
      },
      previewSource: "shown",
      theme: myTheme,
    },
  },
};

export default preview;

为了更好地解释......我想要这样的东西:

注意:对颜色感到抱歉,但这仅用于测试。

始终显示的错误是:

无法读取未定义的属性(读取“品牌”)

也尝试过这个:

const container = ({ children, context, globals }) => {
    const { brand, mode } = globals;
    const selectedTheme = themes[brand][mode]; // Access brand and mode

    // ... (rest of the container function)
};

,这个:

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

const container = ({ children, context }) => {
    const { brand, mode } = useGlobals();
    const selectedTheme = themes[brand][mode]; // Access brand and mode

    return (
        <DocsContainer context={context}>
            <ThemeProvider theme={selectedTheme}>
                <GlobalStyles />
                {children}
            </ThemeProvider>
        </DocsContainer>
    );
};

,这个:

const container = (context, { children }) => {
    const selectedTheme =
          themes[context.globals.brand][context.globals.mode];

        return (
          <DocsContainer context={context}>
            <ThemeProvider theme={selectedTheme}>
              <GlobalStyles />
              {children}
            </ThemeProvider>
          </DocsContainer>);
      },
};

还有这个:

const container = (context, children) => {
    const selectedTheme =
          themes[context.globals.brand][context.globals.mode];

        return (
          <DocsContainer context={context}>
            <ThemeProvider theme={selectedTheme}>
              <GlobalStyles />
              {children}
            </ThemeProvider>
          </DocsContainer>);
      },
};

但似乎没有任何作用。

这很重要,因为它可以使多品牌 Storybook 的文档变得更好。

我还了解到装饰器和容器中上下文的读取方式不同。

在装饰器中我写道:

  console.log(context);
  console.log("decorator context: " + context);
  console.log("decorator context.globals: " + context.globals);
  console.log("decorator context.globals.brand: " + context.globals.brand);
  console.log("decorator context.globals.mode: " + context.globals.mode);
  console.log(currentTheme);

这显示在控制台中:

但是当我像这样在容器中写它时:

  console.log(context);
  console.log("container context: " + context); //this works
  console.log("container context.globals: " + context.globals); //this works
  console.log("container context.globals.brand: " + context.globals.brand); //this doesn't
  console.log("container context.globals.mode: " + context.globals.mode); //this doesn't

在控制台中显示如下:

如果我只尝试

console.log(context.globals);

它只在控制台中显示“未定义”。

所以,我不明白为什么我无法获取具有全局变量的上下文(就像在装饰器中一样),因为它正在获取另一种上下文,即 React 上下文,就像 Storybook Github 中所说的那样:

如果您想为 MDX 页面添加一些包装器,或者添加某种其他类型的 React 上下文,会发生什么?

如果没有

context={context}
 中的 
<DocsContainer context={context}>

,这将不起作用

那么...我如何使用两者并从全局调用我想要的一个来选择品牌和模式?

reactjs styled-components mdx storybook themeprovider
1个回答
0
投票

在探索容器中

console.log(context);
中的结果对象后(我花了一段时间......)。我找到方法了:

export const themeProviderMDX = ({ children, context }) => {
  const currentTheme =
    themes[context.store.globals.globals.brand][
      context.store.globals.globals.mode
    ];

  console.log(context);

  return (
    <DocsContainer context={context}>
      <ThemeProvider theme={currentTheme}>
        <GlobalStyles />
        {children}
      </ThemeProvider>
    </DocsContainer>
  );
};

[...]

parameters: {
    docs: {
      container: themeProviderMDX,
    },
  },

您可以在控制台中看到这一点:

希望这对某人有帮助:)

© www.soinside.com 2019 - 2024. All rights reserved.