From a9bf332369958e9ba77de19bea3d5e4eb47c14cd Mon Sep 17 00:00:00 2001 From: Josh Wright Date: Tue, 21 Apr 2026 13:29:50 -0400 Subject: [PATCH] Retheme UI from blue to neutral zinc backgrounds with indigo accents Removes the blue tint from all dark-mode surfaces by switching CSS variables to zinc-based neutrals, and replaces decorative blue classes with indigo across buttons, focus rings, tabs, and links. Semantic blue (severity badges, status badges, role badges, timeline markers) is preserved. Co-Authored-By: Claude Opus 4.6 --- client/index.html | 2 +- client/src/components/CTISelect.tsx | 2 +- client/src/index.css | 70 ++++++++++++++--------------- client/src/pages/Login.tsx | 4 +- client/src/pages/MyTickets.tsx | 4 +- client/src/pages/NewTicket.tsx | 4 +- client/src/pages/TicketDetail.tsx | 14 +++--- client/src/pages/admin/CTI.tsx | 12 ++--- client/src/pages/admin/Users.tsx | 8 ++-- 9 files changed, 60 insertions(+), 60 deletions(-) diff --git a/client/index.html b/client/index.html index ced1668..339351b 100644 --- a/client/index.html +++ b/client/index.html @@ -3,7 +3,7 @@ - + diff --git a/client/src/components/CTISelect.tsx b/client/src/components/CTISelect.tsx index 979f8c6..b97c9d4 100644 --- a/client/src/components/CTISelect.tsx +++ b/client/src/components/CTISelect.tsx @@ -24,7 +24,7 @@ export default function CTISelect({ value, onChange, disabled }: CTISelectProps) }; const selectClass = - 'block w-full bg-gray-800 border border-gray-700 text-gray-100 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:opacity-50 disabled:cursor-not-allowed'; + 'block w-full bg-gray-800 border border-gray-700 text-gray-100 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent disabled:opacity-50 disabled:cursor-not-allowed'; return (
diff --git a/client/src/index.css b/client/src/index.css index 4684595..d264e34 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -5,70 +5,70 @@ @layer base { :root { --background: 0 0% 100%; - --foreground: 222.2 84% 4.9%; + --foreground: 240 10% 3.9%; --card: 0 0% 100%; - --card-foreground: 222.2 84% 4.9%; + --card-foreground: 240 10% 3.9%; --popover: 0 0% 100%; - --popover-foreground: 222.2 84% 4.9%; + --popover-foreground: 240 10% 3.9%; - --primary: 221.2 83.2% 53.3%; - --primary-foreground: 210 40% 98%; + --primary: 263 70% 50.4%; + --primary-foreground: 0 0% 98%; - --secondary: 210 40% 96.1%; - --secondary-foreground: 222.2 47.4% 11.2%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; - --muted: 210 40% 96.1%; - --muted-foreground: 215.4 16.3% 46.9%; + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 46.1%; - --accent: 210 40% 96.1%; - --accent-foreground: 222.2 47.4% 11.2%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; --destructive: 0 84.2% 60.2%; - --destructive-foreground: 210 40% 98%; + --destructive-foreground: 0 0% 98%; - --border: 214.3 31.8% 91.4%; - --input: 214.3 31.8% 91.4%; - --ring: 221.2 83.2% 53.3%; + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --ring: 263 70% 50.4%; --radius: 0.5rem; } .dark { - --background: 222.2 84% 4.9%; - --foreground: 210 40% 98%; + --background: 240 10% 3.9%; + --foreground: 0 0% 98%; - --card: 222.2 84% 4.9%; - --card-foreground: 210 40% 98%; + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; - --popover: 222.2 84% 4.9%; - --popover-foreground: 210 40% 98%; + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; - --primary: 217.2 91.2% 59.8%; - --primary-foreground: 222.2 47.4% 11.2%; + --primary: 263 70% 50.4%; + --primary-foreground: 0 0% 98%; - --secondary: 217.2 32.6% 17.5%; - --secondary-foreground: 210 40% 98%; + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; - --muted: 217.2 32.6% 17.5%; - --muted-foreground: 215 20.2% 65.1%; + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; - --accent: 217.2 32.6% 17.5%; - --accent-foreground: 210 40% 98%; + --accent: 240 3.7% 15.9%; + --accent-foreground: 0 0% 98%; --destructive: 0 62.8% 30.6%; - --destructive-foreground: 210 40% 98%; + --destructive-foreground: 0 0% 98%; - --border: 217.2 32.6% 17.5%; - --input: 217.2 32.6% 17.5%; - --ring: 224.3 76.3% 48%; + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --ring: 263 70% 50.4%; } } /* Native select dark option styling */ select option { - background-color: #1f2937; + background-color: #27272a; color: #f3f4f6; } @@ -96,7 +96,7 @@ select option { @apply mt-1 mb-0; } .prose a { - @apply text-blue-400 underline hover:text-blue-300; + @apply text-indigo-400 underline hover:text-indigo-300; } .prose strong { @apply font-semibold; diff --git a/client/src/pages/Login.tsx b/client/src/pages/Login.tsx index 0751cad..26ffc26 100644 --- a/client/src/pages/Login.tsx +++ b/client/src/pages/Login.tsx @@ -30,7 +30,7 @@ export default function Login() { }; const inputClass = - 'w-full bg-gray-800 border border-gray-700 text-gray-100 placeholder-gray-500 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent'; + 'w-full bg-gray-800 border border-gray-700 text-gray-100 placeholder-gray-500 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent'; return (
@@ -70,7 +70,7 @@ export default function Login() { diff --git a/client/src/pages/MyTickets.tsx b/client/src/pages/MyTickets.tsx index c95c942..b3e3024 100644 --- a/client/src/pages/MyTickets.tsx +++ b/client/src/pages/MyTickets.tsx @@ -39,7 +39,7 @@ export default function MyTickets() {
-

+

{ticket.title}

diff --git a/client/src/pages/NewTicket.tsx b/client/src/pages/NewTicket.tsx index e655a3f..be1e9c6 100644 --- a/client/src/pages/NewTicket.tsx +++ b/client/src/pages/NewTicket.tsx @@ -49,7 +49,7 @@ export default function NewTicketModal({ onClose }: NewTicketModalProps) { }; const inputClass = - 'w-full bg-gray-800 border border-gray-700 text-gray-100 placeholder-gray-500 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent'; + 'w-full bg-gray-800 border border-gray-700 text-gray-100 placeholder-gray-500 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent'; const labelClass = 'block text-sm font-medium text-gray-300 mb-1'; const errorClass = 'mt-1 text-xs text-red-400'; @@ -162,7 +162,7 @@ export default function NewTicketModal({ onClose }: NewTicketModalProps) { diff --git a/client/src/pages/TicketDetail.tsx b/client/src/pages/TicketDetail.tsx index bef55fc..c31de7e 100644 --- a/client/src/pages/TicketDetail.tsx +++ b/client/src/pages/TicketDetail.tsx @@ -291,7 +291,7 @@ export default function TicketDetail() { type="text" value={editForm.title} onChange={(e) => setEditForm((f) => ({ ...f, title: e.target.value }))} - className="w-full text-2xl font-bold text-gray-100 bg-transparent border-0 border-b-2 border-blue-500 focus:outline-none pb-1" + className="w-full text-2xl font-bold text-gray-100 bg-transparent border-0 border-b-2 border-indigo-500 focus:outline-none pb-1" autoFocus /> ) : ( @@ -319,7 +319,7 @@ export default function TicketDetail() { onClick={() => setTab(key)} className={`flex items-center gap-2 px-4 py-3.5 text-sm font-medium border-b-2 -mb-px transition-colors ${ tab === key - ? 'border-blue-500 text-blue-400' + ? 'border-indigo-500 text-indigo-400' : 'border-transparent text-gray-500 hover:text-gray-300' }`} > @@ -338,7 +338,7 @@ export default function TicketDetail() { value={editForm.overview} onChange={(e) => setEditForm((f) => ({ ...f, overview: e.target.value }))} rows={12} - className="w-full bg-gray-800 border border-gray-700 text-gray-100 rounded-lg px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 resize-y font-mono" + className="w-full bg-gray-800 border border-gray-700 text-gray-100 rounded-lg px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 resize-y font-mono" />
@@ -426,7 +426,7 @@ export default function TicketDetail() { onClick={() => setPreview(label === 'Preview')} className={`text-xs py-2 border-b-2 -mb-px transition-colors ${ (label === 'Preview') === preview - ? 'border-blue-500 text-blue-400' + ? 'border-indigo-500 text-indigo-400' : 'border-transparent text-gray-500 hover:text-gray-300' }`} > @@ -468,7 +468,7 @@ export default function TicketDetail() { diff --git a/client/src/pages/admin/CTI.tsx b/client/src/pages/admin/CTI.tsx index 00f12f6..73cd354 100644 --- a/client/src/pages/admin/CTI.tsx +++ b/client/src/pages/admin/CTI.tsx @@ -131,7 +131,7 @@ export default function AdminCTI() { const itemClass = (active: boolean) => `flex items-center justify-between px-4 py-2.5 cursor-pointer group transition-colors ${ active - ? 'bg-blue-600/20 border-l-2 border-blue-500' + ? 'bg-indigo-600/20 border-l-2 border-indigo-500' : 'hover:bg-gray-800 border-l-2 border-transparent' }`; @@ -144,7 +144,7 @@ export default function AdminCTI() {

Categories

@@ -199,7 +199,7 @@ export default function AdminCTI() { {selectedCategory && ( @@ -257,7 +257,7 @@ export default function AdminCTI() { {selectedType && ( @@ -314,7 +314,7 @@ export default function AdminCTI() { onChange={(e) => setNameValue(e.target.value)} required autoFocus - className="w-full bg-gray-800 border border-gray-700 text-gray-100 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" + className="w-full bg-gray-800 border border-gray-700 text-gray-100 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent" />
@@ -328,7 +328,7 @@ export default function AdminCTI() { diff --git a/client/src/pages/admin/Users.tsx b/client/src/pages/admin/Users.tsx index 4351ef9..54b1f9e 100644 --- a/client/src/pages/admin/Users.tsx +++ b/client/src/pages/admin/Users.tsx @@ -174,7 +174,7 @@ export default function AdminUsers() { }; const inputClass = - 'w-full bg-gray-800 border border-gray-700 text-gray-100 placeholder-gray-500 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent'; + 'w-full bg-gray-800 border border-gray-700 text-gray-100 placeholder-gray-500 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent'; const labelClass = 'block text-sm font-medium text-gray-300 mb-1'; return ( @@ -183,7 +183,7 @@ export default function AdminUsers() { action={
@@ -371,7 +371,7 @@ export default function AdminUsers() {