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 };