Files
emaui/libs/shared/src/lib/theme/portal-theme.ts
fitse-yotor 659e954306 refactor(theme): share one base theme between backoffice and portal
The two apps had drifted into unrelated themes. The portal's carried a full
type scale, radius scale, shadow ramp and component defaults; the backoffice's
had none of them — 55 lines defining two colour ramps and little else. With
nothing to inherit, its 23 features each invented their own sizing, which is
the real source of the inconsistency the UI reads with.

Promote the portal's structure to `libs/shared` as `baseTheme`, and reduce both
themes to what they should differ on: brand. The backoffice keeps #1e40af and
the portal keeps Coastal Modern — a distinct accent tells an officer which of
the two systems they are in, and the ramps are not interchangeable in contrast.

Both export names are preserved, so no consumer import changes.

Two properties are deliberately held back rather than shared:
- `colors.gray`: the portal's blue-tinted neutrals retint every dimmed label,
  neutral badge and table border. The backoffice adopts them as its own
  reviewed change, not as a side effect of sharing a base.
- `primaryShade.dark`: moves every filled control in dark mode; waits until
  dark mode is verified end to end.

Also fixes a live bug: PageLoader coloured its primary label `navy.9`, which is
defined in neither theme. Mantine drops unresolved colour keys silently, so the
label in a component used by 20 files had been rendering an inherited colour.

Adds a visual-regression harness to make all of this reviewable. It runs
against a static gallery route rather than real pages, so it needs no API,
database or auth — a theme diff cannot be masked by a migration or an expired
token. The portal is the control group: it is pixel-identical across all four
light/dark × desktop/tablet baselines, which is what makes the refactor
provably lossless.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 11:25:26 +03:00

30 lines
1.0 KiB
TypeScript

import { createTheme, mergeThemeOverrides } from '@mantine/core';
import { baseTheme } from './base-theme';
import { emaCoastalBlue, emaGray, emaTeal } from './palettes';
/**
* Portal theme — "Coastal Modern".
*
* Structure comes from `baseTheme` (which this theme's own structure was the
* source of, so nothing here changes visually). What remains is the brand: a
* softer blue than the backoffice, a teal accent, and cool blue-tinted
* neutrals in place of Mantine's stock gray.
*
* The gray override stays portal-only for now. It is the widest-reaching
* single line in either theme — it retints every dimmed label, neutral badge
* and table border — so the backoffice adopts it as its own reviewed change,
* not as a side effect of sharing a base.
*/
export const portalTheme = mergeThemeOverrides(
baseTheme,
createTheme({
primaryColor: 'emaPrimary',
primaryShade: { light: 6, dark: 5 },
colors: {
emaPrimary: emaCoastalBlue,
emaTeal,
gray: emaGray,
},
}),
);