ReactMaterial3/src/hooks/useTheme.tsx

127 lines
5.9 KiB
TypeScript

import { hexFromArgb, Theme } from "@material/material-color-utilities";
import React from "react";
import { createContext, useContext } from "react";
import { useScheme } from "./useScheme";
const ThemeContext = createContext<Theme | undefined>(undefined);
export function ThemeProvider({ children, theme, scheme }: { children: React.ReactNode, theme: Theme, scheme: 'dark' | 'light' }) {
return (
<ThemeContext.Provider value={theme}>
<style>
{`
body {
--md-ref-typeface-brand: 'Roboto Flex';
--md-ref-typeface-plain: 'Roboto Flex';
--md-sys-color-primary: ${hexFromArgb(theme.schemes[scheme].primary)};
--md-sys-color-primary-container: ${hexFromArgb(theme.schemes[scheme].primaryContainer)};
--md-sys-color-secondary: ${hexFromArgb(theme.schemes[scheme].secondary)};
--md-sys-color-secondary-container: ${hexFromArgb(theme.schemes[scheme].secondaryContainer)};
--md-sys-color-tertiary: ${hexFromArgb(theme.schemes[scheme].tertiary)};
--md-sys-color-tertiary-container: ${hexFromArgb(theme.schemes[scheme].tertiaryContainer)};
--md-sys-color-error: ${hexFromArgb(theme.schemes[scheme].error)};
--md-sys-color-error-container: ${hexFromArgb(theme.schemes[scheme].errorContainer)};
--md-sys-color-background: ${hexFromArgb(theme.schemes[scheme].background)};
--md-sys-color-surface: ${hexFromArgb(theme.schemes[scheme].surface)};
--md-sys-color-surface-bright: ${hexFromArgb(theme.schemes[scheme].surface)};
--md-sys-color-surface-dim: ${hexFromArgb(theme.schemes[scheme].surface)};
--md-sys-color-surface-container: ${hexFromArgb(theme.schemes[scheme].surface)};
--md-sys-color-surface-container-lowest: ${hexFromArgb(theme.schemes[scheme].surface)};
--md-sys-color-surface-container-low: ${hexFromArgb(theme.schemes[scheme].surface)};
--md-sys-color-surface-container-high: ${hexFromArgb(theme.schemes[scheme].surface)};
--md-sys-color-surface-container-highest: ${hexFromArgb(theme.schemes[scheme].surface)};
--md-sys-color-outline: ${hexFromArgb(theme.schemes[scheme].outline)};
--md-sys-color-outline-variant: ${hexFromArgb(theme.schemes[scheme].outlineVariant)};
--md-sys-color-scrim: ${hexFromArgb(theme.schemes[scheme].scrim)};
--md-sys-color-shadow: ${hexFromArgb(theme.schemes[scheme].shadow)};
--md-sys-color-on-surface: ${hexFromArgb(theme.schemes[scheme].onSurface)};
--md-sys-color-on-surface-variant: ${hexFromArgb(theme.schemes[scheme].onSurfaceVariant)};
--md-sys-color-on-surface-bright: ${hexFromArgb(theme.schemes[scheme].onSurface)};
--md-sys-color-on-surface-dim: ${hexFromArgb(theme.schemes[scheme].onSurface)};
--md-sys-color-background: ${hexFromArgb(theme.schemes[scheme].background)};
--md-sys-color-background-variant: ${hexFromArgb(theme.schemes[scheme].surface)};
--md-sys-color-on-primary: ${hexFromArgb(theme.schemes[scheme].onPrimary)};
--md-sys-color-on-primary-container: ${hexFromArgb(theme.schemes[scheme].onPrimaryContainer)};
--md-sys-color-on-secondary: ${hexFromArgb(theme.schemes[scheme].onSecondary)};
--md-sys-color-on-secondary-container: ${hexFromArgb(theme.schemes[scheme].onSecondaryContainer)};
--md-sys-color-on-tertiary: ${hexFromArgb(theme.schemes[scheme].onTertiary)};
--md-sys-color-on-tertiary-container: ${hexFromArgb(theme.schemes[scheme].onTertiaryContainer)};
--md-sys-color-on-error: ${hexFromArgb(theme.schemes[scheme].onError)};
--md-sys-color-on-error-container: ${hexFromArgb(theme.schemes[scheme].onErrorContainer)};
--md-sys-typescale-headline-small-font: 'Roboto Flex';
--md-sys-typescale-headline-medium-font: 'Roboto Flex';
--md-sys-typescale-headline-large-font: 'Roboto Flex';
--md-sys-typescale-headline-small-size: 24px;
--md-sys-typescale-headline-medium-size: 32px;
--md-sys-typescale-headline-large-size: 40px;
--md-sys-typescale-headline-small-weight: 400;
--md-sys-typescale-headline-medium-weight: 400;
--md-sys-typescale-headline-large-weight: 400;
--md-sys-typescale-headline-small-line-height: 32px;
--md-sys-typescale-headline-medium-line-height: 40px;
--md-sys-typescale-headline-large-line-height: 48px;
--md-sys-typescale-body-small-font: 'Roboto Flex';
--md-sys-typescale-body-medium-font: 'Roboto Flex';
--md-sys-typescale-body-large-font: 'Roboto Flex';
--md-sys-typescale-body-small-size: 12px;
--md-sys-typescale-body-medium-size: 14px;
--md-sys-typescale-body-large-size: 16px;
--md-sys-typescale-body-small-weight: 400;
--md-sys-typescale-body-medium-weight: 400;
--md-sys-typescale-body-large-weight: 400;
--md-sys-typescale-body-small-line-height: 16px;
--md-sys-typescale-body-medium-line-height: 20px;
--md-sys-typescale-body-large-line-height: 24px;
--md-sys-typescale-label-small-font: 'Roboto Flex';
--md-sys-typescale-label-medium-font: 'Roboto Flex';
--md-sys-typescale-label-large-font: 'Roboto Flex';
--md-sys-typescale-label-small-size: 12px;
--md-sys-typescale-label-medium-size: 14px;
--md-sys-typescale-label-large-size: 16px;
--md-sys-typescale-label-small-weight: 400;
--md-sys-typescale-label-medium-weight: 400;
--md-sys-typescale-label-large-weight: 400;
--md-sys-typescale-label-small-line-height: 16px;
--md-sys-typescale-label-medium-line-height: 20px;
--md-sys-typescale-label-large-line-height: 24px;
background-color: var(--md-sys-color-background);
}
`}
</style>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
const context = useContext(ThemeContext);
if (context === undefined) {
throw new Error("useTheme must be used within a ThemeProvider");
}
return context;
}
export function usePalette() {
const theme = useTheme();
const scheme = useScheme();
return theme.schemes[scheme];
}