mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 00:52:50 +00:00
fix the layout style
This commit is contained in:
@@ -22,7 +22,7 @@ import {
|
||||
Sun,
|
||||
User,
|
||||
} from "lucide-react";
|
||||
import { type CSSProperties, Fragment, type ReactNode, useState } from "react";
|
||||
import { Fragment, type ReactNode, useState } from "react";
|
||||
|
||||
export interface SidebarItem {
|
||||
label: string;
|
||||
@@ -47,18 +47,6 @@ export interface AppLayoutProps {
|
||||
type Theme = "light" | "dark";
|
||||
const THEME_KEY = "edr-theme";
|
||||
|
||||
const EDR = {
|
||||
primary: "#0EA371",
|
||||
primaryDark: "#0A6F4D",
|
||||
soft: "#ECF6F1",
|
||||
border: "#E6ECF2",
|
||||
bg: "#F4F7FA",
|
||||
text: "#10202F",
|
||||
muted: "#6B7C8E",
|
||||
ink: "#0C1A2B",
|
||||
accent: "#F2A516",
|
||||
};
|
||||
|
||||
function getStoredTheme(): Theme {
|
||||
if (typeof window === "undefined") return "light";
|
||||
const stored = localStorage.getItem(THEME_KEY);
|
||||
@@ -94,18 +82,24 @@ function getActivePage(items: SidebarItem[], activePath: string): { label: strin
|
||||
const navClassNames = (active: boolean) => {
|
||||
if (active) {
|
||||
return {
|
||||
root: `rounded-[10px] font-medium transition-all duration-150 bg-[#ECF6F1]! ring-1 ring-inset ring-[#0EA371]/15`,
|
||||
label: `text-[#0A6F4D]! font-bold!`,
|
||||
section: `text-[#0A6F4D]!`,
|
||||
root: "rounded-[10px] font-medium transition-all duration-150 bg-[var(--mantine-color-edr-soft-0)]! ring-1 ring-inset ring-[var(--mantine-color-edr-green-5)]/15",
|
||||
label: "text-[var(--mantine-color-edr-green-7)]! font-bold!",
|
||||
section: "text-[var(--mantine-color-edr-green-7)]!",
|
||||
};
|
||||
}
|
||||
return {
|
||||
root: `rounded-[10px] font-medium transition-all duration-150 hover:bg-[#F1F4F7]!`,
|
||||
label: `text-[#3D4D5C]! font-semibold! hover:text-[#0C1A2B]!`,
|
||||
section: `text-[#54657A]! hover:text-[#0C1A2B]!`,
|
||||
root: "rounded-[10px] font-medium transition-all duration-150 hover:bg-[var(--mantine-color-edr-slate-soft-0)]!",
|
||||
label: "text-[var(--mantine-color-edr-slate-0)]! font-semibold! hover:text-[var(--mantine-color-edr-ink-0)]!",
|
||||
section: "text-[var(--mantine-color-edr-muted-0)]! hover:text-[var(--mantine-color-edr-ink-0)]!",
|
||||
};
|
||||
};
|
||||
|
||||
// 36×36 header control chips
|
||||
const islandCls =
|
||||
"size-9 rounded-full border border-[var(--mantine-color-edr-border-0)] bg-white flex items-center justify-center shrink-0 cursor-pointer";
|
||||
const squareIslandCls =
|
||||
"size-9 rounded-[10px] border border-[var(--mantine-color-edr-border-0)] bg-white flex items-center justify-center shrink-0 cursor-pointer";
|
||||
|
||||
export function AppLayout({
|
||||
title = "EDR Freight",
|
||||
sidebarItems,
|
||||
@@ -139,21 +133,6 @@ export function AppLayout({
|
||||
activePath === item.href.toLowerCase() ||
|
||||
activePath.startsWith(item.href.toLowerCase() + "/");
|
||||
|
||||
// Shared header "island" styles — every control is a consistent 36px chip.
|
||||
const islandStyle: CSSProperties = {
|
||||
width: 36,
|
||||
height: 36,
|
||||
borderRadius: 999,
|
||||
border: `1px solid ${EDR.border}`,
|
||||
backgroundColor: "#fff",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
flexShrink: 0,
|
||||
cursor: "pointer",
|
||||
};
|
||||
const toggleStyle: CSSProperties = { ...islandStyle, borderRadius: 10 };
|
||||
|
||||
return (
|
||||
<AppShell
|
||||
layout="alt"
|
||||
@@ -161,37 +140,27 @@ export function AppLayout({
|
||||
header={{ height: 56 }}
|
||||
padding={0}
|
||||
>
|
||||
{/* ── Header (frosted glass; compact floating islands, mirrors the pen) ── */}
|
||||
{/* ── Header ── */}
|
||||
<AppShell.Header
|
||||
withBorder={false}
|
||||
style={{
|
||||
backdropFilter: "blur(14px)",
|
||||
WebkitBackdropFilter: "blur(14px)",
|
||||
border: "none",
|
||||
background: "transparent",
|
||||
boxShadow: "none",
|
||||
background:'transparent',
|
||||
border: "none",
|
||||
}}
|
||||
>
|
||||
<Group h="100%" px={24} justify="space-between" wrap="nowrap">
|
||||
{/* Left: sidebar toggle + page title */}
|
||||
<Group gap={12} wrap="nowrap" align="center">
|
||||
<UnstyledButton onClick={toggleMobile} style={toggleStyle} aria-label="Toggle sidebar">
|
||||
<MenuIcon size={18} color={EDR.text} strokeWidth={1.8} />
|
||||
<UnstyledButton onClick={toggleMobile} className={squareIslandCls} aria-label="Toggle sidebar">
|
||||
<MenuIcon size={18} color="var(--mantine-color-edr-text-0)" strokeWidth={1.8} />
|
||||
</UnstyledButton>
|
||||
<Text
|
||||
style={{
|
||||
fontFamily: '"Inter", sans-serif',
|
||||
fontSize: 16,
|
||||
fontWeight: 700,
|
||||
color: EDR.text,
|
||||
lineHeight: 1,
|
||||
}}
|
||||
>
|
||||
<Text fw={700} fz="lg" c="edr-text">
|
||||
{activePage ? activePage.label : title}
|
||||
</Text>
|
||||
</Group>
|
||||
|
||||
{/* Right: search + bell + avatar */}
|
||||
<Group gap={10} wrap="nowrap" align="center">
|
||||
{/* Search pill */}
|
||||
<Group
|
||||
@@ -202,22 +171,22 @@ export function AppLayout({
|
||||
width: 260,
|
||||
height: 36,
|
||||
borderRadius: 999,
|
||||
border: `1px solid ${EDR.border}`,
|
||||
backgroundColor: "#fff",
|
||||
border: "1px solid var(--mantine-color-edr-border-0)",
|
||||
backgroundColor: "var(--mantine-color-white)",
|
||||
padding: "0 14px",
|
||||
cursor: "text",
|
||||
}}
|
||||
>
|
||||
<Search size={15} color={EDR.muted} strokeWidth={1.8} />
|
||||
<Text size="sm" style={{ color: EDR.muted, userSelect: "none" }}>
|
||||
<Search size={15} color="var(--mantine-color-edr-muted-0)" strokeWidth={1.8} />
|
||||
<Text size="sm" c="edr-muted" style={{ userSelect: "none" }}>
|
||||
Search shipments, bookings…
|
||||
</Text>
|
||||
</Group>
|
||||
|
||||
{/* Bell */}
|
||||
<Box style={{ position: "relative" }}>
|
||||
<UnstyledButton style={islandStyle} aria-label="Notifications">
|
||||
<Bell size={17} color={EDR.text} strokeWidth={1.8} />
|
||||
<UnstyledButton className={islandCls} aria-label="Notifications">
|
||||
<Bell size={17} color="var(--mantine-color-edr-text-0)" strokeWidth={1.8} />
|
||||
</UnstyledButton>
|
||||
<Box
|
||||
style={{
|
||||
@@ -227,30 +196,30 @@ export function AppLayout({
|
||||
width: 7,
|
||||
height: 7,
|
||||
borderRadius: "50%",
|
||||
backgroundColor: EDR.accent,
|
||||
border: "1.5px solid #fff",
|
||||
backgroundColor: "var(--mantine-color-edr-accent-0)",
|
||||
border: "1.5px solid var(--mantine-color-white)",
|
||||
pointerEvents: "none",
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{enableThemeToggle && (
|
||||
<UnstyledButton onClick={toggleTheme} style={islandStyle} aria-label="Toggle theme">
|
||||
<UnstyledButton onClick={toggleTheme} className={islandCls} aria-label="Toggle theme">
|
||||
{theme === "dark"
|
||||
? <Sun size={17} color={EDR.text} strokeWidth={1.8} />
|
||||
: <Moon size={17} color={EDR.text} strokeWidth={1.8} />}
|
||||
? <Sun size={17} color="var(--mantine-color-edr-text-0)" strokeWidth={1.8} />
|
||||
: <Moon size={17} color="var(--mantine-color-edr-text-0)" strokeWidth={1.8} />}
|
||||
</UnstyledButton>
|
||||
)}
|
||||
|
||||
{/* Avatar pill */}
|
||||
{/* Avatar dropdown */}
|
||||
<Menu width={220} position="bottom-end" withinPortal shadow="md" offset={8} radius="md">
|
||||
<Menu.Target>
|
||||
<UnstyledButton
|
||||
style={{
|
||||
height: 36,
|
||||
borderRadius: 999,
|
||||
border: `1px solid ${EDR.border}`,
|
||||
backgroundColor: "#fff",
|
||||
border: "1px solid var(--mantine-color-edr-border-0)",
|
||||
backgroundColor: "var(--mantine-color-white)",
|
||||
padding: "0 10px 0 4px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
@@ -261,13 +230,12 @@ export function AppLayout({
|
||||
<Avatar radius="xl" size={28} color="edr-green.5">
|
||||
<Text fw={700} fz={12} c="white">{initials}</Text>
|
||||
</Avatar>
|
||||
<ChevronDown size={15} color={EDR.muted} strokeWidth={1.8} />
|
||||
<ChevronDown size={15} color="var(--mantine-color-edr-muted-0)" strokeWidth={1.8} />
|
||||
</UnstyledButton>
|
||||
</Menu.Target>
|
||||
|
||||
<Menu.Dropdown>
|
||||
<Box px="sm" py="xs">
|
||||
<Text size="sm" fw={600} truncate style={{ color: EDR.text }}>{userName}</Text>
|
||||
<Text size="sm" fw={600} truncate c="edr-text">{userName}</Text>
|
||||
{userEmail && <Text size="xs" c="dimmed" truncate>{userEmail}</Text>}
|
||||
</Box>
|
||||
<Divider />
|
||||
@@ -287,49 +255,33 @@ export function AppLayout({
|
||||
<AppShell.Navbar
|
||||
withBorder={false}
|
||||
style={{
|
||||
backgroundColor: "#ffffff",
|
||||
borderRight: `1px solid ${EDR.border}`,
|
||||
backgroundColor: "var(--mantine-color-white)",
|
||||
borderRight: "1px solid var(--mantine-color-edr-border-0)",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
{/* Brand */}
|
||||
<Box
|
||||
style={{
|
||||
height: 60,
|
||||
flexShrink: 0,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
padding: "0 18px",
|
||||
}}
|
||||
>
|
||||
<Box className="h-[60px] shrink-0 flex items-center px-[18px]">
|
||||
<Group gap={11} wrap="nowrap">
|
||||
<img
|
||||
src="/assets/edr-logo.png"
|
||||
alt="EDR"
|
||||
style={{ width: 40, height: 40, objectFit: "contain", flexShrink: 0 }}
|
||||
className="size-10 object-contain shrink-0"
|
||||
/>
|
||||
<Box>
|
||||
<Text
|
||||
fw={800}
|
||||
style={{
|
||||
fontFamily: '"Inter", sans-serif',
|
||||
fontWeight: 800,
|
||||
fontSize: 19,
|
||||
letterSpacing: "0.03em",
|
||||
color: EDR.primary,
|
||||
color: "var(--mantine-color-edr-green-5)",
|
||||
lineHeight: 1.15,
|
||||
}}
|
||||
>
|
||||
EDR FREIGHT
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 10.5,
|
||||
fontWeight: 500,
|
||||
color: EDR.muted,
|
||||
lineHeight: 1.2,
|
||||
}}
|
||||
>
|
||||
<Text fz={10.5} fw={500} c="edr-muted" style={{ lineHeight: 1.2 }}>
|
||||
Ethio–Djibouti Railway
|
||||
</Text>
|
||||
</Box>
|
||||
@@ -350,17 +302,13 @@ export function AppLayout({
|
||||
item.section && item.section !== prevSection ? (
|
||||
<Text
|
||||
key={`section-${item.section}`}
|
||||
size="xs"
|
||||
fz={11}
|
||||
tt="uppercase"
|
||||
px="sm"
|
||||
mt={i === 0 ? 4 : "md"}
|
||||
mb={4}
|
||||
style={{
|
||||
fontWeight: 600,
|
||||
letterSpacing: "0.08em",
|
||||
color: EDR.muted,
|
||||
fontSize: 11,
|
||||
}}
|
||||
c="edr-muted"
|
||||
style={{ fontWeight: 600, letterSpacing: "0.08em" }}
|
||||
>
|
||||
{item.section}
|
||||
</Text>
|
||||
@@ -421,42 +369,38 @@ export function AppLayout({
|
||||
marginBottom: 10,
|
||||
}}
|
||||
>
|
||||
{/* Train image fills the full card */}
|
||||
<img
|
||||
src="/assets/train-edr.jpg"
|
||||
alt=""
|
||||
style={{
|
||||
position: "absolute",
|
||||
bottom:"-16px",
|
||||
left:0,
|
||||
right:"-70px",
|
||||
bottom: "-16px",
|
||||
left: 0,
|
||||
right: "-70px",
|
||||
width: "120%",
|
||||
objectFit: "cover",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Diagonal green overlay: lower-left → upper-right cut */}
|
||||
<Box
|
||||
style={{
|
||||
position: "absolute",
|
||||
inset: 0,
|
||||
top:"-75%",
|
||||
background: "linear-gradient(165deg, #006149 40%, #0DC9A4 70%, #0DC9A402 80%)",
|
||||
top: "-75%",
|
||||
background: "linear-gradient(165deg, #006149 40%, #0DC9A4 70%, #0DC9A402 80%)",
|
||||
clipPath: "polygon(0 0, 100% 0, 100% 58%, 0 72%)",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Text sits on top of the green overlay */}
|
||||
<Box style={{ position: "relative", zIndex: 1, padding: "16px 16px 0" }} className="max-w-[180px]">
|
||||
<Text style={{ fontSize: 15, fontWeight: 800, color: "#fff", lineHeight: 1.3, marginBottom: 4 }}>
|
||||
<Box
|
||||
style={{ position: "relative", zIndex: 1, padding: "16px 16px 0" }}
|
||||
className="max-w-[180px]"
|
||||
>
|
||||
<Text fw={800} style={{ fontSize: 15, color: "#fff", lineHeight: 1.3, marginBottom: 4 }}>
|
||||
Moving Africa Forward
|
||||
</Text>
|
||||
<Text style={{ fontSize: 11, color: "rgba(255,255,255,0.7)", lineHeight: 1.5 }}>
|
||||
Reliable. Efficient. Connected.
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
{/* Learn More — visible on the image area */}
|
||||
<Box
|
||||
style={{
|
||||
position: "absolute",
|
||||
@@ -466,22 +410,24 @@ export function AppLayout({
|
||||
display: "inline-flex",
|
||||
alignItems: "center",
|
||||
gap: 5,
|
||||
backgroundColor: "#fff",
|
||||
backgroundColor: "var(--mantine-color-white)",
|
||||
borderRadius: 8,
|
||||
padding: "6px 12px",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
>
|
||||
<Text style={{ fontSize: 12, fontWeight: 600, color: EDR.primaryDark }}>Learn More</Text>
|
||||
<span style={{ fontSize: 12, color: EDR.primaryDark }}>→</span>
|
||||
<Text fw={600} style={{ fontSize: 12, color: "var(--mantine-color-edr-green-7)" }}>
|
||||
Learn More
|
||||
</Text>
|
||||
<span style={{ fontSize: 12, color: "var(--mantine-color-edr-green-7)" }}>→</span>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Profile */}
|
||||
{/* Profile footer */}
|
||||
<Box
|
||||
style={{
|
||||
borderRadius: 12,
|
||||
border: `1px solid ${EDR.border}`,
|
||||
border: "1px solid var(--mantine-color-edr-border-0)",
|
||||
padding: "10px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
@@ -489,25 +435,20 @@ export function AppLayout({
|
||||
cursor: "pointer",
|
||||
}}
|
||||
>
|
||||
<Avatar
|
||||
radius="xl"
|
||||
size={38}
|
||||
color="edr-green.5"
|
||||
style={{ flexShrink: 0 }}
|
||||
>
|
||||
<Avatar radius="xl" size={38} color="edr-green.5" style={{ flexShrink: 0 }}>
|
||||
<Text fw={600} fz={13} c="white">{initials}</Text>
|
||||
</Avatar>
|
||||
<Box style={{ minWidth: 0, flex: 1 }}>
|
||||
<Text size="sm" fw={600} truncate style={{ color: EDR.text, lineHeight: 1.3 }}>
|
||||
<Text size="sm" fw={600} truncate c="edr-text" style={{ lineHeight: 1.3 }}>
|
||||
{userName}
|
||||
</Text>
|
||||
{userEmail && (
|
||||
<Text size="xs" truncate style={{ color: EDR.muted, lineHeight: 1.3 }}>
|
||||
<Text size="xs" truncate c="edr-muted" style={{ lineHeight: 1.3 }}>
|
||||
{userEmail}
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
<ChevronDown size={16} color={EDR.muted} style={{ flexShrink: 0 }} />
|
||||
<ChevronDown size={16} color="var(--mantine-color-edr-muted-0)" style={{ flexShrink: 0 }} />
|
||||
</Box>
|
||||
</Box>
|
||||
</AppShell.Navbar>
|
||||
@@ -515,7 +456,7 @@ export function AppLayout({
|
||||
{/* ── Main ── */}
|
||||
<AppShell.Main
|
||||
style={{
|
||||
backgroundColor: EDR.bg,
|
||||
backgroundColor: "var(--mantine-color-edr-bg-0)",
|
||||
backgroundImage:
|
||||
"radial-gradient(58% 42% at 100% 0%, rgba(14,163,113,0.16) 0%, rgba(14,163,113,0.06) 38%, rgba(14,163,113,0) 72%)",
|
||||
backgroundRepeat: "no-repeat",
|
||||
|
||||
Reference in New Issue
Block a user