388 lines
8.8 KiB
TypeScript
388 lines
8.8 KiB
TypeScript
import { createTheme } from "@mui/material";
|
|
import { lightPalette, darkPalette, typographyLevels } from "@/Utils/Theme/Palette";
|
|
|
|
import type { Theme } from "@mui/material/styles";
|
|
import type {} from "@mui/material/styles";
|
|
import { SCROLLBAR_SIZE } from "@/Utils/Theme/constants";
|
|
|
|
declare module "@mui/material/styles" {
|
|
interface TypographyVariants {
|
|
eyebrow: React.CSSProperties;
|
|
fontFamilyMonospace: string;
|
|
}
|
|
interface TypographyVariantsOptions {
|
|
eyebrow?: React.CSSProperties;
|
|
fontFamilyMonospace?: string;
|
|
}
|
|
interface TypeAction {
|
|
rowHover: string;
|
|
controlHover: string;
|
|
selectedHover: string;
|
|
}
|
|
interface Palette {
|
|
sidebar: { accent: string };
|
|
scrollbar: { track: string; thumb: string };
|
|
rowStatus: { running: string; paused: string };
|
|
chart: {
|
|
phases: {
|
|
dns: string;
|
|
tcp: string;
|
|
tls: string;
|
|
request: string;
|
|
firstByte: string;
|
|
download: string;
|
|
};
|
|
};
|
|
}
|
|
interface PaletteOptions {
|
|
sidebar?: { accent: string };
|
|
scrollbar?: { track: string; thumb: string };
|
|
rowStatus?: { running: string; paused: string };
|
|
chart?: {
|
|
phases: {
|
|
dns: string;
|
|
tcp: string;
|
|
tls: string;
|
|
request: string;
|
|
firstByte: string;
|
|
download: string;
|
|
};
|
|
};
|
|
}
|
|
}
|
|
|
|
declare module "@mui/material/Typography" {
|
|
interface TypographyPropsVariantOverrides {
|
|
eyebrow: true;
|
|
}
|
|
}
|
|
|
|
export type PaletteKey = {
|
|
[K in keyof Theme["palette"]]: Theme["palette"][K] extends { main: any } ? K : never;
|
|
}[keyof Theme["palette"]];
|
|
|
|
const fontFamilyPrimary = '"Geist Variable", system-ui, sans-serif';
|
|
const fontFamilyMonospace =
|
|
'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace';
|
|
const shadow =
|
|
"0px 4px 24px -4px rgba(16, 24, 40, 0.08), 0px 3px 3px -3px rgba(16, 24, 40, 0.03)";
|
|
|
|
export const theme = (mode: string, palette: any) =>
|
|
createTheme({
|
|
breakpoints: {
|
|
values: {
|
|
xs: 300,
|
|
sm: 600,
|
|
md: 900,
|
|
lg: 1200,
|
|
xl: 1536,
|
|
},
|
|
},
|
|
spacing: 2,
|
|
palette: {
|
|
mode: mode,
|
|
...palette,
|
|
},
|
|
typography: {
|
|
fontFamily: fontFamilyPrimary,
|
|
fontFamilyMonospace,
|
|
fontSize: typographyLevels.base,
|
|
h1: {
|
|
fontSize: typographyLevels.xxl,
|
|
fontWeight: 700,
|
|
letterSpacing: "-0.015em",
|
|
},
|
|
h2: {
|
|
fontSize: typographyLevels.l,
|
|
fontWeight: 600,
|
|
letterSpacing: "-0.01em",
|
|
},
|
|
body1: {
|
|
fontSize: typographyLevels.m,
|
|
fontWeight: 400,
|
|
},
|
|
body2: {
|
|
fontSize: typographyLevels.s,
|
|
fontWeight: 400,
|
|
},
|
|
eyebrow: {
|
|
fontSize: 13,
|
|
fontWeight: 500,
|
|
textTransform: "uppercase",
|
|
letterSpacing: "0.08em",
|
|
lineHeight: 1.4,
|
|
},
|
|
},
|
|
|
|
components: {
|
|
MuiCssBaseline: {
|
|
styleOverrides: (theme) => ({
|
|
"*": {
|
|
scrollbarWidth: "auto",
|
|
scrollbarColor: `${theme.palette.scrollbar.thumb} ${theme.palette.scrollbar.track}`,
|
|
},
|
|
"*::-webkit-scrollbar": {
|
|
width: SCROLLBAR_SIZE,
|
|
height: SCROLLBAR_SIZE,
|
|
},
|
|
"*::-webkit-scrollbar-track": {
|
|
background: theme.palette.scrollbar.track,
|
|
borderRadius: theme.shape.borderRadius,
|
|
},
|
|
"*::-webkit-scrollbar-thumb": {
|
|
background: theme.palette.scrollbar.thumb,
|
|
borderRadius: theme.shape.borderRadius,
|
|
},
|
|
"*::-webkit-scrollbar-button": { display: "none" },
|
|
}),
|
|
},
|
|
MuiTouchRipple: {
|
|
styleOverrides: {
|
|
root: {
|
|
display: "none",
|
|
},
|
|
},
|
|
},
|
|
MuiButtonBase: {
|
|
defaultProps: {
|
|
disableRipple: true,
|
|
disableTouchRipple: true,
|
|
},
|
|
},
|
|
MuiButton: {
|
|
defaultProps: {
|
|
disableRipple: true,
|
|
disableTouchRipple: true,
|
|
disableFocusRipple: true,
|
|
},
|
|
styleOverrides: {
|
|
root: ({ theme }) => ({
|
|
"&.Mui-focusVisible": {
|
|
outline: `1px solid ${
|
|
theme.palette.mode === "dark"
|
|
? theme.palette.primary.light
|
|
: theme.palette.primary.main
|
|
}`,
|
|
outlineOffset: 2,
|
|
},
|
|
}),
|
|
},
|
|
},
|
|
MuiIconButton: {
|
|
defaultProps: {
|
|
disableRipple: true,
|
|
disableTouchRipple: true,
|
|
disableFocusRipple: true,
|
|
},
|
|
},
|
|
MuiListItemButton: {
|
|
defaultProps: {
|
|
disableRipple: true,
|
|
disableTouchRipple: true,
|
|
},
|
|
},
|
|
MuiTab: {
|
|
defaultProps: {
|
|
disableRipple: true,
|
|
disableTouchRipple: true,
|
|
disableFocusRipple: true,
|
|
},
|
|
},
|
|
MuiToggleButton: {
|
|
defaultProps: {
|
|
disableRipple: true,
|
|
disableTouchRipple: true,
|
|
disableFocusRipple: true,
|
|
},
|
|
},
|
|
|
|
MuiFormLabel: {
|
|
styleOverrides: {
|
|
root: ({ theme }) => ({
|
|
fontSize: typographyLevels.base,
|
|
"&.Mui-focused": {
|
|
color: theme.palette.secondary.contrastText,
|
|
},
|
|
}),
|
|
},
|
|
},
|
|
MuiInputLabel: {
|
|
styleOverrides: {
|
|
root: ({ theme }) => ({
|
|
top: `-${theme.spacing(4)}`,
|
|
"&.MuiInputLabel-shrink": {
|
|
top: 0,
|
|
},
|
|
}),
|
|
},
|
|
},
|
|
MuiOutlinedInput: {
|
|
styleOverrides: {
|
|
input: {
|
|
paddingTop: 0,
|
|
paddingBottom: 0,
|
|
height: "100%",
|
|
},
|
|
root: ({ theme }) => ({
|
|
"& .MuiSelect-select": {
|
|
paddingTop: 0,
|
|
paddingBottom: 0,
|
|
display: "flex",
|
|
alignItems: "center",
|
|
minHeight: "unset",
|
|
},
|
|
"& .MuiOutlinedInput-notchedOutline": {
|
|
borderColor: theme.palette.divider,
|
|
transition: "border-color 0.15s ease",
|
|
},
|
|
"&:hover:not(.Mui-focused):not(.Mui-disabled) .MuiOutlinedInput-notchedOutline":
|
|
{
|
|
borderColor: theme.palette.text.disabled,
|
|
},
|
|
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
|
|
borderColor:
|
|
theme.palette.mode === "dark"
|
|
? theme.palette.primary.light
|
|
: theme.palette.primary.main,
|
|
borderWidth: 2,
|
|
},
|
|
"&.Mui-error .MuiOutlinedInput-notchedOutline": {
|
|
borderColor: theme.palette.error.main,
|
|
},
|
|
}),
|
|
},
|
|
},
|
|
|
|
MuiPaper: {
|
|
styleOverrides: {
|
|
root: ({ theme }) => {
|
|
return {
|
|
marginTop: 4,
|
|
padding: 0,
|
|
border: 1,
|
|
borderStyle: "solid",
|
|
borderColor: theme.palette.divider,
|
|
borderRadius: 4,
|
|
boxShadow: shadow,
|
|
backgroundColor: theme.palette.background.paper,
|
|
backgroundImage: "none",
|
|
};
|
|
},
|
|
},
|
|
},
|
|
|
|
MuiSwitch: {
|
|
defaultProps: { disableRipple: true },
|
|
styleOverrides: {
|
|
root: {
|
|
width: 36,
|
|
height: 20,
|
|
padding: "0 6px 0 0",
|
|
boxSizing: "content-box",
|
|
overflow: "visible",
|
|
},
|
|
switchBase: ({ theme }) => ({
|
|
padding: 2,
|
|
"&.Mui-checked": {
|
|
transform: "translateX(16px)",
|
|
color: "#fff",
|
|
"& + .MuiSwitch-track": {
|
|
backgroundColor: theme.palette.primary.main,
|
|
opacity: 1,
|
|
border: 0,
|
|
},
|
|
},
|
|
}),
|
|
thumb: {
|
|
width: 16,
|
|
height: 16,
|
|
boxShadow: "0 1px 2px rgba(16, 24, 40, 0.1)",
|
|
},
|
|
track: ({ theme }) => ({
|
|
borderRadius: 999,
|
|
backgroundColor:
|
|
theme.palette.mode === "dark"
|
|
? "rgba(255,255,255,0.16)"
|
|
: theme.palette.action.disabledBackground,
|
|
opacity: 1,
|
|
}),
|
|
},
|
|
},
|
|
|
|
MuiRadio: {
|
|
defaultProps: { disableRipple: true },
|
|
styleOverrides: {
|
|
root: ({ theme }) => ({
|
|
padding: theme.spacing(2),
|
|
color: theme.palette.divider,
|
|
"& .MuiSvgIcon-root": {
|
|
fontSize: 20,
|
|
transition: "none",
|
|
},
|
|
"&.Mui-checked": {
|
|
color: theme.palette.primary.main,
|
|
},
|
|
"&.Mui-checked .MuiSvgIcon-root:last-of-type": {
|
|
transform: "scale(0.6)",
|
|
},
|
|
}),
|
|
},
|
|
},
|
|
|
|
MuiSlider: {
|
|
styleOverrides: {
|
|
root: ({ theme }) => ({
|
|
height: 4,
|
|
padding: "13px 0",
|
|
color: theme.palette.primary.main,
|
|
}),
|
|
rail: ({ theme }) => ({
|
|
height: 4,
|
|
borderRadius: 999,
|
|
opacity: 1,
|
|
backgroundColor:
|
|
theme.palette.mode === "dark"
|
|
? "rgba(255,255,255,0.16)"
|
|
: theme.palette.action.disabledBackground,
|
|
}),
|
|
track: {
|
|
height: 4,
|
|
borderRadius: 999,
|
|
border: "none",
|
|
},
|
|
thumb: ({ theme }) => ({
|
|
width: 18,
|
|
height: 18,
|
|
backgroundColor: theme.palette.background.paper,
|
|
border: `2px solid ${theme.palette.primary.main}`,
|
|
boxShadow: "0 1px 2px rgba(16, 24, 40, 0.1)",
|
|
"&:hover, &.Mui-focusVisible": {
|
|
boxShadow: `0 0 0 6px ${theme.palette.primary.main}1f`,
|
|
},
|
|
"&.Mui-active": {
|
|
boxShadow: `0 0 0 8px ${theme.palette.primary.main}29`,
|
|
},
|
|
"&::before": { display: "none" },
|
|
}),
|
|
mark: ({ theme }) => ({
|
|
width: 2,
|
|
height: 2,
|
|
borderRadius: 999,
|
|
backgroundColor: theme.palette.text.disabled,
|
|
opacity: 0.5,
|
|
}),
|
|
markActive: ({ theme }) => ({
|
|
backgroundColor: theme.palette.primary.main,
|
|
opacity: 0.5,
|
|
}),
|
|
},
|
|
},
|
|
},
|
|
shape: {
|
|
borderRadius: 2,
|
|
},
|
|
});
|
|
|
|
export const lightTheme = createTheme(theme("light", lightPalette));
|
|
export const darkTheme = createTheme(theme("dark", darkPalette));
|