github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/ui/dashboard/src/hooks/useStorybookTheme.tsx (about)

     1  import React, { createContext, useContext, useState } from "react";
     2  import addons, { mockChannel } from "@storybook/addons";
     3  import { useDarkMode } from "storybook-dark-mode";
     4  
     5  if (!addons.hasChannel()) {
     6    addons.setChannel(mockChannel());
     7  }
     8  
     9  export type Theme = {
    10    name: string;
    11    label: string;
    12  };
    13  
    14  type IThemes = {
    15    [key: string]: Theme;
    16  };
    17  
    18  const ThemeNames = {
    19    STEAMPIPE_DEFAULT: "steampipe-default",
    20    STEAMPIPE_DARK: "steampipe-dark",
    21  };
    22  
    23  const Themes: IThemes = {
    24    [ThemeNames.STEAMPIPE_DEFAULT]: {
    25      label: "Light",
    26      name: ThemeNames.STEAMPIPE_DEFAULT,
    27    },
    28    [ThemeNames.STEAMPIPE_DARK]: {
    29      label: "Dark",
    30      name: ThemeNames.STEAMPIPE_DARK,
    31    },
    32  };
    33  
    34  type IThemeContext = {
    35    theme: Theme;
    36    setWithFooterPadding(newValue: boolean): void;
    37    setWrapperRef(element: any): void;
    38    withFooterPadding: boolean;
    39    wrapperRef: React.Ref<null>;
    40  };
    41  
    42  const ThemeContext = createContext<IThemeContext | undefined>(undefined);
    43  
    44  const ThemeProvider = ({ children }) => {
    45    const [withFooterPadding, setWithFooterPadding] = useState(true);
    46    const [wrapperRef, setWrapperRef] = useState(null);
    47    const doSetWrapperRef = (element) => setWrapperRef(() => element);
    48  
    49    let theme;
    50  
    51    if (useDarkMode()) {
    52      theme = Themes[ThemeNames.STEAMPIPE_DARK];
    53    } else {
    54      theme = Themes[ThemeNames.STEAMPIPE_DEFAULT];
    55    }
    56  
    57    return (
    58      <ThemeContext.Provider
    59        value={{
    60          theme,
    61          setWithFooterPadding,
    62          setWrapperRef: doSetWrapperRef,
    63          withFooterPadding,
    64          wrapperRef,
    65        }}
    66      >
    67        {children}
    68      </ThemeContext.Provider>
    69    );
    70  };
    71  
    72  const ThemeWrapper = ({ children }) => {
    73    const { setWrapperRef, theme } = useStorybookTheme();
    74    return (
    75      <div
    76        ref={setWrapperRef}
    77        className={`theme-${theme.name} bg-dashboard print:bg-white print:theme-steampipe-default text-foreground print:text-black`}
    78      >
    79        {children}
    80      </div>
    81    );
    82  };
    83  
    84  const useStorybookTheme = () => {
    85    const context = useContext(ThemeContext);
    86    if (context === undefined) {
    87      throw new Error("useTheme must be used within a ThemeContext");
    88    }
    89    return context;
    90  };
    91  
    92  export { Themes, ThemeNames, ThemeProvider, ThemeWrapper, useStorybookTheme };