feat(design-system): add MUI theme adapter
This commit is contained in:
parent
fdffe204e4
commit
1107a1fc8b
20
packages/design-system/src/theme/MoexVibeThemeProvider.tsx
Normal file
20
packages/design-system/src/theme/MoexVibeThemeProvider.tsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { type ReactNode } from 'react';
|
||||||
|
import { ThemeProvider } from '@mui/material/styles';
|
||||||
|
import CssBaseline from '@mui/material/CssBaseline';
|
||||||
|
import { Experimental_CssVarsProvider as CssVarsProvider } from '@mui/material/styles';
|
||||||
|
import { createMoexVibeTheme } from './createMoexVibeTheme';
|
||||||
|
|
||||||
|
const theme = createMoexVibeTheme();
|
||||||
|
|
||||||
|
export interface MoexVibeThemeProviderProps {
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MoexVibeThemeProvider({ children }: MoexVibeThemeProviderProps) {
|
||||||
|
return (
|
||||||
|
<CssVarsProvider theme={theme}>
|
||||||
|
<CssBaseline />
|
||||||
|
{children}
|
||||||
|
</CssVarsProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
29
packages/design-system/src/theme/createMoexVibeTheme.test.ts
Normal file
29
packages/design-system/src/theme/createMoexVibeTheme.test.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { createMoexVibeTheme } from './createMoexVibeTheme';
|
||||||
|
|
||||||
|
describe('createMoexVibeTheme', () => {
|
||||||
|
it('sets cssVarPrefix to mv', () => {
|
||||||
|
const theme = createMoexVibeTheme();
|
||||||
|
expect(theme.cssVarPrefix).toBe('mv');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('maps color.action.primary to MUI primary main', () => {
|
||||||
|
const theme = createMoexVibeTheme();
|
||||||
|
expect(theme.colorSchemes.light.palette.primary.main).toBe('#176747');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses Inter in typography', () => {
|
||||||
|
const theme = createMoexVibeTheme();
|
||||||
|
expect(theme.typography.body1.fontFamily).toContain('Inter');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('maps radius.md to shape border radius', () => {
|
||||||
|
const theme = createMoexVibeTheme();
|
||||||
|
expect(theme.shape.borderRadius).toBe(8);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('disables elevation on MuiButton by default', () => {
|
||||||
|
const theme = createMoexVibeTheme();
|
||||||
|
expect(theme.components?.MuiButton?.defaultProps).toMatchObject({ disableElevation: true });
|
||||||
|
});
|
||||||
|
});
|
||||||
55
packages/design-system/src/theme/createMoexVibeTheme.ts
Normal file
55
packages/design-system/src/theme/createMoexVibeTheme.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { createTheme } from '@mui/material/styles';
|
||||||
|
import { primitiveTokens, semanticLightTokens, componentTokens, resolveToken } from '../tokens';
|
||||||
|
|
||||||
|
const allTokens = {
|
||||||
|
...primitiveTokens,
|
||||||
|
...semanticLightTokens,
|
||||||
|
...componentTokens,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
function resolveValue(name: string): string | number | readonly number[] | readonly string[] {
|
||||||
|
return resolveToken(allTokens, name).value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createMoexVibeTheme() {
|
||||||
|
return createTheme({
|
||||||
|
cssVariables: { cssVarPrefix: 'mv' },
|
||||||
|
colorSchemes: {
|
||||||
|
light: {
|
||||||
|
palette: {
|
||||||
|
primary: { main: resolveValue('color.action.primary') as string },
|
||||||
|
secondary: { main: resolveValue('color.action.secondary') as string },
|
||||||
|
error: { main: resolveValue('color.feedback.error') as string },
|
||||||
|
warning: { main: resolveValue('color.feedback.warning') as string },
|
||||||
|
info: { main: resolveValue('color.feedback.info') as string },
|
||||||
|
success: { main: resolveValue('color.finance.positive') as string },
|
||||||
|
background: {
|
||||||
|
default: resolveValue('color.canvas') as string,
|
||||||
|
paper: resolveValue('color.surface.default') as string,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: resolveValue('color.text.primary') as string,
|
||||||
|
secondary: resolveValue('color.text.secondary') as string,
|
||||||
|
disabled: resolveValue('color.text.disabled') as string,
|
||||||
|
},
|
||||||
|
divider: resolveValue('color.border.default') as string,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
typography: {
|
||||||
|
fontFamily: (resolveValue('font.family.sans') as readonly string[]).join(', '),
|
||||||
|
body1: { fontFamily: (resolveValue('font.family.body') as readonly string[]).join(', ') },
|
||||||
|
fontWeightRegular: resolveValue('font.weight.regular') as number,
|
||||||
|
fontWeightMedium: resolveValue('font.weight.medium') as number,
|
||||||
|
fontWeightBold: resolveValue('font.weight.bold') as number,
|
||||||
|
},
|
||||||
|
shape: {
|
||||||
|
borderRadius: parseInt(resolveValue('radius.md') as string, 10),
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
MuiButton: {
|
||||||
|
defaultProps: { disableElevation: true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
2
packages/design-system/src/theme/index.ts
Normal file
2
packages/design-system/src/theme/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { createMoexVibeTheme } from './createMoexVibeTheme';
|
||||||
|
export { MoexVibeThemeProvider } from './MoexVibeThemeProvider';
|
||||||
18
packages/design-system/src/theme/mui.d.ts
vendored
Normal file
18
packages/design-system/src/theme/mui.d.ts
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import type {} from '@mui/material/themeCssVarsAugmentation';
|
||||||
|
|
||||||
|
declare module '@mui/material/styles' {
|
||||||
|
interface Palette {
|
||||||
|
finance: {
|
||||||
|
positive: string;
|
||||||
|
negative: string;
|
||||||
|
neutral: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
interface PaletteOptions {
|
||||||
|
finance?: {
|
||||||
|
positive: string;
|
||||||
|
negative: string;
|
||||||
|
neutral: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user