import { StyledEngineProvider, ThemeProvider } from "@mui/material"; import { createTheme as muiCreateTheme } from "@mui/material/styles"; import { type ReactNode, useEffect, useState } from "react"; function getColorScheme(): "light" | "dark" { let scheme = document.body?.dataset.colorScheme ?? document.documentElement?.dataset.colorScheme ?? "light"; if (scheme === "auto") { return globalThis.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light"; } return scheme === "dark" ? "dark" : "light"; } /** * Tracks the color scheme Designsystemet is rendering with. The article template * sets `data-color-scheme` on `
`, so watch that attribute as well as the * OS preference (used when the scheme is `auto`). */ function useColorScheme() { let [scheme, setScheme] = useState<"light" | "dark">(() => getColorScheme()); useEffect(() => { function update() { setScheme(getColorScheme()); } update(); let observer = new MutationObserver(update); observer.observe(document.body, { attributes: true, attributeFilter: ["data-color-scheme"] }); observer.observe(document.documentElement, { attributes: true, attributeFilter: ["data-color-scheme"] }); let media = globalThis.matchMedia?.("(prefers-color-scheme: dark)"); media?.addEventListener("change", update); return () => { observer.disconnect(); media?.removeEventListener("change", update); }; }, []); return scheme; } function buildMuiTheme(mode: "light" | "dark") { const s = getComputedStyle(document.body); const get = (v: string) => s.getPropertyValue(v).trim(); const isDark = mode === "dark"; return muiCreateTheme({ palette: { mode, primary: { main: get("--ds-color-brand-base-default") || "#116069", dark: get("--ds-color-brand-base-hover") || "#0d4b52", contrastText: get("--ds-color-brand-base-contrast-default") || "#ffffff", }, secondary: { main: get("--ds-color-brand-light-base-default") || "#1a95a2", }, background: { default: get("--ds-color-neutral-background-default") || (isDark ? "#17181a" : "#ffffff"), paper: get("--ds-color-neutral-background-default") || (isDark ? "#17181a" : "#ffffff"), }, text: { primary: get("--ds-color-neutral-text-default") || (isDark ? "#e5e6e7" : "#292c30"), secondary: get("--ds-color-neutral-text-subtle") || (isDark ? "#b3b5b7" : "#5b5f64"), }, divider: get("--ds-color-neutral-border-subtle") || (isDark ? "#4e5052" : "#bbbcbd"), }, typography: { fontFamily: [ "-apple-system", "BlinkMacSystemFont", '"Segoe UI"', "Roboto", '"Helvetica Neue"', "Arial", "sans-serif", '"Apple Color Emoji"', '"Segoe UI Emoji"', '"Segoe UI Symbol"', ].join(","), }, components: { MuiTypography: { styleOverrides: { h1: { fontSize: "2.488rem" }, h2: { fontSize: "2.074rem" }, h3: { fontSize: "1.728rem" }, h4: { fontSize: "1.44rem" }, h5: { fontSize: "1.2rem" }, h6: { fontSize: "1rem" }, }, }, MuiAppBar: { styleOverrides: { root: { "& .MuiTypography-h1": { fontSize: "1.25rem", fontWeight: "500", }, }, }, }, MuiButton: { styleOverrides: { root: { borderRadius: 2 }, }, }, MuiDialogTitle: { styleOverrides: { root: { fontSize: "1.2rem", fontWeight: 500, paddingLeft: 16, paddingRight: 16, }, }, }, MuiFormLabel: { styleOverrides: { root: { color: get("--ds-color-neutral-text-subtle") || "rgba(0, 0, 0, 0.72)" }, }, }, MuiTextField: { defaultProps: { variant: "filled" } }, MuiSelect: { defaultProps: { variant: "filled" } }, MuiFormControl: { defaultProps: { variant: "filled" } }, }, }); } export type MuiThemeProviderProps = { children: ReactNode; }; /** * Bridges Designsystemet's colour tokens into a MUI theme, so MUI components * (most notably the data grid) follow Designsystemet instead of MUI defaults. * * This lives in a separate entry point (`@olenbetong/synergi-react/mui`) so apps * that have migrated to Designsystemet don't pull ~160 kB of MUI and Emotion * into their bundle just by using `AppShell`. Wrap `AppShell` with it in apps * that still render MUI components: * * @example * ```tsx * import { AppShell } from "@olenbetong/synergi-react"; * import { MuiThemeProvider } from "@olenbetong/synergi-react/mui"; * *