From 7afb4829bc052c8392e589f43e67594643c808ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Br=C3=BCckner?= Date: Fri, 5 Jun 2026 11:08:34 +0200 Subject: [PATCH] refactor(ui): comprehensive light mode fixes and dashboard cleanup - Light mode: fix 40+ missing CSS overrides (solid emerald/cyan bg-950, 300-level text colours, border opacity variants, hover states, violet accent, bg-slate-900/30 and /90, bg-rose-950/30, red-950/50) - Light mode: fix broad bg-gradient-to-br override to only target dark banner cards (from-[#1E293B]), preserving coloured user avatar gradients - Light mode: BookingDetailsModal JSON panel switched to GitHub-Light style (bg #f6f8fa) including
 override so the general 'pre' rule cannot
  darken it back
- Dashboard: simplify banner (flat card, no gradient/watermark/time-widget)
- Dashboard: reduce visual noise (shorter titles, remove LIVE animated badge,
  remove italic notes quote, neutral checklist items, no footer jargon)
- Dashboard: normalise section-icon colours to slate-400 except Active (emerald)
- Dashboard: replace non-standard Tailwind classes (slate-101/350/905/1000,
  indigo-405, emerald-990) with valid equivalents
- Dashboard: standardise button style to rounded-lg + text-xs across
  Active Reservations and Upcoming cards; add visible borders on Cancel/Purge
---
 src/components/Dashboard.tsx | 204 ++++++++++---------------
 src/index.css                | 282 ++++++++++++++++++++++++++++++++---
 2 files changed, 340 insertions(+), 146 deletions(-)

diff --git a/src/components/Dashboard.tsx b/src/components/Dashboard.tsx
index 3d6b1ce..7cd3edc 100644
--- a/src/components/Dashboard.tsx
+++ b/src/components/Dashboard.tsx
@@ -65,10 +65,10 @@ export default function Dashboard({
   // Quick state checklist for the user to mark items as done as they test their lab!
   // (kept deliberately nerdy - morale is a critical infrastructure dependency)
   const [todoList, setTodoList] = useState([
-    { id: 't1', text: 'Ping 8.8.8.8 to confirm the Internet still exists', checked: false },
-    { id: 't2', text: 'Coffee level nominal ☕ - packets route faster on caffeine', checked: true },
-    { id: 't3', text: "Rule out DNS first (narrator: it was, in fact, always DNS)", checked: false },
-    { id: 't4', text: 'Layer-1 check: is it actually plugged in? (PEBKAC defense)', checked: false }
+    { id: 't1', text: 'Verify network connectivity (ping gateway)', checked: false },
+    { id: 't2', text: 'Coffee ready ☕', checked: true },
+    { id: 't3', text: 'Check DNS resolution', checked: false },
+    { id: 't4', text: 'Confirm physical connections are in place', checked: false }
   ]);
 
   const toggleTodo = (id: string) => {
@@ -91,58 +91,30 @@ export default function Dashboard({
   return (
     
- {/* Banner Card Grid */} -
-
- NET -
- -
-

- Welcome back, {currentUser.name}! + {/* Banner */} +
+
+

+ Welcome back, {currentUser.name}

-

- Your lab cockpit. Grab some hardware, block a time slot, and keep the rescue runbooks one click away for when a switch decides to packet-storm itself at 16:59 on a Friday. root@ghostgrid:~# have fun, break things (in the lab). +

+ Your lab management hub. Reserve hardware, track active sessions, and keep runbooks close.

- -
- - -
- -
-
- System Time -
- {now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' })} -
-

- {now.toLocaleDateString([], { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' })} -

-
- -
-
- {devices.length} - Hardware Nodes -
-
- {labs.length} - Available Labs -
-
+
+ +
@@ -156,28 +128,16 @@ export default function Dashboard({

- - Active Reservations (your boxes, right now) - - - - - - - LIVE + + Active Reservations +

{activeBookings.length === 0 ? ( -
- -

No boxes checked out right now. idle hands, idle hardware.

- +
+ +

No active sessions.

) : (
@@ -209,28 +169,24 @@ export default function Dashboard({
-

- "{booking.notes || 'no notes - running blind'}" -

- -
+
- Active window: {startF} - {endF} + {startF} – {endF}
@@ -245,13 +201,13 @@ export default function Dashboard({ {/* Upcoming Sessions */}
-

- - Upcoming in the Queue ({upcomingBookings.length}) +

+ + Upcoming ({upcomingBookings.length})

{upcomingBookings.length === 0 ? ( -

Queue is empty. crontab clean, nothing scheduled.

+

No upcoming reservations.

) : (
{upcomingBookings.map((booking) => { @@ -260,14 +216,14 @@ export default function Dashboard({ const startF = new Date(booking.startDateTime).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }); const endF = new Date(booking.endDateTime).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }); return ( -
+
- + {dayStr} - {startF} - {endF} + {startF} – {endF}

{lab?.name}

@@ -276,32 +232,32 @@ export default function Dashboard({

-
+
@@ -316,62 +272,58 @@ export default function Dashboard({ {/* RIGHT COLUMN: Checklist and simulated action panel */}
- {/* Workflows Checklist */} + {/* Lab Checklist */}
-

- - Pre-Flight Checklist (before you blame the network) +

+ + Lab Checklist

- -
+ +
{todoList.map((item) => ( -
toggleTodo(item.id)} - className="flex items-start gap-2.5 p-2 bg-slate-1000/40 hover:bg-slate-900 rounded-lg cursor-pointer transition-all border border-slate-850/60" + className="flex items-start gap-2.5 p-2 bg-slate-900/40 hover:bg-slate-900 rounded-lg cursor-pointer transition-all border border-slate-800/60" > {}} - className="mt-0.5 rounded border-slate-800 text-emerald-500 focus:ring-emerald-450 w-3.5 h-3.5 shrink-0" + className="mt-0.5 rounded border-slate-700 text-emerald-500 w-3.5 h-3.5 shrink-0" /> - + {item.text}
))}
- -
- Works on my machine (TM). check the boxes anyway. -
- {/* Quick Links - shortcut into the shared tooling dashboard */} + {/* Quick Links */}
-

+

- + Quick Links

{links.length === 0 ? ( -
- -

No shared links yet.

+
+ +

No shared links yet.

) : ( @@ -386,23 +338,23 @@ export default function Dashboard({ href={link.url} target="_blank" rel="noopener noreferrer" - className="group flex items-center gap-2.5 p-2 bg-slate-1000/40 hover:bg-slate-900 rounded-lg border border-slate-850/60 hover:border-slate-800 transition-all" + className="group flex items-center gap-2.5 p-2 bg-slate-900/40 hover:bg-slate-900 rounded-lg border border-slate-800/60 hover:border-slate-700 transition-all" > - {link.title} - {host} + {link.title} + {host} - + ); })} {links.length > 6 && ( diff --git a/src/index.css b/src/index.css index 38e34fa..2ce2e6b 100644 --- a/src/index.css +++ b/src/index.css @@ -72,11 +72,11 @@ border-color: var(--border) !important; } -/* Amber-tinted warning/safety card used in Dashboard */ +/* BookingCalendar "Quick Booking" green-tinted card */ :root.light .bg-\[\#1D2535\], :root.light .bg-\[\#1d2535\] { - background-color: #fffbeb !important; - border-color: #fde68a !important; + background-color: #f0fdf4 !important; + border-color: #bbf7d0 !important; } /* ── Header & nav ─────────────────────────────────────────────── */ @@ -128,8 +128,10 @@ background-color: #e9ecf0 !important; } -/* ── Dashboard banner gradient ────────────────────────────────── */ -:root.light .bg-gradient-to-br { +/* ── Dashboard / UserDirectory banner gradients (dark hex only) ── */ +/* Targets only the dark-themed banners, not coloured avatar gradients */ +:root.light .bg-gradient-to-br.from-\[\#1E293B\], +:root.light .bg-gradient-to-br.from-\[\#1e293b\] { background-image: linear-gradient(to bottom right, #ffffff, #f1f5f9) !important; border-color: var(--border) !important; } @@ -155,6 +157,7 @@ } /* ── Borders ──────────────────────────────────────────────────── */ +:root.light .border-slate-900, :root.light .border-slate-800, :root.light .border-slate-850, :root.light .border-slate-855, @@ -164,6 +167,12 @@ border-color: var(--border) !important; } +:root.light .border-red-900\/50, +:root.light .border-red-900\/40, +:root.light .border-red-900\/30 { + border-color: #fca5a5 !important; +} + :root.light .divide-slate-800 > *, :root.light .divide-slate-850 > * { border-color: var(--border) !important; @@ -171,6 +180,9 @@ /* ── Text colours ─────────────────────────────────────────────── */ :root.light .text-white, +:root.light .text-white\/90, +:root.light .text-white\/80, +:root.light .text-white\/70, :root.light .text-slate-100, :root.light .text-slate-200 { color: var(--text) !important; @@ -238,7 +250,13 @@ color: #9f1239 !important; } +:root.light .bg-rose-950\/30, +:root.light .hover\:bg-rose-950\/30:hover { + background-color: #ffe4e6 !important; +} + :root.light .bg-red-950\/60, +:root.light .bg-red-950\/50, :root.light .bg-red-950\/40, :root.light .bg-red-950\/20 { background-color: #fee2e2 !important; @@ -518,33 +536,40 @@ border-color: var(--border) !important; } -/* JSON REST Response panel – always dark (code/terminal aesthetic) */ +/* JSON REST Response panel – GitHub Light style in light mode */ :root.light #booking-details-modal .font-mono.bg-slate-950 { - background-color: #0d1117 !important; - color: #c9d1d9 !important; - border-color: #30363d !important; + background-color: #f6f8fa !important; + color: #24292f !important; + border-color: #d0d7de !important; } -/* Header bar inside the dark JSON panel – keep dark to match the block */ +/* The
 inside inherits the dark pre-rule; override explicitly */
+:root.light #booking-details-modal .font-mono.bg-slate-950 pre {
+  background-color: transparent !important;
+  color: #24292f !important;
+  border-color: transparent !important;
+}
+
+/* Header bar inside the JSON panel */
 :root.light #booking-details-modal .font-mono.bg-slate-950 .bg-slate-900 {
-  background-color: #161b22 !important;
-  border-color: #30363d !important;
+  background-color: #eaeef2 !important;
+  border-color: #d0d7de !important;
 }
 
-/* Title label and icon in dark panel header */
+/* Title label and icon in panel header */
 :root.light #booking-details-modal .font-mono.bg-slate-950 .text-indigo-400 {
-  color: #818cf8 !important;
+  color: #6366f1 !important;
 }
 
-/* Copy button inside dark panel */
+/* Copy button inside panel */
 :root.light #booking-details-modal .font-mono.bg-slate-950 button {
-  background-color: #21262d !important;
-  border-color: #30363d !important;
-  color: #8b949e !important;
+  background-color: #eaeef2 !important;
+  border-color: #d0d7de !important;
+  color: #57606a !important;
 }
 :root.light #booking-details-modal .font-mono.bg-slate-950 button:hover {
-  background-color: #30363d !important;
-  color: #f0f6fc !important;
+  background-color: #d0d7de !important;
+  color: #24292f !important;
 }
 
 /* Ansible status card – orange accent in light mode */
@@ -630,3 +655,220 @@
 :root.light #add-link-btn:hover {
   background-color: #6366f1 !important;
 }
+
+/* ─────────────────────────────────────────────────────────────────── */
+/* EXTENDED LIGHT MODE OVERRIDES                                       */
+/* ─────────────────────────────────────────────────────────────────── */
+
+/* ── Solid (no-opacity) color backgrounds ────────────────────────── */
+/* These are used in Logbook type badges and Dashboard countdown pill */
+
+:root.light .bg-emerald-950 {
+  background-color: #d1fae5 !important;
+  border-color: #6ee7b7 !important;
+  color: #065f46 !important;
+}
+
+:root.light .bg-cyan-950 {
+  background-color: #cffafe !important;
+  border-color: #67e8f9 !important;
+  color: #155e75 !important;
+}
+
+:root.light .bg-indigo-950 {
+  background-color: #e0e7ff !important;
+  border-color: #a5b4fc !important;
+  color: #3730a3 !important;
+}
+
+:root.light .bg-rose-950 {
+  background-color: #ffe4e6 !important;
+  border-color: #fca5a5 !important;
+  color: #9f1239 !important;
+}
+
+/* ── emerald-900 opacity variants (quick booking modal tabs) ──────── */
+:root.light .bg-emerald-900\/50,
+:root.light .bg-emerald-900\/40,
+:root.light .bg-emerald-900\/30 {
+  background-color: #d1fae5 !important;
+}
+
+/* ── Violet accent (LinkDashboard) ────────────────────────────────── */
+:root.light .bg-violet-950\/60,
+:root.light .bg-violet-950\/40,
+:root.light .bg-violet-950\/20 {
+  background-color: #ede9fe !important;
+  border-color: #c4b5fd !important;
+  color: #5b21b6 !important;
+}
+
+:root.light .text-violet-400 {
+  color: #7c3aed !important;
+}
+
+/* ── 300-level text – near-invisible on white backgrounds ────────── */
+:root.light .text-amber-300 {
+  color: #b45309 !important;
+}
+
+:root.light .text-emerald-300 {
+  color: #059669 !important;
+}
+
+:root.light .text-cyan-300 {
+  color: #0891b2 !important;
+}
+
+:root.light .text-rose-300 {
+  color: #be123c !important;
+}
+
+:root.light .text-indigo-300 {
+  color: #4338ca !important;
+}
+
+/* ── Missing border opacity variants ─────────────────────────────── */
+
+/* slate-700 with opacity */
+:root.light .border-slate-700\/40,
+:root.light .border-slate-700\/50,
+:root.light .border-slate-700\/60 {
+  border-color: var(--border) !important;
+}
+
+/* slate-900 opacity (section dividers, row separators) */
+:root.light .border-slate-900\/30,
+:root.light .border-slate-900\/40,
+:root.light .border-slate-900\/60 {
+  border-color: var(--border) !important;
+}
+
+/* emerald borders – solid and opacity variants */
+:root.light .border-emerald-900,
+:root.light .border-emerald-900\/30,
+:root.light .border-emerald-900\/40,
+:root.light .border-emerald-900\/60 {
+  border-color: #6ee7b7 !important;
+}
+
+:root.light .border-emerald-800\/50,
+:root.light .border-emerald-800\/60 {
+  border-color: #a7f3d0 !important;
+}
+
+/* cyan borders */
+:root.light .border-cyan-900\/50,
+:root.light .border-cyan-900\/60 {
+  border-color: #67e8f9 !important;
+}
+
+/* amber borders */
+:root.light .border-amber-900\/40,
+:root.light .border-amber-900\/60 {
+  border-color: #fde68a !important;
+}
+
+:root.light .border-amber-800\/50,
+:root.light .border-amber-800\/60 {
+  border-color: #fde68a !important;
+}
+
+/* rose borders */
+:root.light .border-rose-900\/30,
+:root.light .border-rose-900\/50,
+:root.light .border-rose-900\/60 {
+  border-color: #fca5a5 !important;
+}
+
+/* indigo borders */
+:root.light .border-indigo-900,
+:root.light .border-indigo-900\/40,
+:root.light .border-indigo-900\/50 {
+  border-color: #a5b4fc !important;
+}
+
+/* violet borders */
+:root.light .border-violet-900\/50,
+:root.light .border-violet-950\/40 {
+  border-color: #c4b5fd !important;
+}
+
+/* ── Missing bg-slate-900 opacity variants ───────────────────────── */
+:root.light .bg-slate-900\/30,
+:root.light .bg-slate-900\/50,
+:root.light .bg-slate-900\/70,
+:root.light .bg-slate-900\/90 {
+  background-color: #f1f5f9 !important;
+}
+
+/* ── bg-slate-800 additional variant ────────────────────────────── */
+:root.light .bg-slate-800\/40 {
+  background-color: #e2e8f0 !important;
+}
+
+/* ── Hover-state overrides for dark bg classes ───────────────────── */
+/* Without these the hover flashes a dark background in light mode.  */
+
+:root.light .hover\:bg-slate-900:hover {
+  background-color: #f1f5f9 !important;
+}
+
+:root.light .hover\:bg-slate-900\/35:hover,
+:root.light .hover\:bg-slate-900\/40:hover,
+:root.light .hover\:bg-slate-900\/60:hover,
+:root.light .hover\:bg-slate-900\/70:hover,
+:root.light .hover\:bg-slate-900\/80:hover {
+  background-color: #f1f5f9 !important;
+}
+
+:root.light .hover\:bg-slate-800:hover {
+  background-color: #e2e8f0 !important;
+}
+
+:root.light .hover\:bg-slate-800\/80:hover {
+  background-color: #e2e8f0 !important;
+}
+
+:root.light .hover\:bg-slate-950\/30:hover,
+:root.light .hover\:bg-slate-950\/40:hover {
+  background-color: #f8fafc !important;
+}
+
+/* Coloured hover states */
+:root.light .hover\:bg-emerald-900\/40:hover,
+:root.light .hover\:bg-emerald-900\/60:hover {
+  background-color: #a7f3d0 !important;
+}
+
+:root.light .hover\:bg-rose-900\/60:hover {
+  background-color: #fecdd3 !important;
+}
+
+:root.light .hover\:bg-red-950\/40:hover {
+  background-color: #fee2e2 !important;
+}
+
+/* ── Border-dashed empty slots (calendar grid) ───────────────────── */
+:root.light .border-slate-800\/40 {
+  border-color: var(--border) !important;
+}
+
+:root.light .hover\:border-slate-700\/60:hover {
+  border-color: var(--border-muted) !important;
+}
+
+/* ── Hover text colors – prevent near-white text on light backgrounds */
+:root.light .hover\:text-white:hover,
+:root.light .hover\:text-slate-100:hover,
+:root.light .hover\:text-slate-200:hover {
+  color: var(--text) !important;
+}
+
+:root.light .group:hover .group-hover\:text-white {
+  color: var(--text) !important;
+}
+
+:root.light .group:hover .group-hover\:text-slate-300 {
+  color: var(--text-muted) !important;
+}