style: some clean up

This commit is contained in:
ghost2023
2026-06-19 16:24:20 +03:00
parent 2b4da2397c
commit 9caf9bbd59
6 changed files with 344 additions and 170 deletions

View File

@@ -87,7 +87,12 @@ const FreightDashboardHeader = ({
<Text
fw={700}
truncate
style={{ fontSize: "20px", lineHeight: 1.2, color: "#0f172a", letterSpacing: "-0.4px" }}
style={{
fontSize: "20px",
lineHeight: 1.2,
color: "#0f172a",
letterSpacing: "-0.4px",
}}
>
{pageMeta.title}
</Text>
@@ -120,13 +125,6 @@ const FreightDashboardHeader = ({
</button>
</Tooltip>
<Tooltip label="Messages" withArrow openDelay={300}>
<button type="button" className="fdh-icon-btn" aria-label="Messages">
<MessageSquare size={18} />
<span className="fdh-badge">3</span>
</button>
</Tooltip>
<Tooltip label="Notifications" withArrow openDelay={300}>
<button
type="button"
@@ -189,7 +187,12 @@ const FreightDashboardHeader = ({
<div className="fdh-avatar">{initials}</div>
</div>
<Stack gap={0} style={{ minWidth: 0 }}>
<Text size="sm" fw={600} truncate style={{ color: "#0f172a" }}>
<Text
size="sm"
fw={600}
truncate
style={{ color: "#0f172a" }}
>
{userName}
</Text>
{userEmail && (

View File

@@ -65,25 +65,24 @@ const FreightDashboardLayout = ({
return (
<>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="" />
<link
href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700&display=swap"
rel="stylesheet"
/>
<MantineProvider theme={freightMantineTheme}>
<Box
style={{
display: "flex",
height: "100dvh",
overflow: "hidden",
background: "var(--mantine-color-gray-1)",
padding: "0px",
fontFamily: "'Outfit', var(--font-sans)",
}}
>
<Box style={{ display: "flex", height: "100%", minHeight: 0, width: "100%", gap: "5px" }}>
<Box
style={{
display: "flex",
height: "100%",
minHeight: 0,
width: "100%",
}}
>
<FreightSidebar
sections={sidebarSections}
activeHref={activeHref}
@@ -98,49 +97,21 @@ const FreightDashboardLayout = ({
minWidth: 0,
flex: 1,
flexDirection: "column",
gap: "8px",
}}
>
<Paper
p={0}
radius="lg"
withBorder
style={{
flexShrink: 0,
background: "white",
border: "1px solid var(--mantine-color-gray-2)",
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.05)",
}}
>
<FreightDashboardHeader
pageMeta={pageMeta}
headerRight={headerRight}
enableThemeToggle={enableThemeToggle}
userName={userName}
userEmail={userEmail}
userInitials={userInitials}
onLogout={onLogout}
theme={theme}
onToggleTheme={toggleTheme}
/>
</Paper>
<FreightDashboardHeader
pageMeta={pageMeta}
headerRight={headerRight}
enableThemeToggle={enableThemeToggle}
userName={userName}
userEmail={userEmail}
userInitials={userInitials}
onLogout={onLogout}
theme={theme}
onToggleTheme={toggleTheme}
/>
<Paper
p={{ base: 16, md: 24 }}
radius="lg"
withBorder
style={{
minHeight: 0,
flex: 1,
overflowY: "auto",
overscrollBehavior: "contain",
background: "white",
border: "1px solid var(--mantine-color-gray-2)",
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.05)",
}}
>
{children}
</Paper>
{children}
</Box>
</Box>
</Box>

View File

@@ -8,12 +8,7 @@
max-height: 100%;
width: 280px;
flex-shrink: 0;
border-radius: 16px;
border: 1px solid #eef1f4;
background: #ffffff;
box-shadow:
0 1px 2px rgba(15, 23, 42, 0.04),
0 8px 24px -16px rgba(15, 23, 42, 0.12);
border-radius: 12px;
display: flex;
flex-direction: column;
overflow: hidden;
@@ -36,8 +31,9 @@
content: "";
position: absolute;
inset: 0;
background:
radial-gradient(120px 80px at 24px 18px, rgba(34, 197, 94, 0.08), transparent 70%);
background: radial-gradient(120px 80px at 24px 18px,
rgba(34, 197, 94, 0.08),
transparent 70%);
pointer-events: none;
}
@@ -50,7 +46,7 @@
width: 44px;
height: 44px;
border-radius: 13px;
background: linear-gradient(135deg, #2DBF95 0%, #1B9E7A 60%, #15805F 100%);
background: linear-gradient(135deg, #2dbf95 0%, #1b9e7a 60%, #15805f 100%);
box-shadow:
0 6px 16px -4px rgba(27, 158, 122, 0.45),
inset 0 1px 0 rgba(255, 255, 255, 0.25);
@@ -72,13 +68,16 @@
.fsb-nav::-webkit-scrollbar {
width: 6px;
}
.fsb-nav::-webkit-scrollbar-thumb {
background: #e2e8f0;
border-radius: 3px;
}
.fsb-nav::-webkit-scrollbar-thumb:hover {
background: #cbd5e1;
}
.fsb-nav::-webkit-scrollbar-track {
background: transparent;
}
@@ -121,12 +120,10 @@
}
.fsb-item[data-active="true"] {
background: linear-gradient(
135deg,
rgba(34, 197, 94, 0.12) 0%,
rgba(27, 158, 122, 0.06) 100%
);
color: #1B9E7A;
background: linear-gradient(135deg,
rgba(34, 197, 94, 0.12) 0%,
rgba(27, 158, 122, 0.06) 100%);
color: #1b9e7a;
font-weight: 600;
}
@@ -139,7 +136,7 @@
width: 3px;
height: 22px;
border-radius: 0 4px 4px 0;
background: linear-gradient(180deg, #2DBF95 0%, #1B9E7A 100%);
background: linear-gradient(180deg, #2dbf95 0%, #1b9e7a 100%);
}
.fsb-item-label {
@@ -155,8 +152,6 @@
display: flex;
align-items: center;
justify-content: center;
width: 31px;
height: 31px;
border-radius: 9px;
flex-shrink: 0;
background: #f1f5f9;
@@ -164,13 +159,19 @@
transition: all 160ms ease;
}
/* ---- Icon well ---- */
.fsb-icon svg {
height: 24px;
width: 24px;
}
.fsb-item:hover .fsb-icon {
background: #e6ebf1;
color: #334155;
}
.fsb-item[data-active="true"] .fsb-icon {
background: linear-gradient(135deg, #2DBF95 0%, #1B9E7A 100%);
background: linear-gradient(135deg, #2dbf95 0%, #1b9e7a 100%);
color: #ffffff;
box-shadow: 0 5px 12px -2px rgba(27, 158, 122, 0.45);
}
@@ -219,9 +220,11 @@
background: transparent;
transition: background-color 150ms ease;
}
.fsb-group:hover {
background-color: #f5f7fa;
}
.fsb-group-label {
font-size: 11px;
font-weight: 700;
@@ -229,8 +232,9 @@
text-transform: uppercase;
color: #94a3b8;
}
.fsb-group[data-active="true"] .fsb-group-label {
color: #1B9E7A;
color: #1b9e7a;
}
/* child leaf */
@@ -251,12 +255,14 @@
background-color 150ms ease,
color 150ms ease;
}
.fsb-child:hover {
background-color: #f5f7fa;
color: #0f172a;
}
.fsb-child[data-active="true"] {
color: #1B9E7A;
color: #1b9e7a;
font-weight: 600;
background-color: rgba(27, 158, 122, 0.08);
}
@@ -269,11 +275,13 @@
background: #cbd5e1;
transition: all 150ms ease;
}
.fsb-child:hover .fsb-dot {
background: #94a3b8;
}
.fsb-child[data-active="true"] .fsb-dot {
background: #1B9E7A;
background: #1b9e7a;
box-shadow: 0 0 0 3px rgba(27, 158, 122, 0.16);
}
@@ -283,36 +291,41 @@
padding: 12px;
border-top: 1px solid #f1f5f9;
}
.fsb-status {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 12px;
border-radius: 11px;
background: linear-gradient(135deg, #E7F8F2 0%, #f8fafc 100%);
background: linear-gradient(135deg, #e7f8f2 0%, #f8fafc 100%);
border: 1px solid #e7f3ec;
}
.fsb-pulse {
position: relative;
width: 9px;
height: 9px;
border-radius: 50%;
background: #2DBF95;
background: #2dbf95;
flex-shrink: 0;
}
.fsb-pulse::after {
content: "";
position: absolute;
inset: 0;
border-radius: 50%;
background: #2DBF95;
background: #2dbf95;
animation: fsb-pulse 2s ease-out infinite;
}
@keyframes fsb-pulse {
0% {
transform: scale(1);
opacity: 0.6;
}
100% {
transform: scale(2.6);
opacity: 0;

View File

@@ -11,6 +11,7 @@ import { Box, Stack, Text } from "@mantine/core";
import type { SidebarItem, SidebarSection } from "./types";
import "./FreightSidebar.css";
import { Link } from "react-router-dom";
export interface FreightSidebarProps {
sections: SidebarSection[];
@@ -176,20 +177,7 @@ const FreightSidebar = ({
return (
<Box key={item.href}>
<a
href={item.href}
className="fsb-item"
data-active={isActive}
onClick={(e) => {
if (hasChildren) {
setExpanded((current) => ({
...current,
[item.href!]: true,
}));
}
navigateTo(e, item.href!);
}}
>
<Link to={item.href} className="fsb-item" data-active={isActive}>
{item.icon && <span className="fsb-icon">{item.icon}</span>}
<span className="fsb-item-label">{item.label}</span>
{hasChildren && (
@@ -212,7 +200,7 @@ const FreightSidebar = ({
/>
</button>
)}
</a>
</Link>
{hasChildren && isOpen && (
<div className="fsb-branch">
@@ -224,7 +212,16 @@ const FreightSidebar = ({
};
return (
<Box component="aside" className="fsb-aside">
<Box
component="aside"
className="fsb-aside"
m="4px"
bg="edr-bg"
style={{
border: "1px solid var(--mantine-color-gray-2)",
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.05)",
}}
>
<div className="fsb-brand">
<div className="fsb-logo">
<Train size={23} color="white" strokeWidth={2.1} />
@@ -233,7 +230,11 @@ const FreightSidebar = ({
<Text
size="md"
fw={700}
style={{ letterSpacing: "-0.3px", lineHeight: 1.2, color: "#0f172a" }}
style={{
letterSpacing: "-0.3px",
lineHeight: 1.2,
color: "#0f172a",
}}
>
EDR Freight
</Text>
@@ -257,20 +258,6 @@ const FreightSidebar = ({
</div>
))}
</nav>
<div className="fsb-footer">
<div className="fsb-status">
<span className="fsb-pulse" />
<Stack gap={0} style={{ minWidth: 0 }}>
<Text size="xs" fw={600} style={{ color: "#15805F", lineHeight: 1.3 }}>
All systems operational
</Text>
<Text size="10px" style={{ color: "#94a3b8", lineHeight: 1.3 }}>
EDR Platform · v1.0
</Text>
</Stack>
</div>
</div>
</Box>
);
};

View File

@@ -1,6 +1,15 @@
import { type FormEvent, useState } from "react";
import { parsePhoneNumberFromString } from "libphonenumber-js";
import { Eye, EyeOff, Mail, Smartphone, UserRound, ArrowUpRight, Globe, ChevronDown } from "lucide-react";
import {
Eye,
EyeOff,
Mail,
Smartphone,
UserRound,
ArrowUpRight,
Globe,
ChevronDown,
} from "lucide-react";
import { useNavigate } from "react-router-dom";
import { useAuth } from "@/auth/useAuth";
@@ -13,10 +22,25 @@ const loginModes: Array<{
icon: typeof Mail;
placeholder: string;
}> = [
{ value: "email", label: "Email", icon: Mail, placeholder: "name@company.com" },
{ value: "phone", label: "Phone", icon: Smartphone, placeholder: "09XXXXXXXX" },
{ value: "username", label: "Username", icon: UserRound, placeholder: "username" },
];
{
value: "email",
label: "Email",
icon: Mail,
placeholder: "name@company.com",
},
{
value: "phone",
label: "Phone",
icon: Smartphone,
placeholder: "09XXXXXXXX",
},
{
value: "username",
label: "Username",
icon: UserRound,
placeholder: "username",
},
];
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const usernamePattern = /^[a-zA-Z0-9._-]{3,32}$/;
@@ -43,7 +67,9 @@ const normalizeIdentifier = (mode: LoginMode, value: string) => {
}
if (!usernamePattern.test(trimmed)) {
throw new Error("Username must be 3-32 characters and use letters, numbers, ., _, or -.");
throw new Error(
"Username must be 3-32 characters and use letters, numbers, ., _, or -.",
);
}
return trimmed;
@@ -59,14 +85,24 @@ const primaryButtonClass =
"h-11 w-full rounded-full bg-primary text-sm font-semibold text-primary-foreground shadow-[0_8px_20px_-6px_rgba(16,94,52,0.5)] transition-all duration-200 hover:bg-primary/90 hover:shadow-[0_10px_24px_-6px_rgba(16,94,52,0.55)] active:scale-[0.99] disabled:cursor-not-allowed disabled:opacity-60 disabled:shadow-none";
const LeftPanelDecor = () => (
<div className="pointer-events-none absolute inset-0 overflow-hidden" aria-hidden>
<div
className="pointer-events-none absolute inset-0 overflow-hidden"
aria-hidden
>
<svg
className="absolute -bottom-24 -left-24 h-[420px] w-[420px] text-white/[0.07]"
viewBox="0 0 400 400"
fill="none"
>
{[0, 1, 2, 3, 4, 5].map((ring) => (
<circle key={ring} cx="200" cy="200" r={60 + ring * 36} stroke="currentColor" strokeWidth="1" />
<circle
key={ring}
cx="200"
cy="200"
r={60 + ring * 36}
stroke="currentColor"
strokeWidth="1"
/>
))}
</svg>
<div className="absolute right-0 top-0 h-40 w-40 rounded-full bg-white/[0.06] blur-2xl" />
@@ -74,12 +110,23 @@ const LeftPanelDecor = () => (
);
const RightPanelDecor = () => (
<div className="pointer-events-none absolute inset-0 overflow-hidden" aria-hidden>
<div
className="pointer-events-none absolute inset-0 overflow-hidden"
aria-hidden
>
<div className="absolute -right-16 -top-20 h-56 w-56 rounded-full bg-primary/[0.06] blur-3xl" />
<div className="absolute -bottom-12 left-1/4 h-40 w-40 rounded-full bg-primary/[0.04] blur-2xl" />
<svg className="absolute inset-0 h-full w-full text-gray-200/40" xmlns="http://www.w3.org/2000/svg">
<svg
className="absolute inset-0 h-full w-full text-gray-200/40"
xmlns="http://www.w3.org/2000/svg"
>
<defs>
<pattern id="login-grid" width="28" height="28" patternUnits="userSpaceOnUse">
<pattern
id="login-grid"
width="28"
height="28"
patternUnits="userSpaceOnUse"
>
<circle cx="1" cy="1" r="0.75" fill="currentColor" />
</pattern>
</defs>
@@ -99,7 +146,11 @@ const LeftPanel = () => (
<LeftPanelDecor />
<div className="relative z-10 flex shrink-0 items-center justify-between px-4 pt-4 sm:px-6 sm:pt-6 lg:px-8 lg:pt-8">
<img src={EDR_LOGO} alt="EDR Freight" className="h-7 w-auto brightness-0 invert sm:h-9" />
<img
src={EDR_LOGO}
alt="EDR Freight"
className="h-7 w-auto brightness-0 invert sm:h-9"
/>
<a
href="#"
className="flex items-center gap-1.5 rounded-full border border-white/70 bg-white/10 px-3 py-1.5 text-xs font-medium text-white backdrop-blur-sm transition-colors hover:bg-white/20 sm:px-4 sm:py-2 sm:text-sm"
@@ -118,8 +169,8 @@ const LeftPanel = () => (
</span>
</div>
<p className="text-sm leading-relaxed text-white/85">
Sign in to manage bookings, track cargo, and run logistics operations on the
Ethio Djibouti Railway freight platform.
Sign in to manage bookings, track cargo, and run logistics operations
on the Ethio Djibouti Railway freight platform.
</p>
</div>
</div>
@@ -138,13 +189,22 @@ const FormFooter = () => (
<div className="relative z-10 flex shrink-0 flex-col items-center justify-between gap-3 border-t border-gray-100 px-4 py-4 text-xs text-gray-400 sm:flex-row sm:gap-4 sm:px-6 sm:py-4 lg:px-8 lg:pb-6">
<span className="shrink-0">© 2026 EDR Freight</span>
<div className="flex flex-wrap items-center justify-center gap-3 sm:justify-end sm:gap-6">
<a href="#" className="font-semibold text-gray-700 transition-colors hover:text-primary">
<a
href="#"
className="font-semibold text-gray-700 transition-colors hover:text-primary"
>
Terms & Conditions
</a>
<a href="#" className="font-semibold text-gray-700 transition-colors hover:text-primary">
<a
href="#"
className="font-semibold text-gray-700 transition-colors hover:text-primary"
>
Privacy Policy
</a>
<a href="#" className="font-semibold text-gray-700 transition-colors hover:text-primary">
<a
href="#"
className="font-semibold text-gray-700 transition-colors hover:text-primary"
>
Help & Support
</a>
</div>
@@ -176,7 +236,7 @@ const LoginPage = () => {
setNormalizedIdentifier(normalized);
const result = await login({ email: normalized, password });
console.log(result)
console.log(result);
if (result.mfaRequired) {
setNeedsMfa(true);
return;
@@ -212,15 +272,20 @@ const LoginPage = () => {
</div>
<div className="mb-4 space-y-1.5 text-center sm:mb-5">
<h1 className="text-xl font-bold tracking-tight text-gray-900 sm:text-2xl">Get Started</h1>
<h1 className="text-xl font-bold tracking-tight text-gray-900 sm:text-2xl">
Get Started
</h1>
<p className="text-sm leading-relaxed text-gray-500">
Log in to access the freight backoffice & explore all logistics resources.
Log in to access the freight backoffice & explore all logistics
resources.
</p>
</div>
<div className="flex w-full flex-col gap-4">
<div className="space-y-1.5">
<label className="text-sm font-medium text-gray-800">Sign in method</label>
<label className="text-sm font-medium text-gray-800">
Sign in method
</label>
<div className="relative">
<select
value={mode}
@@ -267,32 +332,26 @@ const LoginPage = () => {
className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 transition-colors hover:text-gray-600"
aria-label={showPassword ? "Hide password" : "Show password"}
>
{showPassword ? <EyeOff className="h-5 w-5" /> : <Eye className="h-5 w-5" />}
{showPassword ? (
<EyeOff className="h-5 w-5" />
) : (
<Eye className="h-5 w-5" />
)}
</button>
</div>
</div>
<label className="flex cursor-pointer items-start gap-2.5">
<input
type="checkbox"
className="mt-0.5 h-4 w-4 shrink-0 cursor-pointer rounded-md border-gray-300 text-primary transition-colors focus:ring-2 focus:ring-primary/20 focus:ring-offset-0"
/>
<span className="text-sm leading-snug text-gray-600">
I agree to EDR Freight{" "}
<a href="#" className="font-semibold text-primary hover:underline">
Terms & Conditions
</a>
.
</span>
</label>
{error ? (
<div className="rounded-lg border border-red-200 bg-red-50 px-3 py-2.5 text-sm text-red-700">
{error}
</div>
) : null}
<button type="submit" disabled={submitting} className={primaryButtonClass}>
<button
type="submit"
disabled={submitting}
className={primaryButtonClass}
>
{submitting ? "Signing in..." : "Sign In"}
</button>
@@ -318,8 +377,10 @@ const LoginPage = () => {
</h1>
<p className="text-sm leading-relaxed text-gray-500">
We sent a verification code to{" "}
<span className="font-medium text-gray-700">{normalizedIdentifier}</span>. Enter it below
to complete sign in.
<span className="font-medium text-gray-700">
{normalizedIdentifier}
</span>
. Enter it below to complete sign in.
</p>
</div>
@@ -354,7 +415,11 @@ const LoginPage = () => {
>
Back
</button>
<button type="submit" disabled={submitting} className={`${primaryButtonClass} min-w-0 flex-1`}>
<button
type="submit"
disabled={submitting}
className={`${primaryButtonClass} min-w-0 flex-1`}
>
{submitting ? "Verifying..." : "Verify"}
</button>
</div>

View File

@@ -1,4 +1,8 @@
import { createTheme, type MantineColorsTuple } from "@mantine/core";
import {
colorsTuple,
createTheme,
type MantineColorsTuple,
} from "@mantine/core";
/** EDR Freight primary brand green */
export const FREIGHT_BRAND = "#1B9E7A";
@@ -17,24 +21,155 @@ export const freightBrand = {
mutedBorder: "#B7EBDC",
} as const;
/** Mantine green scale with #1B9E7A at index 6 (filled buttons, nav active). */
const freightGreen: MantineColorsTuple = [
"#E7F8F2",
"#C5EFE1",
"#9CE4CD",
"#6BD6B5",
"#41C8A0",
"#25B58C",
FREIGHT_BRAND,
FREIGHT_BRAND_DARK,
"#105F47",
"#0A3D2E",
const edrGreen: MantineColorsTuple = [
"#ecfdf5",
"#d1fae5",
"#a7f3d0",
"#6ee7b7",
"#34d399",
"#0EA371",
"#0A8A5F",
"#0A6F4D",
"#065f46",
"#064e3b",
];
const neutral: MantineColorsTuple = [
"#F4F7FA",
"#eef2f7",
"#E6ECF2",
"#d0dae6",
"#b0bfce",
"#8fa0b2",
"#6B7C8E",
"#4b5a6a",
"#10202F",
"#0C1A2B",
];
export const freightMantineTheme = createTheme({
primaryColor: "green",
colors: {
green: freightGreen,
"edr-green": edrGreen,
gray: neutral,
// Brand surface + text tokens (single-value semantic colors).
// Each generates --mantine-color-{name}-{0..9} CSS variables.
"edr-bg": colorsTuple("#F7FAFC"),
"edr-card": colorsTuple("#FFFFFF"),
"edr-border": colorsTuple("#E6ECF2"),
"edr-divider": colorsTuple("#EEF1F5"),
"edr-text": colorsTuple("#10202F"),
"edr-muted": colorsTuple("#6B7C8E"),
"edr-soft": colorsTuple("#ECF6F1"),
"edr-ink": colorsTuple("#0C1A2B"),
"edr-accent": colorsTuple("#F2A516"),
// Semantic status shades (from the design system).
"edr-amber-soft": colorsTuple("#FDF3E0"),
"edr-amber-text": colorsTuple("#9A5B00"),
"edr-blue": colorsTuple("#2E5B96"),
"edr-blue-soft": colorsTuple("#E9F0F8"),
"edr-blue-dot": colorsTuple("#3B6FB0"),
"edr-red": colorsTuple("#C0392B"),
"edr-red-soft": colorsTuple("#FBEAE7"),
"edr-slate": colorsTuple("#475569"),
"edr-slate-soft": colorsTuple("#F1F4F7"),
"edr-slate-soft2": colorsTuple("#EEF2F6"),
"edr-step": colorsTuple("#94A3B8"),
"edr-step-idle": colorsTuple("#D5DBE2"),
"edr-conn-idle": colorsTuple("#E6EAEF"),
},
primaryColor: "edr-green",
primaryShade: { light: 5, dark: 4 },
white: "#ffffff",
black: "#10202F",
fontFamily:
'"Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
defaultRadius: "md",
radius: {
xs: "4px",
sm: "6px",
md: "8px",
lg: "12px",
xl: "18px",
},
spacing: {
xs: "8px",
sm: "12px",
md: "16px",
lg: "24px",
xl: "32px",
},
fontSizes: {
xs: "12px",
sm: "14px",
md: "16px",
lg: "20px",
xl: "24px",
},
lineHeights: {
xs: "1.4",
sm: "1.45",
md: "1.55",
lg: "1.55",
xl: "1.5",
},
headings: {
fontFamily: '"Inter", var(--mantine-font-family)',
fontWeight: "700",
sizes: {
h1: { fontSize: "36px", lineHeight: "1.1", fontWeight: "800" },
h2: { fontSize: "28px", lineHeight: "1.2", fontWeight: "700" },
h3: { fontSize: "22px", lineHeight: "1.3", fontWeight: "600" },
h4: { fontSize: "18px", lineHeight: "1.4", fontWeight: "600" },
h5: { fontSize: "15px", lineHeight: "1.45", fontWeight: "600" },
h6: { fontSize: "13px", lineHeight: "1.45", fontWeight: "600" },
},
},
shadows: {
xs: "0 1px 2px rgba(16, 24, 40, 0.04)",
sm: "0 1px 3px rgba(16, 24, 40, 0.06)",
md: "0 4px 12px rgba(16, 24, 40, 0.06)",
},
components: {
Card: {
defaultProps: {
radius: "xl",
withBorder: true,
shadow: "none",
padding: "lg",
},
styles: {
root: { borderColor: "#E6ECF2" },
},
},
Button: {
defaultProps: { radius: "md" },
styles: { root: { fontWeight: 600 } },
},
Badge: {
defaultProps: { radius: "xl", variant: "light" },
styles: { root: { fontWeight: 600, textTransform: "none" } },
},
Paper: {
defaultProps: { radius: "xl", shadow: "none", withBorder: true },
styles: { root: { borderColor: "#E6ECF2" } },
},
Table: {
defaultProps: { verticalSpacing: "sm", horizontalSpacing: "md" },
},
Title: {
styles: { root: { letterSpacing: "-0.01em" } },
},
},
fontFamily: "'Outfit', var(--font-sans)",
});