mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-09 03:38:17 +00:00
style: some clean up
This commit is contained in:
@@ -87,7 +87,12 @@ const FreightDashboardHeader = ({
|
|||||||
<Text
|
<Text
|
||||||
fw={700}
|
fw={700}
|
||||||
truncate
|
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}
|
{pageMeta.title}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -120,13 +125,6 @@ const FreightDashboardHeader = ({
|
|||||||
</button>
|
</button>
|
||||||
</Tooltip>
|
</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}>
|
<Tooltip label="Notifications" withArrow openDelay={300}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -189,7 +187,12 @@ const FreightDashboardHeader = ({
|
|||||||
<div className="fdh-avatar">{initials}</div>
|
<div className="fdh-avatar">{initials}</div>
|
||||||
</div>
|
</div>
|
||||||
<Stack gap={0} style={{ minWidth: 0 }}>
|
<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}
|
{userName}
|
||||||
</Text>
|
</Text>
|
||||||
{userEmail && (
|
{userEmail && (
|
||||||
|
|||||||
@@ -65,25 +65,24 @@ const FreightDashboardLayout = ({
|
|||||||
|
|
||||||
return (
|
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}>
|
<MantineProvider theme={freightMantineTheme}>
|
||||||
<Box
|
<Box
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
height: "100dvh",
|
height: "100dvh",
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
background: "var(--mantine-color-gray-1)",
|
|
||||||
padding: "0px",
|
padding: "0px",
|
||||||
fontFamily: "'Outfit', var(--font-sans)",
|
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
|
<FreightSidebar
|
||||||
sections={sidebarSections}
|
sections={sidebarSections}
|
||||||
activeHref={activeHref}
|
activeHref={activeHref}
|
||||||
@@ -98,49 +97,21 @@ const FreightDashboardLayout = ({
|
|||||||
minWidth: 0,
|
minWidth: 0,
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
gap: "8px",
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Paper
|
<FreightDashboardHeader
|
||||||
p={0}
|
pageMeta={pageMeta}
|
||||||
radius="lg"
|
headerRight={headerRight}
|
||||||
withBorder
|
enableThemeToggle={enableThemeToggle}
|
||||||
style={{
|
userName={userName}
|
||||||
flexShrink: 0,
|
userEmail={userEmail}
|
||||||
background: "white",
|
userInitials={userInitials}
|
||||||
border: "1px solid var(--mantine-color-gray-2)",
|
onLogout={onLogout}
|
||||||
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.05)",
|
theme={theme}
|
||||||
}}
|
onToggleTheme={toggleTheme}
|
||||||
>
|
/>
|
||||||
<FreightDashboardHeader
|
|
||||||
pageMeta={pageMeta}
|
|
||||||
headerRight={headerRight}
|
|
||||||
enableThemeToggle={enableThemeToggle}
|
|
||||||
userName={userName}
|
|
||||||
userEmail={userEmail}
|
|
||||||
userInitials={userInitials}
|
|
||||||
onLogout={onLogout}
|
|
||||||
theme={theme}
|
|
||||||
onToggleTheme={toggleTheme}
|
|
||||||
/>
|
|
||||||
</Paper>
|
|
||||||
|
|
||||||
<Paper
|
{children}
|
||||||
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>
|
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -8,12 +8,7 @@
|
|||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
width: 280px;
|
width: 280px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
border-radius: 16px;
|
border-radius: 12px;
|
||||||
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);
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -36,8 +31,9 @@
|
|||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background:
|
background: radial-gradient(120px 80px at 24px 18px,
|
||||||
radial-gradient(120px 80px at 24px 18px, rgba(34, 197, 94, 0.08), transparent 70%);
|
rgba(34, 197, 94, 0.08),
|
||||||
|
transparent 70%);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +46,7 @@
|
|||||||
width: 44px;
|
width: 44px;
|
||||||
height: 44px;
|
height: 44px;
|
||||||
border-radius: 13px;
|
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:
|
box-shadow:
|
||||||
0 6px 16px -4px rgba(27, 158, 122, 0.45),
|
0 6px 16px -4px rgba(27, 158, 122, 0.45),
|
||||||
inset 0 1px 0 rgba(255, 255, 255, 0.25);
|
inset 0 1px 0 rgba(255, 255, 255, 0.25);
|
||||||
@@ -72,13 +68,16 @@
|
|||||||
.fsb-nav::-webkit-scrollbar {
|
.fsb-nav::-webkit-scrollbar {
|
||||||
width: 6px;
|
width: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fsb-nav::-webkit-scrollbar-thumb {
|
.fsb-nav::-webkit-scrollbar-thumb {
|
||||||
background: #e2e8f0;
|
background: #e2e8f0;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fsb-nav::-webkit-scrollbar-thumb:hover {
|
.fsb-nav::-webkit-scrollbar-thumb:hover {
|
||||||
background: #cbd5e1;
|
background: #cbd5e1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fsb-nav::-webkit-scrollbar-track {
|
.fsb-nav::-webkit-scrollbar-track {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
@@ -121,12 +120,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.fsb-item[data-active="true"] {
|
.fsb-item[data-active="true"] {
|
||||||
background: linear-gradient(
|
background: linear-gradient(135deg,
|
||||||
135deg,
|
rgba(34, 197, 94, 0.12) 0%,
|
||||||
rgba(34, 197, 94, 0.12) 0%,
|
rgba(27, 158, 122, 0.06) 100%);
|
||||||
rgba(27, 158, 122, 0.06) 100%
|
color: #1b9e7a;
|
||||||
);
|
|
||||||
color: #1B9E7A;
|
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +136,7 @@
|
|||||||
width: 3px;
|
width: 3px;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
border-radius: 0 4px 4px 0;
|
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 {
|
.fsb-item-label {
|
||||||
@@ -155,8 +152,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 31px;
|
|
||||||
height: 31px;
|
|
||||||
border-radius: 9px;
|
border-radius: 9px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
background: #f1f5f9;
|
background: #f1f5f9;
|
||||||
@@ -164,13 +159,19 @@
|
|||||||
transition: all 160ms ease;
|
transition: all 160ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- Icon well ---- */
|
||||||
|
.fsb-icon svg {
|
||||||
|
height: 24px;
|
||||||
|
width: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
.fsb-item:hover .fsb-icon {
|
.fsb-item:hover .fsb-icon {
|
||||||
background: #e6ebf1;
|
background: #e6ebf1;
|
||||||
color: #334155;
|
color: #334155;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fsb-item[data-active="true"] .fsb-icon {
|
.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;
|
color: #ffffff;
|
||||||
box-shadow: 0 5px 12px -2px rgba(27, 158, 122, 0.45);
|
box-shadow: 0 5px 12px -2px rgba(27, 158, 122, 0.45);
|
||||||
}
|
}
|
||||||
@@ -219,9 +220,11 @@
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
transition: background-color 150ms ease;
|
transition: background-color 150ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fsb-group:hover {
|
.fsb-group:hover {
|
||||||
background-color: #f5f7fa;
|
background-color: #f5f7fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fsb-group-label {
|
.fsb-group-label {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
@@ -229,8 +232,9 @@
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: #94a3b8;
|
color: #94a3b8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fsb-group[data-active="true"] .fsb-group-label {
|
.fsb-group[data-active="true"] .fsb-group-label {
|
||||||
color: #1B9E7A;
|
color: #1b9e7a;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* child leaf */
|
/* child leaf */
|
||||||
@@ -251,12 +255,14 @@
|
|||||||
background-color 150ms ease,
|
background-color 150ms ease,
|
||||||
color 150ms ease;
|
color 150ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fsb-child:hover {
|
.fsb-child:hover {
|
||||||
background-color: #f5f7fa;
|
background-color: #f5f7fa;
|
||||||
color: #0f172a;
|
color: #0f172a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fsb-child[data-active="true"] {
|
.fsb-child[data-active="true"] {
|
||||||
color: #1B9E7A;
|
color: #1b9e7a;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
background-color: rgba(27, 158, 122, 0.08);
|
background-color: rgba(27, 158, 122, 0.08);
|
||||||
}
|
}
|
||||||
@@ -269,11 +275,13 @@
|
|||||||
background: #cbd5e1;
|
background: #cbd5e1;
|
||||||
transition: all 150ms ease;
|
transition: all 150ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fsb-child:hover .fsb-dot {
|
.fsb-child:hover .fsb-dot {
|
||||||
background: #94a3b8;
|
background: #94a3b8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fsb-child[data-active="true"] .fsb-dot {
|
.fsb-child[data-active="true"] .fsb-dot {
|
||||||
background: #1B9E7A;
|
background: #1b9e7a;
|
||||||
box-shadow: 0 0 0 3px rgba(27, 158, 122, 0.16);
|
box-shadow: 0 0 0 3px rgba(27, 158, 122, 0.16);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,36 +291,41 @@
|
|||||||
padding: 12px;
|
padding: 12px;
|
||||||
border-top: 1px solid #f1f5f9;
|
border-top: 1px solid #f1f5f9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fsb-status {
|
.fsb-status {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
padding: 10px 12px;
|
padding: 10px 12px;
|
||||||
border-radius: 11px;
|
border-radius: 11px;
|
||||||
background: linear-gradient(135deg, #E7F8F2 0%, #f8fafc 100%);
|
background: linear-gradient(135deg, #e7f8f2 0%, #f8fafc 100%);
|
||||||
border: 1px solid #e7f3ec;
|
border: 1px solid #e7f3ec;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fsb-pulse {
|
.fsb-pulse {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 9px;
|
width: 9px;
|
||||||
height: 9px;
|
height: 9px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: #2DBF95;
|
background: #2dbf95;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fsb-pulse::after {
|
.fsb-pulse::after {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: #2DBF95;
|
background: #2dbf95;
|
||||||
animation: fsb-pulse 2s ease-out infinite;
|
animation: fsb-pulse 2s ease-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fsb-pulse {
|
@keyframes fsb-pulse {
|
||||||
0% {
|
0% {
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
transform: scale(2.6);
|
transform: scale(2.6);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { Box, Stack, Text } from "@mantine/core";
|
|||||||
|
|
||||||
import type { SidebarItem, SidebarSection } from "./types";
|
import type { SidebarItem, SidebarSection } from "./types";
|
||||||
import "./FreightSidebar.css";
|
import "./FreightSidebar.css";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
export interface FreightSidebarProps {
|
export interface FreightSidebarProps {
|
||||||
sections: SidebarSection[];
|
sections: SidebarSection[];
|
||||||
@@ -176,20 +177,7 @@ const FreightSidebar = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box key={item.href}>
|
<Box key={item.href}>
|
||||||
<a
|
<Link to={item.href} className="fsb-item" data-active={isActive}>
|
||||||
href={item.href}
|
|
||||||
className="fsb-item"
|
|
||||||
data-active={isActive}
|
|
||||||
onClick={(e) => {
|
|
||||||
if (hasChildren) {
|
|
||||||
setExpanded((current) => ({
|
|
||||||
...current,
|
|
||||||
[item.href!]: true,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
navigateTo(e, item.href!);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{item.icon && <span className="fsb-icon">{item.icon}</span>}
|
{item.icon && <span className="fsb-icon">{item.icon}</span>}
|
||||||
<span className="fsb-item-label">{item.label}</span>
|
<span className="fsb-item-label">{item.label}</span>
|
||||||
{hasChildren && (
|
{hasChildren && (
|
||||||
@@ -212,7 +200,7 @@ const FreightSidebar = ({
|
|||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</a>
|
</Link>
|
||||||
|
|
||||||
{hasChildren && isOpen && (
|
{hasChildren && isOpen && (
|
||||||
<div className="fsb-branch">
|
<div className="fsb-branch">
|
||||||
@@ -224,7 +212,16 @@ const FreightSidebar = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
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-brand">
|
||||||
<div className="fsb-logo">
|
<div className="fsb-logo">
|
||||||
<Train size={23} color="white" strokeWidth={2.1} />
|
<Train size={23} color="white" strokeWidth={2.1} />
|
||||||
@@ -233,7 +230,11 @@ const FreightSidebar = ({
|
|||||||
<Text
|
<Text
|
||||||
size="md"
|
size="md"
|
||||||
fw={700}
|
fw={700}
|
||||||
style={{ letterSpacing: "-0.3px", lineHeight: 1.2, color: "#0f172a" }}
|
style={{
|
||||||
|
letterSpacing: "-0.3px",
|
||||||
|
lineHeight: 1.2,
|
||||||
|
color: "#0f172a",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
EDR Freight
|
EDR Freight
|
||||||
</Text>
|
</Text>
|
||||||
@@ -257,20 +258,6 @@ const FreightSidebar = ({
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</nav>
|
</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>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,15 @@
|
|||||||
import { type FormEvent, useState } from "react";
|
import { type FormEvent, useState } from "react";
|
||||||
import { parsePhoneNumberFromString } from "libphonenumber-js";
|
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 { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { useAuth } from "@/auth/useAuth";
|
import { useAuth } from "@/auth/useAuth";
|
||||||
@@ -13,10 +22,25 @@ const loginModes: Array<{
|
|||||||
icon: typeof Mail;
|
icon: typeof Mail;
|
||||||
placeholder: string;
|
placeholder: string;
|
||||||
}> = [
|
}> = [
|
||||||
{ value: "email", label: "Email", icon: Mail, placeholder: "name@company.com" },
|
{
|
||||||
{ value: "phone", label: "Phone", icon: Smartphone, placeholder: "09XXXXXXXX" },
|
value: "email",
|
||||||
{ value: "username", label: "Username", icon: UserRound, placeholder: "username" },
|
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 emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
const usernamePattern = /^[a-zA-Z0-9._-]{3,32}$/;
|
const usernamePattern = /^[a-zA-Z0-9._-]{3,32}$/;
|
||||||
@@ -43,7 +67,9 @@ const normalizeIdentifier = (mode: LoginMode, value: string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!usernamePattern.test(trimmed)) {
|
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;
|
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";
|
"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 = () => (
|
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
|
<svg
|
||||||
className="absolute -bottom-24 -left-24 h-[420px] w-[420px] text-white/[0.07]"
|
className="absolute -bottom-24 -left-24 h-[420px] w-[420px] text-white/[0.07]"
|
||||||
viewBox="0 0 400 400"
|
viewBox="0 0 400 400"
|
||||||
fill="none"
|
fill="none"
|
||||||
>
|
>
|
||||||
{[0, 1, 2, 3, 4, 5].map((ring) => (
|
{[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>
|
</svg>
|
||||||
<div className="absolute right-0 top-0 h-40 w-40 rounded-full bg-white/[0.06] blur-2xl" />
|
<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 = () => (
|
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 -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" />
|
<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>
|
<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" />
|
<circle cx="1" cy="1" r="0.75" fill="currentColor" />
|
||||||
</pattern>
|
</pattern>
|
||||||
</defs>
|
</defs>
|
||||||
@@ -99,7 +146,11 @@ const LeftPanel = () => (
|
|||||||
<LeftPanelDecor />
|
<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">
|
<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
|
<a
|
||||||
href="#"
|
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"
|
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>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm leading-relaxed text-white/85">
|
<p className="text-sm leading-relaxed text-white/85">
|
||||||
Sign in to manage bookings, track cargo, and run logistics operations on the
|
Sign in to manage bookings, track cargo, and run logistics operations
|
||||||
Ethio Djibouti Railway freight platform.
|
on the Ethio Djibouti Railway freight platform.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</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">
|
<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>
|
<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">
|
<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
|
Terms & Conditions
|
||||||
</a>
|
</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
|
Privacy Policy
|
||||||
</a>
|
</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
|
Help & Support
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -176,7 +236,7 @@ const LoginPage = () => {
|
|||||||
setNormalizedIdentifier(normalized);
|
setNormalizedIdentifier(normalized);
|
||||||
|
|
||||||
const result = await login({ email: normalized, password });
|
const result = await login({ email: normalized, password });
|
||||||
console.log(result)
|
console.log(result);
|
||||||
if (result.mfaRequired) {
|
if (result.mfaRequired) {
|
||||||
setNeedsMfa(true);
|
setNeedsMfa(true);
|
||||||
return;
|
return;
|
||||||
@@ -212,15 +272,20 @@ const LoginPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-4 space-y-1.5 text-center sm:mb-5">
|
<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">
|
<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>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex w-full flex-col gap-4">
|
<div className="flex w-full flex-col gap-4">
|
||||||
<div className="space-y-1.5">
|
<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">
|
<div className="relative">
|
||||||
<select
|
<select
|
||||||
value={mode}
|
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"
|
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"}
|
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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</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 ? (
|
{error ? (
|
||||||
<div className="rounded-lg border border-red-200 bg-red-50 px-3 py-2.5 text-sm text-red-700">
|
<div className="rounded-lg border border-red-200 bg-red-50 px-3 py-2.5 text-sm text-red-700">
|
||||||
{error}
|
{error}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<button type="submit" disabled={submitting} className={primaryButtonClass}>
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={submitting}
|
||||||
|
className={primaryButtonClass}
|
||||||
|
>
|
||||||
{submitting ? "Signing in..." : "Sign In"}
|
{submitting ? "Signing in..." : "Sign In"}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -318,8 +377,10 @@ const LoginPage = () => {
|
|||||||
</h1>
|
</h1>
|
||||||
<p className="text-sm leading-relaxed text-gray-500">
|
<p className="text-sm leading-relaxed text-gray-500">
|
||||||
We sent a verification code to{" "}
|
We sent a verification code to{" "}
|
||||||
<span className="font-medium text-gray-700">{normalizedIdentifier}</span>. Enter it below
|
<span className="font-medium text-gray-700">
|
||||||
to complete sign in.
|
{normalizedIdentifier}
|
||||||
|
</span>
|
||||||
|
. Enter it below to complete sign in.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -354,7 +415,11 @@ const LoginPage = () => {
|
|||||||
>
|
>
|
||||||
Back
|
Back
|
||||||
</button>
|
</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"}
|
{submitting ? "Verifying..." : "Verify"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import { createTheme, type MantineColorsTuple } from "@mantine/core";
|
import {
|
||||||
|
colorsTuple,
|
||||||
|
createTheme,
|
||||||
|
type MantineColorsTuple,
|
||||||
|
} from "@mantine/core";
|
||||||
|
|
||||||
/** EDR Freight primary brand green */
|
/** EDR Freight primary brand green */
|
||||||
export const FREIGHT_BRAND = "#1B9E7A";
|
export const FREIGHT_BRAND = "#1B9E7A";
|
||||||
@@ -17,24 +21,155 @@ export const freightBrand = {
|
|||||||
mutedBorder: "#B7EBDC",
|
mutedBorder: "#B7EBDC",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
/** Mantine green scale with #1B9E7A at index 6 (filled buttons, nav active). */
|
const edrGreen: MantineColorsTuple = [
|
||||||
const freightGreen: MantineColorsTuple = [
|
"#ecfdf5",
|
||||||
"#E7F8F2",
|
"#d1fae5",
|
||||||
"#C5EFE1",
|
"#a7f3d0",
|
||||||
"#9CE4CD",
|
"#6ee7b7",
|
||||||
"#6BD6B5",
|
"#34d399",
|
||||||
"#41C8A0",
|
"#0EA371",
|
||||||
"#25B58C",
|
"#0A8A5F",
|
||||||
FREIGHT_BRAND,
|
"#0A6F4D",
|
||||||
FREIGHT_BRAND_DARK,
|
"#065f46",
|
||||||
"#105F47",
|
"#064e3b",
|
||||||
"#0A3D2E",
|
];
|
||||||
|
|
||||||
|
const neutral: MantineColorsTuple = [
|
||||||
|
"#F4F7FA",
|
||||||
|
"#eef2f7",
|
||||||
|
"#E6ECF2",
|
||||||
|
"#d0dae6",
|
||||||
|
"#b0bfce",
|
||||||
|
"#8fa0b2",
|
||||||
|
"#6B7C8E",
|
||||||
|
"#4b5a6a",
|
||||||
|
"#10202F",
|
||||||
|
"#0C1A2B",
|
||||||
];
|
];
|
||||||
|
|
||||||
export const freightMantineTheme = createTheme({
|
export const freightMantineTheme = createTheme({
|
||||||
primaryColor: "green",
|
|
||||||
colors: {
|
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)",
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user