feat: implement monochrome design system across entire frontend
Migrate all 84 frontend files from the old themed/colored design to a monochrome glass-morphism design system. Pure black backgrounds, white text with opacity levels, glass-card components with backdrop-blur, and functional color reserved for status indicators only. Foundation: remap CSS variables to monochrome, simplify Tailwind config, remove theme toggle, convert brand logo/wordmark to white. Pages: all 14 pages updated. Components: all common, library, session, step-library, tree-editor, tree-preview, admin, and subscription components converted. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -223,7 +223,7 @@ export function SessionDetailPage() {
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex h-64 items-center justify-center">
|
||||
<div className="h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent" />
|
||||
<div className="h-8 w-8 animate-spin rounded-full border-4 border-white/20 border-t-white" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -231,12 +231,12 @@ export function SessionDetailPage() {
|
||||
if (error || !session) {
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8">
|
||||
<div className="rounded-md bg-destructive/10 p-4 text-destructive">
|
||||
<div className="rounded-md border border-red-400/20 bg-red-400/10 p-4 text-red-400">
|
||||
{error || 'Session not found'}
|
||||
</div>
|
||||
<button
|
||||
onClick={() => navigate('/sessions')}
|
||||
className="mt-4 text-primary hover:underline"
|
||||
className="mt-4 text-white hover:underline"
|
||||
>
|
||||
Back to sessions
|
||||
</button>
|
||||
@@ -252,18 +252,18 @@ export function SessionDetailPage() {
|
||||
<div>
|
||||
<button
|
||||
onClick={() => navigate('/sessions')}
|
||||
className="mb-2 text-sm text-muted-foreground hover:text-foreground"
|
||||
className="mb-2 text-sm text-white/40 hover:text-white"
|
||||
>
|
||||
← Back to sessions
|
||||
</button>
|
||||
<h1 className="text-2xl font-bold text-foreground sm:text-3xl">
|
||||
<h1 className="text-2xl font-bold text-white sm:text-3xl">
|
||||
{session.ticket_number || 'Session Details'}
|
||||
</h1>
|
||||
<div className="mt-2 flex items-center gap-4 text-sm text-muted-foreground">
|
||||
<div className="mt-2 flex items-center gap-4 text-sm text-white/40">
|
||||
<span
|
||||
className={cn(
|
||||
'flex items-center gap-1',
|
||||
session.completed_at ? 'text-green-600' : 'text-yellow-600'
|
||||
session.completed_at ? 'text-emerald-400' : 'text-yellow-400'
|
||||
)}
|
||||
>
|
||||
<span
|
||||
@@ -286,8 +286,8 @@ export function SessionDetailPage() {
|
||||
onClick={() => setShowSaveAsTreeModal(true)}
|
||||
disabled={isSavingTree}
|
||||
className={cn(
|
||||
'flex items-center gap-2 rounded-md border border-input bg-background px-4 py-2 text-sm font-medium',
|
||||
'hover:bg-accent hover:text-accent-foreground disabled:opacity-50'
|
||||
'flex items-center gap-2 rounded-md border border-white/10 bg-transparent px-4 py-2 text-sm font-medium text-white/60',
|
||||
'hover:bg-white/10 hover:text-white disabled:opacity-50'
|
||||
)}
|
||||
>
|
||||
<Save className="h-4 w-4" />
|
||||
@@ -299,8 +299,8 @@ export function SessionDetailPage() {
|
||||
<button
|
||||
onClick={handleCopyForTicket}
|
||||
className={cn(
|
||||
'flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground',
|
||||
'hover:bg-primary/90'
|
||||
'flex items-center gap-2 rounded-md bg-white px-4 py-2 text-sm font-medium text-black',
|
||||
'hover:bg-white/90'
|
||||
)}
|
||||
>
|
||||
{copiedPsa ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
|
||||
@@ -314,8 +314,8 @@ export function SessionDetailPage() {
|
||||
onChange={(e) => setExportFormat(e.target.value as typeof exportFormat)}
|
||||
aria-label="Export format"
|
||||
className={cn(
|
||||
'w-full rounded-md border border-input bg-background px-3 py-2 text-sm sm:w-auto',
|
||||
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary'
|
||||
'w-full rounded-md border border-white/10 bg-black/50 px-3 py-2 text-sm text-white sm:w-auto',
|
||||
'focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20'
|
||||
)}
|
||||
>
|
||||
<option value="markdown">Markdown</option>
|
||||
@@ -328,18 +328,18 @@ export function SessionDetailPage() {
|
||||
disabled={isExporting}
|
||||
title="Copy to clipboard"
|
||||
className={cn(
|
||||
'rounded-md border border-input bg-background p-2 text-muted-foreground',
|
||||
'hover:bg-accent hover:text-accent-foreground disabled:opacity-50'
|
||||
'rounded-md border border-white/10 bg-transparent p-2 text-white/60',
|
||||
'hover:bg-white/10 hover:text-white disabled:opacity-50'
|
||||
)}
|
||||
>
|
||||
{copied ? <Check className="h-4 w-4 text-green-500" /> : <Copy className="h-4 w-4" />}
|
||||
{copied ? <Check className="h-4 w-4 text-emerald-400" /> : <Copy className="h-4 w-4" />}
|
||||
</button>
|
||||
<button
|
||||
onClick={handlePreview}
|
||||
disabled={isExporting}
|
||||
className={cn(
|
||||
'flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground',
|
||||
'hover:bg-primary/90 disabled:opacity-50'
|
||||
'flex items-center gap-2 rounded-md bg-white px-4 py-2 text-sm font-medium text-black',
|
||||
'hover:bg-white/90 disabled:opacity-50'
|
||||
)}
|
||||
>
|
||||
<Eye className="h-4 w-4" />
|
||||
@@ -352,37 +352,37 @@ export function SessionDetailPage() {
|
||||
|
||||
{/* Timeline */}
|
||||
<div className="mb-8">
|
||||
<h2 className="mb-4 text-lg font-semibold text-foreground">Decision Timeline</h2>
|
||||
<h2 className="mb-4 text-lg font-semibold text-white">Decision Timeline</h2>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-3 text-sm">
|
||||
<span className="h-3 w-3 rounded-full bg-primary" />
|
||||
<span className="text-muted-foreground">
|
||||
<span className="h-3 w-3 rounded-full bg-white" />
|
||||
<span className="text-white/40">
|
||||
Session started: {formatDate(session.started_at)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{session.decisions.map((decision, index) => (
|
||||
<div key={index} className="ml-1 border-l-2 border-border pl-6">
|
||||
<div key={index} className="ml-1 border-l-2 border-white/[0.06] pl-6">
|
||||
<div className="relative">
|
||||
<span className="absolute -left-[1.625rem] top-1 h-2 w-2 rounded-full bg-border" />
|
||||
<div className="rounded-lg border border-border bg-card p-4">
|
||||
<span className="absolute -left-[1.625rem] top-1 h-2 w-2 rounded-full bg-white/20" />
|
||||
<div className="glass-card rounded-xl p-4">
|
||||
{decision.question && (
|
||||
<p className="font-medium text-card-foreground">{decision.question}</p>
|
||||
<p className="font-medium text-white">{decision.question}</p>
|
||||
)}
|
||||
{decision.answer && (
|
||||
<p className="mt-1 text-sm text-primary">Answer: {decision.answer}</p>
|
||||
<p className="mt-1 text-sm text-white">Answer: {decision.answer}</p>
|
||||
)}
|
||||
{decision.action_performed && (
|
||||
<p className="mt-1 text-sm text-muted-foreground">
|
||||
<p className="mt-1 text-sm text-white/40">
|
||||
Action: {decision.action_performed}
|
||||
</p>
|
||||
)}
|
||||
{decision.notes && (
|
||||
<p className="mt-2 rounded bg-muted/50 p-2 text-sm text-muted-foreground">
|
||||
<p className="mt-2 rounded bg-white/5 p-2 text-sm text-white/40">
|
||||
Notes: {decision.notes}
|
||||
</p>
|
||||
)}
|
||||
<p className="mt-2 text-xs text-muted-foreground">
|
||||
<p className="mt-2 text-xs text-white/40">
|
||||
{formatDate(decision.timestamp)}
|
||||
</p>
|
||||
</div>
|
||||
@@ -393,7 +393,7 @@ export function SessionDetailPage() {
|
||||
{session.completed_at && (
|
||||
<div className="flex items-center gap-3 text-sm">
|
||||
<span className="h-3 w-3 rounded-full bg-green-500" />
|
||||
<span className="text-green-600">
|
||||
<span className="text-emerald-400">
|
||||
Session completed: {formatDate(session.completed_at)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user