refactor: replace hardcoded hex values with Tailwind semantic tokens

3,200+ hardcoded color values replaced with CSS variable-backed
Tailwind classes (bg-card, text-foreground, border-border, etc.).
Enables light mode via CSS variable swap. Only syntax highlighting
colors and intentional one-offs remain hardcoded (~15 values).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-03-22 04:34:35 -04:00
parent 123fc50af9
commit 303a558432
251 changed files with 3310 additions and 3310 deletions

View File

@@ -80,7 +80,7 @@ export function AppLayout() {
<button
type="button"
onClick={() => setMobileMenuOpen(true)}
className="fixed left-4 top-3.5 z-50 rounded-lg p-2 text-[#848b9b] hover:bg-[#14161d] hover:text-[#e2e5eb] transition-colors md:hidden"
className="fixed left-4 top-3.5 z-50 rounded-lg p-2 text-muted-foreground hover:bg-card hover:text-foreground transition-colors md:hidden"
aria-label="Open menu"
>
<Menu size={20} />
@@ -101,12 +101,12 @@ export function AppLayout() {
<div className="flex h-14 items-center justify-between px-4" style={{ borderBottom: '1px solid #1e2130' }}>
<Link to="/" className="flex items-center gap-2.5">
<BrandLogo size="sm" />
<span className="text-sm font-heading font-bold text-[#f0f2f5]">ResolutionFlow</span>
<span className="text-sm font-heading font-bold text-text-heading">ResolutionFlow</span>
</Link>
<button
type="button"
onClick={() => setMobileMenuOpen(false)}
className="rounded-lg p-2 text-[#848b9b] hover:bg-[#14161d] hover:text-[#e2e5eb]"
className="rounded-lg p-2 text-muted-foreground hover:bg-card hover:text-foreground"
aria-label="Close menu"
>
<X size={18} />
@@ -116,9 +116,9 @@ export function AppLayout() {
<div className="flex flex-col p-3">
{/* User info */}
<div className="mb-3 pb-3 px-3" style={{ borderBottom: '1px solid #1e2130' }}>
<p className="text-sm font-medium text-[#e2e5eb]">{user?.name || user?.email}</p>
<p className="text-sm font-medium text-foreground">{user?.name || user?.email}</p>
{effectiveRole && effectiveRole !== 'engineer' && (
<span className="mt-1 inline-flex items-center gap-1 text-xs text-[#848b9b]">
<span className="mt-1 inline-flex items-center gap-1 text-xs text-muted-foreground">
<Shield size={10} />
{effectiveRole === 'super_admin' ? 'Super Admin' : effectiveRole === 'owner' ? 'Owner' : 'Viewer'}
</span>
@@ -139,8 +139,8 @@ export function AppLayout() {
className={cn(
'flex items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium transition-colors',
isActive
? 'bg-[rgba(34,211,238,0.10)] text-[#e2e5eb]'
: 'text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]'
? 'bg-accent-dim text-foreground'
: 'text-muted-foreground hover:bg-input hover:text-foreground'
)}
>
<Icon size={18} />
@@ -155,7 +155,7 @@ export function AppLayout() {
<button
type="button"
onClick={handleLogout}
className="flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb] transition-colors"
className="flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium text-muted-foreground hover:bg-input hover:text-foreground transition-colors"
>
<LogOut size={18} />
Logout

View File

@@ -48,7 +48,7 @@ export function NavItem({ href, icon: Icon, label, badge, iconColor, matchPaths,
title={label}
>
{isActive && (
<div className="absolute left-0 top-1/2 h-6 w-[3px] -translate-y-1/2 rounded-r-full bg-[#22d3ee]" />
<div className="absolute left-0 top-1/2 h-6 w-[3px] -translate-y-1/2 rounded-r-full bg-primary" />
)}
<Icon size={18} className={cn('shrink-0', isActive ? 'opacity-100' : 'opacity-70')} style={iconColor ? { color: iconColor } : undefined} />
{badge !== undefined && badge !== 0 && badge !== 'dot' && (
@@ -76,7 +76,7 @@ export function NavItem({ href, icon: Icon, label, badge, iconColor, matchPaths,
>
{/* Active indicator bar */}
{isActive && !isParentDimmed && (
<div className="absolute left-0 top-1/2 h-6 w-[3px] -translate-y-1/2 rounded-r-full bg-[#22d3ee]" />
<div className="absolute left-0 top-1/2 h-6 w-[3px] -translate-y-1/2 rounded-r-full bg-primary" />
)}
<Icon size={18} className={cn('shrink-0', isActive ? 'opacity-100' : 'opacity-70')} style={iconColor ? { color: iconColor } : undefined} />

View File

@@ -254,15 +254,15 @@ export function Sidebar() {
className={cn(
'group relative flex flex-col items-center justify-center rounded-lg px-1 py-2 transition-all duration-150',
active
? 'bg-[rgba(34,211,238,0.10)] text-[#67e8f9]'
: 'text-[#6b7280] hover:text-[#848b9b]'
? 'bg-accent-dim text-accent-text'
: 'text-text-rail-label hover:text-muted-foreground'
)}
title={item.label}
>
<span className="relative">
<Icon size={20} className={active ? 'opacity-100' : 'opacity-60 group-hover:opacity-85'} />
{item.badge !== undefined && item.badge > 0 && (
<span className="absolute -right-1.5 -top-1.5 flex h-4 min-w-[16px] items-center justify-center rounded-full bg-[#22d3ee] px-1 text-[0.5rem] font-bold text-[#0c0d10]">
<span className="absolute -right-1.5 -top-1.5 flex h-4 min-w-[16px] items-center justify-center rounded-full bg-primary px-1 text-[0.5rem] font-bold text-[#0c0d10]">
{item.badge > 99 ? '99+' : item.badge}
</span>
)}
@@ -293,9 +293,9 @@ export function Sidebar() {
'group relative flex items-center gap-3 rounded-lg px-3 py-2 text-[0.8125rem] font-medium transition-all duration-150',
active
? isParentDimmed
? 'bg-[rgba(34,211,238,0.05)] text-[#e2e5eb]/70'
: 'bg-[rgba(34,211,238,0.10)] text-[#e2e5eb]'
: 'text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]'
? 'bg-[rgba(34,211,238,0.05)] text-foreground/70'
: 'bg-accent-dim text-foreground'
: 'text-muted-foreground hover:bg-input hover:text-foreground'
)}
>
{active && !isParentDimmed && (
@@ -307,7 +307,7 @@ export function Sidebar() {
<Icon size={18} className={cn('shrink-0', active ? 'opacity-100' : 'opacity-70')} />
<span className="truncate">{item.label}</span>
{item.badge !== undefined && item.badge > 0 && (
<span className="ml-auto shrink-0 rounded-full px-2 text-[0.6875rem] font-mono text-[#4f5666]"
<span className="ml-auto shrink-0 rounded-full px-2 text-[0.6875rem] font-mono text-text-muted"
style={{ background: '#14161d', border: '1px solid #1e2130' }}>
{item.badge}
</span>
@@ -331,13 +331,13 @@ export function Sidebar() {
className={cn(
'flex items-center gap-2 rounded-lg pl-9 pr-3 py-1.5 text-[0.8125rem] font-medium transition-colors',
childActive
? 'bg-[rgba(34,211,238,0.10)] text-[#e2e5eb]'
: 'text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]'
? 'bg-accent-dim text-foreground'
: 'text-muted-foreground hover:bg-input hover:text-foreground'
)}
>
<span className="truncate">{child.label}</span>
{child.count !== undefined && (
<span className="ml-auto shrink-0 rounded-full px-2 text-[0.6875rem] font-mono text-[#4f5666]"
<span className="ml-auto shrink-0 rounded-full px-2 text-[0.6875rem] font-mono text-text-muted"
style={{ background: '#14161d', border: '1px solid #1e2130' }}>
{child.count}
</span>
@@ -373,7 +373,7 @@ export function Sidebar() {
{sections.map((section, si) => (
<div key={section.title}>
{si > 0 && (
<div className="font-mono text-[0.5625rem] uppercase tracking-[0.12em] text-[#4f5666] px-3 pt-3 pb-1">
<div className="font-mono text-[0.5625rem] uppercase tracking-[0.12em] text-text-muted px-3 pt-3 pb-1">
{section.title}
</div>
)}
@@ -390,7 +390,7 @@ export function Sidebar() {
<button
type="button"
onClick={toggleSidebarPinned}
className="flex w-full items-center gap-3 rounded-lg px-3 py-2 text-[0.8125rem] font-medium text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb] transition-colors"
className="flex w-full items-center gap-3 rounded-lg px-3 py-2 text-[0.8125rem] font-medium text-muted-foreground hover:bg-input hover:text-foreground transition-colors"
title="Unpin sidebar"
>
<PinOff size={18} className="shrink-0" />
@@ -427,7 +427,7 @@ export function Sidebar() {
<button
type="button"
onClick={toggleSidebarPinned}
className="flex flex-col items-center justify-center rounded-lg px-1 py-2 text-[#6b7280] hover:text-[#848b9b] transition-colors"
className="flex flex-col items-center justify-center rounded-lg px-1 py-2 text-text-rail-label hover:text-muted-foreground transition-colors"
title="Pin sidebar"
>
<Pin size={18} className="opacity-60 hover:opacity-85" />
@@ -455,7 +455,7 @@ export function Sidebar() {
>
{/* Drawer header */}
<div className="px-3 mb-3">
<h3 className="text-[0.6875rem] font-mono uppercase tracking-[0.12em] text-[#4f5666]">
<h3 className="text-[0.6875rem] font-mono uppercase tracking-[0.12em] text-text-muted">
{activeFlyoutGroup.label}
</h3>
</div>
@@ -469,13 +469,13 @@ export function Sidebar() {
className={cn(
'flex items-center justify-between rounded-md px-3 py-2 text-[0.8125rem] transition-colors',
isChildActive(child)
? 'bg-[rgba(34,211,238,0.10)] text-[#67e8f9]'
: 'text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]'
? 'bg-accent-dim text-accent-text'
: 'text-muted-foreground hover:bg-input hover:text-foreground'
)}
>
<span>{child.label}</span>
{child.count !== undefined && (
<span className="text-[0.6875rem] font-mono text-[#4f5666]">{child.count}</span>
<span className="text-[0.6875rem] font-mono text-text-muted">{child.count}</span>
)}
</Link>
))}
@@ -484,7 +484,7 @@ export function Sidebar() {
{/* Resize handle */}
<div
className="w-1 cursor-col-resize hover:bg-[#22d3ee]/20 active:bg-[#22d3ee]/30 transition-colors shrink-0"
className="w-1 cursor-col-resize hover:bg-primary/20 active:bg-primary/30 transition-colors shrink-0"
onPointerDown={handleResizeStart}
title="Drag to resize"
/>

View File

@@ -67,7 +67,7 @@ export function TopBar() {
className="flex items-center gap-2.5 pr-4 transition-all duration-200"
>
<BrandLogo size="sm" />
<span className="text-sm font-heading font-bold tracking-tight whitespace-nowrap text-[#f0f2f5]">
<span className="text-sm font-heading font-bold tracking-tight whitespace-nowrap text-text-heading">
ResolutionFlow
</span>
</Link>
@@ -81,9 +81,9 @@ export function TopBar() {
className="hidden sm:relative sm:block w-full text-left"
style={{ maxWidth: '480px' }}
>
<Search size={16} className="absolute left-3 top-1/2 -translate-y-1/2 text-[#848b9b]" />
<Search size={16} className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" />
<div
className="w-full rounded-md py-2 pl-9 pr-14 text-[0.8125rem] text-[#848b9b] cursor-pointer transition-colors"
className="w-full rounded-md py-2 pl-9 pr-14 text-[0.8125rem] text-muted-foreground cursor-pointer transition-colors"
style={{
background: '#14161d',
border: '1px solid #1e2130',
@@ -94,7 +94,7 @@ export function TopBar() {
Search flows, sessions, tags...
</div>
<span
className="absolute right-3 top-1/2 -translate-y-1/2 rounded px-1.5 py-0.5 font-mono text-[0.625rem] text-[#4f5666]"
className="absolute right-3 top-1/2 -translate-y-1/2 rounded px-1.5 py-0.5 font-mono text-[0.625rem] text-text-muted"
style={{ background: '#0c0d10', border: '1px solid #1e2130' }}
>
{navigator.platform?.toLowerCase().includes('mac') ? '\u2318K' : 'Ctrl+K'}
@@ -102,7 +102,7 @@ export function TopBar() {
</button>
<button
onClick={() => setCommandPaletteOpen(true)}
className="sm:hidden rounded-lg p-2 text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
className="sm:hidden rounded-lg p-2 text-muted-foreground hover:text-foreground transition-colors"
title="Search"
>
<Search size={18} />
@@ -115,14 +115,14 @@ export function TopBar() {
<div className="flex items-center gap-1">
<button
onClick={() => setQuickLaunchOpen(true)}
className="rounded-lg p-2 text-[#848b9b] hover:bg-[#14161d] hover:text-[#e2e5eb] transition-colors"
className="rounded-lg p-2 text-muted-foreground hover:bg-card hover:text-foreground transition-colors"
title="Quick Launch"
>
<Zap size={18} />
</button>
<Link
to="/guides"
className="rounded-lg p-2 text-[#848b9b] hover:bg-[#14161d] hover:text-[#e2e5eb] transition-colors"
className="rounded-lg p-2 text-muted-foreground hover:bg-card hover:text-foreground transition-colors"
title="User Guides"
>
<HelpCircle size={18} />
@@ -146,9 +146,9 @@ export function TopBar() {
style={{ background: '#14161d', border: '1px solid #1e2130' }}
>
<div className="px-3 py-2.5 mb-1" style={{ borderBottom: '1px solid #1e2130' }}>
<p className="text-sm font-medium text-[#e2e5eb] truncate">{user?.name || user?.email}</p>
<p className="text-sm font-medium text-foreground truncate">{user?.name || user?.email}</p>
{effectiveRole && effectiveRole !== 'engineer' && (
<span className="mt-1 inline-flex items-center gap-1 text-xs text-[#848b9b]">
<span className="mt-1 inline-flex items-center gap-1 text-xs text-muted-foreground">
<Shield size={10} />
{effectiveRole === 'super_admin' ? 'Super Admin' : effectiveRole === 'owner' ? 'Owner' : 'Viewer'}
</span>
@@ -157,7 +157,7 @@ export function TopBar() {
<Link
to="/account"
onClick={() => setUserMenuOpen(false)}
className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]"
className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-muted-foreground hover:bg-input hover:text-foreground"
>
<Settings size={14} />
Account
@@ -166,7 +166,7 @@ export function TopBar() {
<Link
to="/admin"
onClick={() => setUserMenuOpen(false)}
className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]"
className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-muted-foreground hover:bg-input hover:text-foreground"
>
<Shield size={14} />
Admin Panel
@@ -177,7 +177,7 @@ export function TopBar() {
onClick={handleLogout}
className={cn(
'flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm',
'text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]'
'text-muted-foreground hover:bg-input hover:text-foreground'
)}
>
<LogOut size={14} />