frontend scalfolding

This commit is contained in:
Mengisteab
2026-06-10 07:03:50 +00:00
parent 4faf851a8f
commit 86edf2b971
40 changed files with 3525 additions and 79 deletions

View File

@@ -0,0 +1,60 @@
/* Portal global styles — loaded after Mantine's CSS, no Tailwind preflight so
it never fights Mantine's base styles. */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');
:root {
--ema-surface-light: #f5f8fc;
--ema-surface-dark: #0e1521;
}
body {
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
/* Tinted app background that adapts to the color scheme. */
[data-mantine-color-scheme='light'] body {
background-color: var(--ema-surface-light);
}
[data-mantine-color-scheme='dark'] body {
background-color: var(--ema-surface-dark);
}
[data-mantine-color-scheme] body {
transition: background-color 200ms ease;
}
/* ---- Motion utilities ---------------------------------------------------- */
@keyframes ema-fade-up {
from {
opacity: 0;
transform: translateY(8px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.ema-page-enter {
animation: ema-fade-up 320ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
/* Subtle lift on interactive cards. */
.ema-hover-lift {
transition:
transform 160ms ease,
box-shadow 160ms ease,
border-color 160ms ease;
}
.ema-hover-lift:hover {
transform: translateY(-3px);
}
@media (prefers-reduced-motion: reduce) {
.ema-page-enter,
.ema-hover-lift {
animation: none;
transition: none;
}
}

View File

@@ -0,0 +1,100 @@
import {
createTheme,
rem,
type MantineColorsTuple,
} from '@mantine/core';
// ---- Coastal Modern palette ----------------------------------------------
// Portal-only theme. Lives here (not in @ema-platform/shared) so the backoffice
// is unaffected.
const emaPrimary: MantineColorsTuple = [
'#eef4ff', '#dce7fb', '#b6cdf4', '#8db0ee', '#6c97e9',
'#5887e6', '#4b7fe5', '#3b6ccc', '#3160b7', '#2453a2',
];
// Teal accent — the "coastal" half of the palette.
const emaTeal: MantineColorsTuple = [
'#e1fbf6', '#cdf3eb', '#9ee6d7', '#6bd9c1', '#46cdaf',
'#30c7a5', '#1fc29d', '#0aab89', '#009879', '#008368',
];
// Cool neutral grays (slightly blue-tinted) for surfaces & text.
const emaGray: MantineColorsTuple = [
'#f6f8fb', '#eceff4', '#dde2eb', '#c8d0dd', '#aab5c7',
'#8d9bb3', '#73839e', '#5c6b85', '#46546b', '#333f52',
];
export const portalTheme = createTheme({
primaryColor: 'emaPrimary',
primaryShade: { light: 6, dark: 5 },
colors: {
emaPrimary,
emaTeal,
gray: emaGray,
},
fontFamily:
'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
headings: {
fontFamily: 'Inter, sans-serif',
fontWeight: '700',
sizes: {
h1: { fontSize: rem(32), lineHeight: '1.25' },
h2: { fontSize: rem(25), lineHeight: '1.3' },
h3: { fontSize: rem(21), lineHeight: '1.35' },
h4: { fontSize: rem(17), lineHeight: '1.4' },
h5: { fontSize: rem(15), lineHeight: '1.45' },
},
},
defaultRadius: 'md',
radius: {
xs: rem(6),
sm: rem(8),
md: rem(12),
lg: rem(16),
xl: rem(22),
},
shadows: {
xs: '0 1px 2px rgba(15,23,42,0.06)',
sm: '0 2px 8px rgba(15,23,42,0.06), 0 1px 2px rgba(15,23,42,0.04)',
md: '0 8px 24px rgba(15,23,42,0.08)',
lg: '0 16px 40px rgba(15,23,42,0.12)',
xl: '0 24px 64px rgba(15,23,42,0.16)',
},
breakpoints: {
xs: '36em',
sm: '48em',
md: '62em',
lg: '75em',
xl: '88em',
},
cursorType: 'pointer',
components: {
Paper: {
defaultProps: { radius: 'lg' },
},
Card: {
defaultProps: { radius: 'lg' },
},
Button: {
defaultProps: { radius: 'md' },
styles: { root: { fontWeight: 600 } },
},
Badge: {
defaultProps: { radius: 'sm' },
},
ThemeIcon: {
defaultProps: { radius: 'md' },
},
NavLink: {
styles: { root: { borderRadius: rem(10), fontWeight: 500 } },
},
TextInput: { defaultProps: { radius: 'md' } },
Textarea: { defaultProps: { radius: 'md' } },
Select: { defaultProps: { radius: 'md' } },
PasswordInput: { defaultProps: { radius: 'md' } },
},
other: {
heroGradient: 'linear-gradient(135deg, #3160b7 0%, #1fc29d 100%)',
},
});