Initial commit: nick docs

This commit is contained in:
moojttaba
2026-05-23 20:35:34 +03:30
commit 0da235ae27
90 changed files with 18268 additions and 0 deletions

View File

@@ -0,0 +1,250 @@
---
title: Theme Configuration
tags: [design-system, theme, mui]
created: 2026-05-23
---
# Theme Configuration
The MUI theme is constructed in `frontend/src/theme/index.ts` and composed from option modules in `frontend/src/theme/options/`. The resulting theme is provided at the root layout, wrapped by an RTL-aware emotion cache.
---
## 1. Construction pipeline
```ts
// approximate — read theme/index.ts for the canonical version
import { createTheme } from '@mui/material/styles';
import { palette } from './options/palette';
import { typography } from './options/typography';
import { shadows, customShadows } from './options/shadows';
import { componentsOverrides } from './options/overrides';
export function buildTheme(opts: { mode: 'light' | 'dark'; direction: 'ltr' | 'rtl'; preset: string; }) {
return createTheme({
direction: opts.direction,
palette: palette(opts.mode, opts.preset),
typography,
shape: { borderRadius: 8 },
shadows: shadows(opts.mode),
customShadows: customShadows(opts.mode),
components: componentsOverrides(opts),
breakpoints: {
values: { xs: 0, sm: 600, md: 900, lg: 1200, xl: 1536 },
},
});
}
```
The settings context calls `buildTheme()` whenever any axis changes, then re-mounts `<ThemeProvider>`. Because MUI v7 supports CSS variables, the swap is cheap (no React tree thrash).
---
## 2. Provider wiring (root layout)
```tsx
// frontend/src/app/layout.tsx (simplified)
<AppRouterCacheProvider options={{ key: dir === 'rtl' ? 'css-rtl' : 'css', prepend: true, stylisPlugins: dir === 'rtl' ? [rtlPlugin] : [] }}>
<ThemeProvider theme={theme}>
<CssBaseline />
<LocalizationProvider dateAdapter={AdapterDayjs}>
<I18nProvider>
<QueryClientProvider client={queryClient}>
<SocketProvider>
<SnackbarProvider>{children}</SnackbarProvider>
</SocketProvider>
</QueryClientProvider>
</I18nProvider>
</LocalizationProvider>
</ThemeProvider>
</AppRouterCacheProvider>
```
> [!warning]
> The cache `key` MUST differ between LTR and RTL (`'css'` vs `'css-rtl'`) — otherwise switching direction at runtime keeps the previous direction's CSS in the head and the layout breaks.
---
## 3. Palette
See [[Colors]] for the full table. Structure:
```ts
{
mode: 'light' | 'dark',
primary: { lighter, light, main, dark, darker, contrastText },
secondary: { lighter, light, main, dark, darker, contrastText },
info: { lighter, light, main, dark, darker, contrastText },
success: { lighter, light, main, dark, darker, contrastText },
warning: { lighter, light, main, dark, darker, contrastText },
error: { lighter, light, main, dark, darker, contrastText },
grey: { 100900 },
text: { primary, secondary, disabled },
background:{ default, paper, neutral },
action: { active, hover, selected, focus, disabled, disabledBackground },
}
```
Color presets (selectable in settings) swap the `primary` + `secondary` color groups while leaving `grey`, `error`, etc. untouched.
---
## 4. Typography
```ts
{
fontFamily: '"Public Sans Variable", "Helvetica", "Arial", sans-serif',
fontWeightRegular: 400,
fontWeightMedium: 500,
fontWeightSemiBold: 600,
fontWeightBold: 700,
h1: { fontSize: 64, lineHeight: 80/64, letterSpacing: -1 },
h2: { fontSize: 48, lineHeight: 64/48 },
h3: { fontSize: 32, lineHeight: 48/32 },
h4: { fontSize: 24, lineHeight: 36/24 },
h5: { fontSize: 20, lineHeight: 30/20 },
h6: { fontSize: 18, lineHeight: 28/18 },
subtitle1: { fontSize: 16, fontWeight: 600 },
subtitle2: { fontSize: 14, fontWeight: 600 },
body1: { fontSize: 16 },
body2: { fontSize: 14 },
caption: { fontSize: 12 },
overline: { fontSize: 12, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 1.1 },
button: { fontSize: 14, fontWeight: 700, textTransform: 'unset' },
}
```
Variants `h1` and `h2` scale down responsively. Use the `responsiveFontSizes(theme)` helper if you need automatic scaling.
See [[Typography]] for font loading, secondary font (Barlow), and i18n font fallbacks.
---
## 5. Spacing
```ts
spacing: 8 // unit
// theme.spacing(1) === '8px'
// theme.spacing(2) === '16px'
// theme.spacing(0.5) === '4px'
```
Use the shorthand props on the `sx`:
```tsx
<Box sx={{ p: 2, mt: 3, mx: { xs: 1, md: 4 } }} />
```
---
## 6. Shape & radii
```ts
shape: { borderRadius: 8 } // default
// cards typically: borderRadius: 16
// pills: borderRadius: 9999
```
---
## 7. Shadows
MUI's default `shadows` array (25 levels: `none`, then `1``24`) is replaced with a softer custom set. Additionally, `customShadows` defines brand-specific tinted shadows used by the `Card`, `Button`, `Dialog` overrides:
```ts
customShadows: {
z1, z4, z8, z12, z16, z20, z24,
primary: 'rgba(<primary.main>, 0.24) 0 8 16 0',
secondary: '…',
info: '…',
success: '…',
warning: '…',
error: '…',
card: 'rgba(0,0,0,0.04) 0 0 2 0, rgba(0,0,0,0.08) 0 12 24 -4',
dialog: '…',
dropdown: '…',
}
```
Read inside `sx`:
```tsx
sx={{ boxShadow: (theme) => theme.customShadows.z8 }}
```
---
## 8. Component overrides
`theme/options/overrides/` contains one file per overridden component, each exporting `{ defaultProps, styleOverrides }` merged into `components`:
| Component | Notable override |
|---|---|
| `MuiButton` | `disableRipple`, custom `customShadows.primary` on contained variant |
| `MuiCard` | `borderRadius: 16`, `customShadows.card` |
| `MuiPaper` | elevation flattened to `0` by default (use `card` shadow explicitly) |
| `MuiTextField` | `variant: 'outlined'` default, custom focus ring |
| `MuiTooltip` | dark background regardless of mode, smaller padding |
| `MuiAvatar` | letter-based fallback with hashed background color |
| `MuiTableCell` | denser padding, header weight 600 |
| `MuiDialog` | `customShadows.dialog`, max-width responsive |
| `MuiAlert` | tinted background using palette `lighter` |
| `MuiTab` | uppercase off, color from `primary.main` when selected |
| `MuiAutocomplete` | custom popup paper shadow |
Add an override:
1. Create `theme/options/overrides/<Component>.ts` exporting a function `(theme) => ({...})`.
2. Register it in `theme/options/overrides/index.ts`.
3. It will be merged into the next `createTheme` call automatically.
---
## 9. CSS variables (MUI v7)
`createTheme` with `cssVariables: true` (recommended) emits CSS custom properties at the `<html>` root and switches them per mode without re-rendering. The default is on in v7 — verify in `theme/index.ts`.
This means a custom CSS rule can reference:
```css
.my-thing {
background: var(--mui-palette-primary-main);
padding: calc(var(--mui-spacing) * 2);
}
```
Use this sparingly — prefer the `sx` prop.
---
## 10. Per-locale font swap
When the active locale is `fa` or `ar`, the typography option module can layer a Persian/Arabic font (e.g., **Vazirmatn**, **IRANSans**) ahead of `Public Sans Variable`:
```ts
fontFamily: dir === 'rtl'
? '"Vazirmatn", "Public Sans Variable", sans-serif'
: '"Public Sans Variable", sans-serif',
```
Otherwise Latin glyphs still render via the Public Sans fallback. See [[Internationalization & RTL]].
---
## 11. Customisation checklist
- [ ] New brand color → update `palette.ts` (light + dark) and consider a preset.
- [ ] New variant → add to typography options and the `TypographyOptions` interface augmentation.
- [ ] Component override → file in `overrides/`.
- [ ] Verify in both modes (light + dark) AND both directions (ltr + rtl).
- [ ] Verify against WCAG AA contrast.
- [ ] Snapshot test the component if visual stability matters.
---
## Related
- [[Design System Overview]]
- [[Colors]] · [[Typography]] · [[Components]] · [[Layouts]]
- [[Internationalization & RTL]] · [[Settings & Theming]]
- [[Frontend Architecture]]