diff --git a/pages/app/use-modes.ts b/pages/app/use-modes.ts index d3b7aa4f..73ba4c62 100644 --- a/pages/app/use-modes.ts +++ b/pages/app/use-modes.ts @@ -5,10 +5,30 @@ import { useSearchParams } from "react-router-dom"; import { applyDensity, applyMode, Density, disableMotion, Mode } from "@cloudscape-design/global-styles"; +// `theme` covers mutually exclusive themes that map to a single body class. +export enum Theme { + Default = "default", + OneTheme = "one-theme", +} + +const themeClassNames: Record = { + [Theme.Default]: "", + [Theme.OneTheme]: "awsui-one-theme", +}; + +function applyThemeClass(activeTheme: Theme) { + for (const [theme, className] of Object.entries(themeClassNames)) { + if (className) { + document.body.classList.toggle(className, theme === activeTheme); + } + } +} + export interface AppUrlParams { mode: Mode; density: Density; direction: "ltr" | "rtl"; + theme: Theme; motionDisabled: boolean; } @@ -16,6 +36,7 @@ export const defaults: AppUrlParams = { mode: Mode.Light, density: Density.Comfortable, direction: "ltr", + theme: Theme.Default, motionDisabled: false, }; @@ -29,6 +50,10 @@ function castToBoolean(s: string) { export function parseQuery(urlParams: URLSearchParams) { const queryParams: Record = { ...defaults }; urlParams.forEach((value, key) => (queryParams[key] = castToBoolean(value))); + const themeValues = Object.values(Theme) as string[]; + if (!themeValues.includes(queryParams.theme)) { + queryParams.theme = Theme.Default; + } return queryParams as AppUrlParams; } @@ -46,7 +71,7 @@ export function formatQuery(params: AppUrlParams) { export default function useModes() { const [searchParams, setSearchParams] = useSearchParams(); const urlParams = parseQuery(searchParams); - const { density, direction, mode, motionDisabled } = urlParams; + const { density, direction, mode, motionDisabled, theme } = urlParams; function setParams(newParams: Partial) { setSearchParams(formatQuery({ ...urlParams, ...newParams })); @@ -68,5 +93,9 @@ export default function useModes() { document.documentElement.setAttribute("dir", direction); }, [direction]); - return { density, direction, mode, motionDisabled, setParams }; + useEffect(() => { + applyThemeClass(theme); + }, [theme]); + + return { density, direction, mode, motionDisabled, theme, setParams }; }