import { alpha, createTheme, type Components, type CSSObject, responsiveFontSizes, type ThemeOptions, ThemeProvider as MaterialUiThemeProvider, type TypographyStyle, type TypographyVariantsOptions, } from '@mui/material/styles'; import { observer } from 'mobx-react-lite'; import React, { type ReactNode } from 'react'; import { useRootStore } from '../RootStore'; interface OuterPalette { background: string; border: string; } interface HighlightPalette { number: string; parameter: string; comment: string; activeLine: string; selection: string; lineNumber: string; foldPlaceholder: string; activeLintRange: string; occurences: { read: string; write: string; }; search: { match: string; selected: string; contrastText: string; }; } declare module '@mui/material/styles' { interface TypographyVariants { editor: TypographyStyle; } // eslint-disable-next-line @typescript-eslint/no-shadow -- Augment imported interface. interface TypographyVariantsOptions { editor: TypographyStyle; } interface Palette { outer: OuterPalette; highlight: HighlightPalette; } interface PaletteOptions { outer: OuterPalette; highlight: HighlightPalette; } } function getMUIThemeOptions(darkMode: boolean): ThemeOptions { const typography: TypographyVariantsOptions = { editor: { fontFamily: '"JetBrains MonoVariable", "JetBrains Mono", monospace', fontFeatureSettings: '"liga", "calt"', fontSize: '1rem', fontWeight: 400, lineHeight: 1.5, letterSpacing: 0, textRendering: 'optimizeLegibility', }, }; const components: Components = { MuiButton: { styleOverrides: { root: { borderRadius: '50em' }, text: { padding: '6px 16px' }, textSizeSmall: { padding: '4px 10px' }, textSizeLarge: { padding: '8px 22px' }, }, }, MuiToggleButtonGroup: { styleOverrides: { groupedHorizontal: { borderRadius: '50em', ':first-of-type': { paddingLeft: 15 }, ':last-of-type': { paddingRight: 15 }, '&.MuiToggleButton-sizeSmall': { ':first-of-type': { paddingLeft: 9 }, ':last-of-type': { paddingRight: 9 }, }, '&.MuiToggleButton-sizeLarge': { ':first-of-type': { paddingLeft: 21 }, ':last-of-type': { paddingRight: 21 }, }, }, }, }, MuiTooltip: { styleOverrides: { tooltip: { background: alpha('#212121', 0.93), color: '#fff', }, arrow: { color: alpha('#212121', 0.93), }, }, }, }; return darkMode ? { typography, components: { ...components, MuiTooltip: { ...(components.MuiTooltip || {}), styleOverrides: { ...(components.MuiTooltip?.styleOverrides || {}), tooltip: { ...((components.MuiTooltip?.styleOverrides?.tooltip as | CSSObject | undefined) || {}), color: '#ebebff', }, }, }, }, palette: { mode: 'dark', primary: { main: '#56b6c2' }, error: { main: '#e06c75' }, warning: { main: '#e5c07b' }, success: { main: '#57a470' }, info: { main: '#52b8ff' }, background: { default: '#282c34', paper: '#21252b', }, text: { primary: '#ebebff', secondary: '#abb2bf', disabled: '#4b5263', }, divider: alpha('#abb2bf', 0.16), outer: { background: '#21252b', border: '#181a1f', }, highlight: { number: '#6188a6', parameter: '#c8ae9d', comment: '#6b717d', activeLine: '#21252b', selection: '#3e4453', lineNumber: '#4b5263', foldPlaceholder: alpha('#ebebff', 0.12), activeLintRange: alpha('#fbc346', 0.28), occurences: { read: alpha('#ebebff', 0.24), write: alpha('#ebebff', 0.24), }, search: { match: '#33eaff', selected: '#dd33fa', contrastText: '#21252b', }, }, }, } : { typography, components: { ...components, MuiToolbar: { styleOverrides: { root: { color: 'rgba(0, 0, 0, 0.54)', }, }, }, }, palette: { mode: 'light', primary: { main: '#0398a8' }, outer: { background: '#f5f5f5', border: '#cacaca', }, highlight: { number: '#3d79a2', parameter: '#6a3e3e', comment: 'rgba(0, 0, 0, 0.38)', activeLine: '#f5f5f5', selection: '#c8e4fb', lineNumber: 'rgba(0, 0, 0, 0.38)', foldPlaceholder: 'rgba(0, 0, 0, 0.12)', activeLintRange: alpha('#ed6c02', 0.24), occurences: { read: 'rgba(0, 0, 0, 0.12)', write: 'rgba(0, 0, 0, 0.12)', }, search: { match: '#00bcd4', selected: '#d500f9', contrastText: '#ffffff', }, }, }, }; } function ThemeProvider({ children }: { children?: ReactNode }) { const { themeStore: { darkMode }, } = useRootStore(); const themeOptions = getMUIThemeOptions(darkMode); const theme = responsiveFontSizes(createTheme(themeOptions)); return ( {children} ); } ThemeProvider.defaultProps = { children: undefined, }; export default observer(ThemeProvider);