refactor: migrate FlowPilot components to Design System v4

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-03-22 01:56:27 -04:00
parent 97a20a4225
commit 56ff792f8e
17 changed files with 219 additions and 221 deletions

View File

@@ -8,7 +8,7 @@ interface AISessionListItemProps {
}
const STATUS_CONFIG = {
active: { icon: Clock, color: 'text-primary', label: 'Active' },
active: { icon: Clock, color: 'text-[#22d3ee]', label: 'Active' },
paused: { icon: Pause, color: 'text-amber-400', label: 'Paused' },
resolved: { icon: CheckCircle2, color: 'text-emerald-400', label: 'Resolved' },
escalated: { icon: ArrowUpRight, color: 'text-amber-400', label: 'Escalated' },
@@ -22,16 +22,16 @@ export function AISessionListItem({ session }: AISessionListItemProps) {
return (
<Link
to={`/pilot/${session.id}`}
className="glass-card block p-4 transition-all"
className="card-interactive block p-4 transition-all"
>
<div className="flex items-start justify-between gap-3">
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-foreground truncate">
<p className="text-sm font-medium text-[#e2e5eb] truncate">
{session.problem_summary || 'Untitled session'}
</p>
<div className="mt-1.5 flex items-center gap-3 flex-wrap">
{session.problem_domain && (
<span className="font-label rounded-md bg-primary/10 px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-primary">
<span className="font-sans text-xs rounded-md bg-[rgba(34,211,238,0.10)] px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-[#22d3ee]">
{session.problem_domain}
</span>
)}
@@ -39,7 +39,7 @@ export function AISessionListItem({ session }: AISessionListItemProps) {
<StatusIcon size={12} />
{config.label}
</span>
<span className="text-xs text-muted-foreground">
<span className="text-xs text-[#848b9b]">
{session.step_count} steps
</span>
<span className="text-xs text-[#5a6170]">
@@ -50,7 +50,7 @@ export function AISessionListItem({ session }: AISessionListItemProps) {
</div>
</div>
{session.session_rating && (
<span className="font-label text-xs text-amber-400">
<span className="font-sans text-xs text-xs text-amber-400">
{'★'.repeat(session.session_rating)}
</span>
)}

View File

@@ -30,12 +30,12 @@ export function ConfidenceIndicator({ tier, score, className }: ConfidenceIndica
return (
<div className={cn('group relative inline-flex items-center gap-2', className)}>
<span className={cn('h-2 w-2 rounded-full', config.color)} />
<span className="font-label text-xs text-muted-foreground">{config.label}</span>
<span className="font-sans text-xs text-xs text-[#848b9b]">{config.label}</span>
{/* Tooltip */}
<div className="pointer-events-none absolute left-0 top-full z-50 mt-2 w-56 rounded-lg border border-border bg-card p-3 opacity-0 shadow-lg transition-opacity group-hover:pointer-events-auto group-hover:opacity-100">
<p className="text-xs text-muted-foreground">{config.description}</p>
<p className="mt-1 font-label text-[0.625rem] text-[#5a6170]">
<div className="pointer-events-none absolute left-0 top-full z-50 mt-2 w-56 rounded-lg border border-[#1e2130] bg-[#14161d] p-3 opacity-0 shadow-lg transition-opacity group-hover:pointer-events-auto group-hover:opacity-100">
<p className="text-xs text-[#848b9b]">{config.description}</p>
<p className="mt-1 font-sans text-xs text-[0.625rem] text-[#5a6170]">
Confidence: {Math.round(score * 100)}%
</p>
</div>

View File

@@ -43,7 +43,7 @@ export function EscalateModal({ open, onClose, onEscalate, isProcessing, hasPsaT
</div>
<div>
<label className="mb-1.5 block text-sm font-medium text-foreground">
<label className="mb-1.5 block text-sm font-medium text-[#e2e5eb]">
Why are you escalating?
</label>
<RichTextInput
@@ -63,14 +63,14 @@ export function EscalateModal({ open, onClose, onEscalate, isProcessing, hasPsaT
<button
onClick={handleClose}
disabled={isProcessing}
className="flex-1 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2.5 min-h-[44px] text-sm font-medium text-foreground hover:border-[rgba(255,255,255,0.12)] transition-colors disabled:opacity-50"
className="flex-1 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2.5 min-h-[44px] text-sm font-medium text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)] transition-colors disabled:opacity-50"
>
Cancel
</button>
<button
onClick={handleSubmit}
disabled={!reason.trim() || reason.trim().length < 5 || isProcessing}
className="flex-1 flex items-center justify-center gap-2 rounded-lg bg-amber-500/90 px-4 py-2.5 min-h-[44px] text-sm font-semibold text-[#101114] hover:bg-amber-500 active:scale-[0.97] disabled:opacity-40 transition-all"
className="flex-1 flex items-center justify-center gap-2 rounded-lg bg-amber-500/90 px-4 py-2.5 min-h-[44px] text-sm font-semibold text-white hover:bg-amber-500 active:scale-[0.98] disabled:opacity-40 transition-all"
>
{isProcessing ? (
<Loader2 size={14} className="animate-spin" />

View File

@@ -42,7 +42,7 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
if (isLoading) {
return (
<div className="flex items-center justify-center py-12">
<Loader2 size={20} className="animate-spin text-muted-foreground" />
<Loader2 size={20} className="animate-spin text-[#848b9b]" />
</div>
)
}
@@ -53,7 +53,7 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
<p className="text-sm text-rose-400">{error}</p>
<button
onClick={loadQueue}
className="mt-2 text-xs text-muted-foreground hover:text-foreground transition-colors"
className="mt-2 text-xs text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
>
Try again
</button>
@@ -64,11 +64,11 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
if (sessions.length === 0) {
return (
<div className="py-12 text-center">
<AlertTriangle size={24} className="mx-auto mb-2 text-muted-foreground/40" />
<p className="text-sm text-muted-foreground">No sessions awaiting escalation</p>
<AlertTriangle size={24} className="mx-auto mb-2 text-[#848b9b]/40" />
<p className="text-sm text-[#848b9b]">No sessions awaiting escalation</p>
<button
onClick={loadQueue}
className="mt-3 flex items-center gap-1.5 mx-auto text-xs text-muted-foreground hover:text-foreground transition-colors"
className="mt-3 flex items-center gap-1.5 mx-auto text-xs text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
>
<RefreshCw size={12} />
Refresh
@@ -80,12 +80,12 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
return (
<div className="space-y-3">
<div className="flex items-center justify-between px-1">
<h3 className="font-label text-[0.625rem] uppercase tracking-wider text-[#5a6170]">
<h3 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170]">
Awaiting pickup ({sessions.length})
</h3>
<button
onClick={loadQueue}
className="flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors"
className="flex items-center gap-1 text-xs text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
>
<RefreshCw size={10} />
Refresh
@@ -93,9 +93,9 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
</div>
{sessions.map((session) => (
<div key={session.id} className="glass-card p-3 sm:p-4 space-y-3">
<div key={session.id} className="card-interactive p-3 sm:p-4 space-y-3">
<div>
<p className="text-sm font-semibold text-foreground">
<p className="text-sm font-semibold text-[#e2e5eb]">
{session.problem_summary || 'Untitled session'}
</p>
{session.escalation_reason && (
@@ -105,9 +105,9 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
)}
</div>
<div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground">
<div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-[#848b9b]">
{session.problem_domain && (
<span className="font-label rounded-md bg-primary/10 px-1.5 py-0.5 text-[0.5625rem] uppercase tracking-wider text-primary">
<span className="font-sans text-xs rounded-md bg-[rgba(34,211,238,0.10)] px-1.5 py-0.5 text-[0.5625rem] uppercase tracking-wider text-[#22d3ee]">
{session.problem_domain}
</span>
)}
@@ -120,7 +120,7 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
{new Date(session.created_at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
</span>
{session.psa_ticket_id && (
<span className="flex items-center gap-1 text-primary">
<span className="flex items-center gap-1 text-[#22d3ee]">
<Ticket size={10} />
#{session.psa_ticket_id}
</span>
@@ -129,7 +129,7 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
<button
onClick={() => handlePickup(session.id)}
className="w-full min-h-[44px] rounded-lg bg-gradient-brand px-4 py-2 text-sm font-semibold text-[#101114] shadow-lg shadow-primary/20 hover:opacity-90 active:scale-[0.97] transition-all"
className="w-full min-h-[44px] rounded-lg bg-[#22d3ee] text-white px-4 py-2 text-sm font-semibold hover:brightness-110 active:scale-[0.98] transition-all"
>
Pick Up Session
</button>

View File

@@ -70,8 +70,8 @@ export function FlowPilotActionBar({
<>
{/* Bottom bar — fixed to viewport bottom, works regardless of height chain */}
<div
className="fixed bottom-0 right-0 z-40 flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-3 border-t px-3 py-3 sm:px-5"
style={{ borderColor: 'var(--glass-border)', background: 'rgba(16, 17, 20, 0.95)', backdropFilter: 'blur(16px)', left: 'var(--sidebar-w, 0px)' }}
className="fixed bottom-0 right-0 z-40 flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-3 border-t border-[#1e2130] bg-[#14161d] px-3 py-3 sm:px-5"
style={{ left: 'var(--sidebar-w, 0px)' }}
>
<div className="flex gap-2 sm:gap-3">
<button
@@ -96,7 +96,7 @@ export function FlowPilotActionBar({
<button
onClick={handlePause}
disabled={isProcessing || submitting}
className="flex items-center justify-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 min-h-[44px] text-sm font-medium text-muted-foreground hover:text-foreground hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 disabled:pointer-events-none transition-colors"
className="flex items-center justify-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 min-h-[44px] text-sm font-medium text-[#848b9b] hover:text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 disabled:pointer-events-none transition-colors"
>
<Pause size={16} />
Pause
@@ -106,7 +106,7 @@ export function FlowPilotActionBar({
<button
onClick={() => setShowAbandon(true)}
disabled={isProcessing || submitting}
className="flex items-center justify-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 min-h-[44px] text-sm font-medium text-muted-foreground hover:text-foreground hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 disabled:pointer-events-none transition-colors"
className="flex items-center justify-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 min-h-[44px] text-sm font-medium text-[#848b9b] hover:text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 disabled:pointer-events-none transition-colors"
>
<X size={16} />
Close
@@ -118,21 +118,21 @@ export function FlowPilotActionBar({
{/* Resolve modal */}
{showResolve && (
<div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center bg-black/60 backdrop-blur-sm">
<div className="glass-card-static w-full max-w-full sm:max-w-lg mx-0 sm:mx-4 p-4 sm:p-6 rounded-t-2xl sm:rounded-2xl">
<h3 className="font-heading text-lg font-semibold text-foreground mb-1">Resolve Session</h3>
<p className="text-sm text-muted-foreground mb-4">Summarize what fixed the issue. This will be included in the auto-generated documentation.</p>
<div className="card-flat w-full max-w-full sm:max-w-lg mx-0 sm:mx-4 p-4 sm:p-6 rounded-t-2xl sm:rounded-2xl">
<h3 className="font-heading text-lg font-semibold text-[#e2e5eb] mb-1">Resolve Session</h3>
<p className="text-sm text-[#848b9b] mb-4">Summarize what fixed the issue. This will be included in the auto-generated documentation.</p>
<textarea
value={resolutionSummary}
onChange={(e) => setResolutionSummary(e.target.value)}
placeholder="What resolved the issue?"
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none"
className="w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2 text-sm text-[#e2e5eb] placeholder:text-[#848b9b] focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none"
rows={4}
autoFocus
/>
<div className="mt-4 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end">
<button
onClick={() => setShowResolve(false)}
className="rounded-lg px-4 py-2 min-h-[44px] text-sm text-muted-foreground hover:text-foreground transition-colors"
className="rounded-lg px-4 py-2 min-h-[44px] text-sm text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
>
Cancel
</button>
@@ -151,15 +151,15 @@ export function FlowPilotActionBar({
{/* Close/Abandon confirmation */}
{showAbandon && (
<div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center bg-black/60 backdrop-blur-sm">
<div className="glass-card-static w-full max-w-full sm:max-w-lg mx-0 sm:mx-4 p-4 sm:p-6 rounded-t-2xl sm:rounded-2xl">
<h3 className="font-heading text-lg font-semibold text-foreground mb-1">Close Session</h3>
<p className="text-sm text-muted-foreground mb-4">
<div className="card-flat w-full max-w-full sm:max-w-lg mx-0 sm:mx-4 p-4 sm:p-6 rounded-t-2xl sm:rounded-2xl">
<h3 className="font-heading text-lg font-semibold text-[#e2e5eb] mb-1">Close Session</h3>
<p className="text-sm text-[#848b9b] mb-4">
Are you sure you want to close this session? The session history will be kept but it won't count as resolved.
</p>
<div className="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end">
<button
onClick={() => setShowAbandon(false)}
className="rounded-lg px-4 py-2 min-h-[44px] text-sm text-muted-foreground hover:text-foreground transition-colors"
className="rounded-lg px-4 py-2 min-h-[44px] text-sm text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
>
Cancel
</button>

View File

@@ -100,11 +100,11 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
return (
<div className="flex items-center justify-center min-h-[50vh]">
<div className="text-center">
<div className="mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-2xl bg-primary/10">
<Sparkles size={24} className="text-primary animate-pulse" />
<div className="mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-2xl bg-[rgba(34,211,238,0.10)]">
<Sparkles size={24} className="text-[#22d3ee] animate-pulse" />
</div>
<p className="text-sm font-medium text-foreground">Analyzing your issue...</p>
<p className="mt-1 text-xs text-muted-foreground">FlowPilot is classifying the problem and searching for relevant flows</p>
<p className="text-sm font-medium text-[#e2e5eb]">Analyzing your issue...</p>
<p className="mt-1 text-xs text-[#848b9b]">FlowPilot is classifying the problem and searching for relevant flows</p>
</div>
</div>
)
@@ -118,26 +118,26 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
<div className="flex items-start justify-center px-3 sm:px-4 pt-[6vh] sm:pt-[10vh]">
<div className="w-full max-w-2xl">
<div className="text-center mb-4 sm:mb-6">
<h1 className="font-heading text-xl sm:text-2xl font-bold tracking-tight text-foreground">
<h1 className="font-heading text-xl sm:text-2xl font-bold tracking-tight text-[#e2e5eb]">
What are you troubleshooting?
</h1>
<p className="mt-2 text-sm text-muted-foreground">
<p className="mt-2 text-sm text-[#848b9b]">
Describe the issue, paste an error message, or pull context from a ticket
</p>
</div>
<div className="glass-card-static p-3 sm:p-5 space-y-4">
<div className="card-flat p-3 sm:p-5 space-y-4">
{/* Selected ticket card */}
{selectedTicket && selectedTicketId && (
<div className="rounded-xl border border-primary/20 bg-primary/5 p-4">
<div className="flex items-start justify-between">
<div className="min-w-0 flex-1">
<p className="text-sm font-semibold text-foreground">
<span className="text-primary">#{selectedTicketId}</span>
<p className="text-sm font-semibold text-[#e2e5eb]">
<span className="text-[#22d3ee]">#{selectedTicketId}</span>
{' — '}
{selectedTicket.summary}
</p>
<div className="mt-1 flex flex-wrap items-center gap-x-2 text-xs text-muted-foreground">
<div className="mt-1 flex flex-wrap items-center gap-x-2 text-xs text-[#848b9b]">
{selectedTicket.company_name && <span>{selectedTicket.company_name}</span>}
{selectedTicket.priority_name && (
<>
@@ -155,7 +155,7 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
</div>
<button
onClick={handleClearTicket}
className="ml-2 rounded-md p-1 text-muted-foreground hover:bg-white/[0.06] hover:text-foreground transition-colors"
className="ml-2 rounded-md p-1 text-[#848b9b] hover:bg-white/[0.06] hover:text-[#e2e5eb] transition-colors"
>
<X size={14} />
</button>
@@ -166,7 +166,7 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
value={additionalContext}
onChange={(e) => setAdditionalContext(e.target.value)}
placeholder="Add extra context (optional) — e.g. 'User called back and said it's also affecting their second monitor'"
className="mt-3 w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none"
className="mt-3 w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2 text-sm text-[#e2e5eb] placeholder:text-[#848b9b] focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none"
rows={3}
/>
</div>
@@ -190,8 +190,8 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
onClick={() => setShowLogs(!showLogs)}
className={`flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-medium transition-colors ${
showLogs
? 'bg-primary/10 text-primary border border-primary/20'
: 'bg-card/50 text-muted-foreground border border-border hover:text-foreground'
? 'bg-[rgba(34,211,238,0.10)] text-[#22d3ee] border border-primary/20'
: 'bg-[#14161d]/50 text-[#848b9b] border border-[#1e2130] hover:text-[#e2e5eb]'
}`}
>
<Terminal size={12} />
@@ -206,8 +206,8 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
disabled={!psaChecked || !psaConnection}
className={`flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-medium transition-colors ${
psaConnection
? 'bg-card/50 text-muted-foreground border border-border hover:text-foreground hover:border-primary/20'
: 'bg-card/50 text-[#5a6170] border border-border opacity-50 cursor-not-allowed'
? 'bg-[#14161d]/50 text-[#848b9b] border border-[#1e2130] hover:text-[#e2e5eb] hover:border-primary/20'
: 'bg-[#14161d]/50 text-[#5a6170] border border-[#1e2130] opacity-50 cursor-not-allowed'
}`}
title={!psaConnection ? 'Connect your PSA in Settings → Integrations' : 'Search for a ConnectWise ticket'}
>
@@ -229,7 +229,7 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
value={logContent}
onChange={(e) => setLogContent(e.target.value)}
placeholder="Paste log output, error messages, or Event Viewer entries here..."
className="w-full rounded-lg border border-border bg-card px-4 py-3 font-mono text-xs text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none"
className="w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-4 py-3 font-mono text-xs text-[#e2e5eb] placeholder:text-[#848b9b] focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none"
rows={6}
/>
)}
@@ -242,7 +242,7 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
<button
onClick={handleSubmit}
disabled={!hasContent}
className="w-full sm:w-auto min-h-[44px] rounded-lg bg-gradient-brand px-5 py-2.5 text-sm font-semibold text-[#101114] shadow-lg shadow-primary/20 hover:opacity-90 active:scale-[0.97] disabled:opacity-40 disabled:shadow-none transition-all whitespace-nowrap"
className="w-full sm:w-auto min-h-[44px] rounded-lg bg-[#22d3ee] text-white px-5 py-2.5 text-sm font-semibold hover:brightness-110 active:scale-[0.98] disabled:opacity-40 transition-all whitespace-nowrap"
>
{submitLabel}
</button>

View File

@@ -48,10 +48,10 @@ export function FlowPilotMessageBar({ onRespond, disabled = false, isProcessing
className={cn(
'flex items-end gap-2 rounded-xl border p-3 transition-colors',
isDisabled
? 'border-border/50 opacity-50'
: 'border-border focus-within:border-[rgba(6,182,212,0.3)]'
? 'border-[#1e2130]/50 opacity-50'
: 'border-[#1e2130] focus-within:border-[rgba(6,182,212,0.3)]'
)}
style={{ background: 'rgba(16, 17, 20, 0.95)', backdropFilter: 'blur(16px)' }}
style={{ background: '#14161d' }}
>
<textarea
ref={textareaRef}
@@ -61,7 +61,7 @@ export function FlowPilotMessageBar({ onRespond, disabled = false, isProcessing
placeholder={isProcessing ? 'FlowPilot is thinking...' : 'Type a message...'}
disabled={isDisabled}
rows={1}
className="flex-1 resize-none bg-transparent text-sm text-foreground placeholder:text-muted-foreground focus:outline-none disabled:cursor-not-allowed py-1.5 px-2"
className="flex-1 resize-none bg-transparent text-sm text-[#e2e5eb] placeholder:text-[#848b9b] focus:outline-none disabled:cursor-not-allowed py-1.5 px-2"
/>
<button
onClick={handleSubmit}
@@ -70,8 +70,8 @@ export function FlowPilotMessageBar({ onRespond, disabled = false, isProcessing
className={cn(
'flex h-9 w-9 shrink-0 items-center justify-center rounded-lg transition-all',
message.trim() && !isDisabled
? 'bg-gradient-brand text-[#101114] hover:opacity-90 active:scale-[0.97]'
: 'bg-[rgba(255,255,255,0.04)] text-muted-foreground cursor-not-allowed'
? 'bg-[#22d3ee] text-white hover:brightness-110 active:scale-[0.98]'
: 'bg-[rgba(255,255,255,0.04)] text-[#848b9b] cursor-not-allowed'
)}
>
<Send size={16} />

View File

@@ -32,20 +32,20 @@ export function FlowPilotOptions({ options, onSelect, disabled }: FlowPilotOptio
'hover:border-[rgba(6,182,212,0.3)] hover:shadow-[0_0_20px_rgba(6,182,212,0.08)]',
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40',
isSelected
? 'border-primary/40 bg-primary/10'
: 'border-border bg-card/50',
? 'border-primary/40 bg-[rgba(34,211,238,0.10)]'
: 'border-[#1e2130] bg-[#14161d]/50',
disabled && 'pointer-events-none opacity-60'
)}
>
<div className="flex items-start justify-between gap-3">
<div className="flex-1">
<p className="text-sm font-medium text-foreground">{option.label}</p>
<p className="text-sm font-medium text-[#e2e5eb]">{option.label}</p>
{option.followup_hint && (
<p className="mt-1 text-xs text-muted-foreground">{option.followup_hint}</p>
<p className="mt-1 text-xs text-[#848b9b]">{option.followup_hint}</p>
)}
</div>
{isSelected && (
<span className="flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-primary/20 text-primary">
<span className="flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-primary/20 text-[#22d3ee]">
<Check size={12} />
</span>
)}

View File

@@ -141,9 +141,9 @@ export function FlowPilotSession({
onClick={() => setShowMobileSidebar(!showMobileSidebar)}
className="flex w-full items-center justify-between px-3 py-2 sm:px-4"
>
<div className="flex items-center gap-3 text-xs text-muted-foreground overflow-x-auto">
<div className="flex items-center gap-3 text-xs text-[#848b9b] overflow-x-auto">
{session.problem_domain && (
<span className="font-label rounded-md bg-primary/10 px-1.5 py-0.5 text-[0.5625rem] uppercase tracking-wider text-primary shrink-0">
<span className="font-sans text-xs rounded-md bg-[rgba(34,211,238,0.10)] px-1.5 py-0.5 text-[0.5625rem] uppercase tracking-wider text-[#22d3ee] shrink-0">
{session.problem_domain}
</span>
)}
@@ -156,7 +156,7 @@ export function FlowPilotSession({
score={currentStep?.confidence_score ?? 0}
/>
</div>
{showMobileSidebar ? <ChevronUp size={14} className="text-muted-foreground shrink-0" /> : <ChevronDown size={14} className="text-muted-foreground shrink-0" />}
{showMobileSidebar ? <ChevronUp size={14} className="text-[#848b9b] shrink-0" /> : <ChevronDown size={14} className="text-[#848b9b] shrink-0" />}
</button>
{showMobileSidebar && (
<div className="px-3 pb-3 sm:px-4 space-y-3">
@@ -169,7 +169,7 @@ export function FlowPilotSession({
<button
onClick={() => setShowTicketPicker(true)}
disabled={linkingTicket}
className="w-full flex items-center gap-2 rounded-xl border border-dashed border-border px-3 py-2.5 text-xs text-muted-foreground hover:text-foreground hover:border-primary/30 transition-colors disabled:opacity-50 min-h-[44px]"
className="w-full flex items-center gap-2 rounded-xl border border-dashed border-[#1e2130] px-3 py-2.5 text-xs text-[#848b9b] hover:text-[#e2e5eb] hover:border-primary/30 transition-colors disabled:opacity-50 min-h-[44px]"
>
<Ticket size={14} />
{linkingTicket ? 'Linking...' : 'Link Ticket'}
@@ -177,14 +177,14 @@ export function FlowPilotSession({
) : null}
{session.problem_summary && (
<div>
<h4 className="font-label text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">Problem</h4>
<p className="text-sm text-foreground">{session.problem_summary}</p>
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">Problem</h4>
<p className="text-sm text-[#e2e5eb]">{session.problem_summary}</p>
</div>
)}
{session.matched_flow_id && (
<div className="flex items-center gap-2">
<Network size={14} className="text-muted-foreground" />
<span className="text-xs text-foreground">
<Network size={14} className="text-[#848b9b]" />
<span className="text-xs text-[#e2e5eb]">
{session.match_score ? `${Math.round(session.match_score * 100)}% match` : 'Match found'}
</span>
</div>
@@ -228,7 +228,7 @@ export function FlowPilotSession({
<button
onClick={() => setShowTicketPicker(true)}
disabled={linkingTicket}
className="w-full flex items-center gap-2 rounded-xl border border-dashed border-border px-3 py-2.5 text-xs text-muted-foreground hover:text-foreground hover:border-primary/30 transition-colors disabled:opacity-50"
className="w-full flex items-center gap-2 rounded-xl border border-dashed border-[#1e2130] px-3 py-2.5 text-xs text-[#848b9b] hover:text-[#e2e5eb] hover:border-primary/30 transition-colors disabled:opacity-50"
>
<Ticket size={14} />
{linkingTicket ? 'Linking...' : 'Link Ticket'}
@@ -238,20 +238,20 @@ export function FlowPilotSession({
{/* Problem summary */}
{session.problem_summary && (
<div>
<h4 className="font-label text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">
Problem
</h4>
<p className="text-sm text-foreground">{session.problem_summary}</p>
<p className="text-sm text-[#e2e5eb]">{session.problem_summary}</p>
</div>
)}
{/* Domain */}
{session.problem_domain && (
<div>
<h4 className="font-label text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">
Domain
</h4>
<span className="font-label rounded-md bg-primary/10 px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-primary">
<span className="font-sans text-xs rounded-md bg-[rgba(34,211,238,0.10)] px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-[#22d3ee]">
{session.problem_domain}
</span>
</div>
@@ -259,7 +259,7 @@ export function FlowPilotSession({
{/* Confidence */}
<div>
<h4 className="font-label text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">
Confidence
</h4>
<ConfidenceIndicator
@@ -271,12 +271,12 @@ export function FlowPilotSession({
{/* Matched flow */}
{session.matched_flow_id && (
<div>
<h4 className="font-label text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">
Matched flow
</h4>
<div className="flex items-center gap-2">
<Network size={14} className="text-muted-foreground" />
<span className="text-xs text-foreground">
<Network size={14} className="text-[#848b9b]" />
<span className="text-xs text-[#e2e5eb]">
{session.match_score ? `${Math.round(session.match_score * 100)}% match` : 'Match found'}
</span>
</div>
@@ -286,12 +286,12 @@ export function FlowPilotSession({
{/* Steps */}
<div className="flex items-center gap-4">
<div className="flex items-center gap-1.5">
<Hash size={12} className="text-muted-foreground" />
<span className="text-xs text-muted-foreground">{session.step_count} steps</span>
<Hash size={12} className="text-[#848b9b]" />
<span className="text-xs text-[#848b9b]">{session.step_count} steps</span>
</div>
<div className="flex items-center gap-1.5">
<Clock size={12} className="text-muted-foreground" />
<span className="text-xs text-muted-foreground">
<Clock size={12} className="text-[#848b9b]" />
<span className="text-xs text-[#848b9b]">
{new Date(session.created_at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
</span>
</div>
@@ -330,13 +330,12 @@ export function FlowPilotSession({
{/* Paused banner */}
{session.status === 'paused' && onResume && (
<div
className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between border-t px-3 py-3 sm:px-5"
style={{ borderColor: 'var(--glass-border)', background: 'rgba(16, 17, 20, 0.8)', backdropFilter: 'blur(12px)' }}
className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between border-t border-[#1e2130] bg-[#14161d] px-3 py-3 sm:px-5"
>
<span className="text-sm text-muted-foreground">Session paused</span>
<span className="text-sm text-[#848b9b]">Session paused</span>
<button
onClick={onResume}
className="flex items-center gap-2 rounded-lg bg-gradient-brand px-4 py-2 text-sm font-semibold text-[#101114] shadow-lg shadow-primary/20 hover:opacity-90 active:scale-[0.97] transition-all"
className="flex items-center gap-2 rounded-lg bg-[#22d3ee] text-white px-4 py-2 text-sm font-semibold hover:brightness-110 active:scale-[0.98] transition-all"
>
<Play size={14} />
Resume Session

View File

@@ -62,12 +62,12 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
return (
<button
onClick={() => setIsCollapsed(false)}
className="w-full text-left glass-card-static p-3 sm:p-4 opacity-70 hover:opacity-90 transition-opacity"
className="w-full text-left card-flat p-3 sm:p-4 opacity-70 hover:opacity-90 transition-opacity"
>
<div className="flex items-center gap-3">
<Icon size={16} className="shrink-0 text-muted-foreground" />
<p className="text-sm text-foreground truncate flex-1">{stepText}</p>
<ChevronDown size={14} className="shrink-0 text-muted-foreground" />
<Icon size={16} className="shrink-0 text-[#848b9b]" />
<p className="text-sm text-[#e2e5eb] truncate flex-1">{stepText}</p>
<ChevronDown size={14} className="shrink-0 text-[#848b9b]" />
</div>
</button>
)
@@ -76,20 +76,20 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
// Expanded completed step
if (!isCurrentStep && !isCollapsed) {
return (
<div className="glass-card-static p-3 sm:p-4 opacity-80">
<div className="card-flat p-3 sm:p-4 opacity-80">
<button
onClick={() => setIsCollapsed(true)}
className="mb-2 flex w-full items-center justify-between text-left"
>
<div className="flex items-center gap-2">
<Icon size={16} className="text-muted-foreground" />
<span className="font-label text-[0.625rem] uppercase tracking-wider text-muted-foreground">
<Icon size={16} className="text-[#848b9b]" />
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#848b9b]">
Step {step.step_order + 1}
</span>
</div>
<ChevronUp size={14} className="text-muted-foreground" />
<ChevronUp size={14} className="text-[#848b9b]" />
</button>
<MarkdownContent content={stepText} className="text-sm text-foreground" />
<MarkdownContent content={stepText} className="text-sm text-[#e2e5eb]" />
</div>
)
}
@@ -98,14 +98,14 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
return (
<div
className={cn(
'glass-card-static p-3 sm:p-4 lg:p-5',
'card-flat p-3 sm:p-4 lg:p-5',
isResolutionSuggestion && 'border-emerald-500/30'
)}
>
{/* Context message */}
{step.context_message && (
<div className="mb-3 rounded-lg bg-primary/5 px-3 py-2 border border-primary/10">
<MarkdownContent content={step.context_message} className="text-xs text-muted-foreground" />
<MarkdownContent content={step.context_message} className="text-xs text-[#848b9b]" />
</div>
)}
@@ -113,14 +113,14 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
<div className="flex items-start gap-3 mb-4">
<span className={cn(
'mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-lg',
isResolutionSuggestion ? 'bg-emerald-500/10 text-emerald-400' : 'bg-primary/10 text-primary'
isResolutionSuggestion ? 'bg-emerald-500/10 text-emerald-400' : 'bg-[rgba(34,211,238,0.10)] text-[#22d3ee]'
)}>
<Icon size={14} />
</span>
<div className="min-w-0 flex-1">
<MarkdownContent content={stepText} className="text-sm" />
{isResolutionSuggestion && typeof content.resolution_summary === 'string' && (
<p className="mt-2 text-sm text-muted-foreground">
<p className="mt-2 text-sm text-[#848b9b]">
{content.resolution_summary}
</p>
)}
@@ -141,7 +141,7 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
</button>
<button
onClick={() => handleResolutionResponse(false)}
className="flex-1 min-h-[44px] rounded-lg bg-card/50 border border-border px-4 py-2.5 text-sm font-medium text-foreground hover:bg-card transition-colors"
className="flex-1 min-h-[44px] rounded-lg bg-[#14161d]/50 border border-[#1e2130] px-4 py-2.5 text-sm font-medium text-[#e2e5eb] hover:bg-[#14161d] transition-colors"
>
No, keep investigating
</button>
@@ -180,7 +180,7 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
window.open('/script-builder?from=flowpilot', '_blank')
onRespond({ action_result: { success: true, details: 'Opened Script Builder' } })
}}
className="flex-1 min-h-[44px] rounded-lg bg-gradient-brand px-4 py-2.5 text-sm font-semibold text-[#101114] hover:opacity-90 active:scale-[0.97] transition-all"
className="flex-1 min-h-[44px] rounded-lg bg-[#22d3ee] text-white px-4 py-2.5 text-sm font-semibold hover:brightness-110 active:scale-[0.98] transition-all"
>
Open Script Builder
</button>
@@ -191,13 +191,13 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
<div className="flex flex-col gap-2 sm:flex-row">
<button
onClick={() => handleActionComplete(true)}
className="flex-1 min-h-[44px] rounded-lg bg-primary/10 border border-primary/20 px-4 py-2.5 text-sm font-medium text-primary hover:bg-primary/20 transition-colors"
className="flex-1 min-h-[44px] rounded-lg bg-[rgba(34,211,238,0.10)] border border-primary/20 px-4 py-2.5 text-sm font-medium text-[#22d3ee] hover:bg-primary/20 transition-colors"
>
I've completed this action
</button>
<button
onClick={() => handleActionComplete(false)}
className="flex-1 min-h-[44px] rounded-lg bg-card/50 border border-border px-4 py-2.5 text-sm font-medium text-foreground hover:bg-card transition-colors"
className="flex-1 min-h-[44px] rounded-lg bg-[#14161d]/50 border border-[#1e2130] px-4 py-2.5 text-sm font-medium text-[#e2e5eb] hover:bg-[#14161d] transition-colors"
>
This didn't work
</button>
@@ -208,7 +208,7 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
{!isResolutionSuggestion && step.allow_skip && (
<button
onClick={handleSkip}
className="flex items-center gap-1.5 text-xs text-[#5a6170] hover:text-muted-foreground transition-colors"
className="flex items-center gap-1.5 text-xs text-[#5a6170] hover:text-[#848b9b] transition-colors"
>
<SkipForward size={12} />
I can't check this right now
@@ -221,7 +221,7 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
{isProcessing && (
<div className="flex items-center gap-2 pt-2">
<div className="h-1.5 w-1.5 rounded-full bg-primary animate-pulse" />
<span className="text-xs text-muted-foreground">FlowPilot is thinking...</span>
<span className="text-xs text-[#848b9b]">FlowPilot is thinking...</span>
</div>
)}
</div>

View File

@@ -65,14 +65,14 @@ export function InSessionScriptGenerator({
return (
<div className="mt-3 rounded-xl border border-primary/20 bg-primary/5 p-3 sm:p-4 space-y-3">
<div className="flex items-center gap-2">
<Terminal size={14} className="text-primary" />
<span className="font-label text-[0.625rem] uppercase tracking-wider text-primary">
<Terminal size={14} className="text-[#22d3ee]" />
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#22d3ee]">
Script Generator
</span>
</div>
{instructions && (
<p className="text-xs text-muted-foreground">{instructions}</p>
<p className="text-xs text-[#848b9b]">{instructions}</p>
)}
{/* Parameter editing */}
@@ -80,7 +80,7 @@ export function InSessionScriptGenerator({
<>
<button
onClick={() => setShowParams(!showParams)}
className="flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors"
className="flex items-center gap-1.5 text-xs text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
>
{showParams ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
Parameters ({Object.keys(params).length})
@@ -90,13 +90,13 @@ export function InSessionScriptGenerator({
<div className="space-y-2">
{Object.entries(params).map(([key, value]) => (
<div key={key}>
<label className="block text-xs font-medium text-muted-foreground mb-1">
<label className="block text-xs font-medium text-[#848b9b] mb-1">
{key.replace(/_/g, ' ')}
</label>
<input
value={value}
onChange={(e) => setParams(prev => ({ ...prev, [key]: e.target.value }))}
className="w-full rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none"
className="w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-1.5 text-sm text-[#e2e5eb] placeholder:text-[#848b9b] focus:border-[rgba(6,182,212,0.3)] focus:outline-none"
/>
</div>
))}
@@ -106,7 +106,7 @@ export function InSessionScriptGenerator({
<button
onClick={handleGenerate}
disabled={isGenerating}
className="w-full min-h-[44px] flex items-center justify-center gap-2 rounded-lg bg-gradient-brand px-4 py-2 text-sm font-semibold text-[#101114] shadow-lg shadow-primary/20 hover:opacity-90 active:scale-[0.97] disabled:opacity-40 transition-all"
className="w-full min-h-[44px] flex items-center justify-center gap-2 rounded-lg bg-[#22d3ee] text-white px-4 py-2 text-sm font-semibold hover:brightness-110 active:scale-[0.98] disabled:opacity-40 transition-all"
>
{isGenerating ? (
<Loader2 size={14} className="animate-spin" />
@@ -121,12 +121,12 @@ export function InSessionScriptGenerator({
{/* Generated script display */}
{generatedScript && (
<>
<div className="relative rounded-lg bg-card/80 border border-border overflow-hidden">
<div className="flex items-center justify-between px-3 py-1.5 border-b border-border/50">
<span className="text-xs text-muted-foreground font-mono">PowerShell</span>
<div className="relative rounded-lg bg-[#14161d]/80 border border-[#1e2130] overflow-hidden">
<div className="flex items-center justify-between px-3 py-1.5 border-b border-[#1e2130]/50">
<span className="text-xs text-[#848b9b] font-mono">PowerShell</span>
<button
onClick={handleCopy}
className="flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors"
className="flex items-center gap-1 text-xs text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
>
{copied ? <Check size={12} className="text-emerald-400" /> : <Copy size={12} />}
{copied ? 'Copied' : 'Copy'}
@@ -141,13 +141,13 @@ export function InSessionScriptGenerator({
<div className="flex flex-col gap-2 pt-1 sm:flex-row">
<button
onClick={() => handleContinue(true)}
className="flex-1 min-h-[44px] rounded-lg bg-primary/10 border border-primary/20 px-4 py-2 text-sm font-medium text-primary hover:bg-primary/20 transition-colors"
className="flex-1 min-h-[44px] rounded-lg bg-[rgba(34,211,238,0.10)] border border-primary/20 px-4 py-2 text-sm font-medium text-[#22d3ee] hover:bg-primary/20 transition-colors"
>
Script worked continue
</button>
<button
onClick={() => handleContinue(false)}
className="flex-1 min-h-[44px] rounded-lg bg-card/50 border border-border px-4 py-2 text-sm font-medium text-foreground hover:bg-card transition-colors"
className="flex-1 min-h-[44px] rounded-lg bg-[#14161d]/50 border border-[#1e2130] px-4 py-2 text-sm font-medium text-[#e2e5eb] hover:bg-[#14161d] transition-colors"
>
Didn't resolve it
</button>

View File

@@ -5,7 +5,7 @@ const TYPE_CONFIG = {
new_flow: { label: 'New Flow', color: 'text-emerald-400 bg-emerald-400/10 border-emerald-400/20', icon: Sparkles },
enhancement: { label: 'Enhancement', color: 'text-amber-400 bg-amber-400/10 border-amber-400/20', icon: ArrowUpRight },
branch_addition: { label: 'Branch', color: 'text-blue-400 bg-blue-400/10 border-blue-400/20', icon: GitBranch },
auto_reinforced: { label: 'Reinforced', color: 'text-muted-foreground bg-card border-border', icon: Sparkles },
auto_reinforced: { label: 'Reinforced', color: 'text-[#848b9b] bg-[#14161d] border-[#1e2130]', icon: Sparkles },
} as const
interface ProposalCardProps {
@@ -24,24 +24,24 @@ export function ProposalCard({ proposal, isSelected, onClick }: ProposalCardProp
className={`w-full text-left rounded-xl border p-3 space-y-2 transition-all ${
isSelected
? 'border-primary/30 bg-primary/5'
: 'border-[rgba(255,255,255,0.06)] bg-[rgba(24,26,31,0.55)] hover:border-[rgba(255,255,255,0.12)]'
: 'border-[rgba(255,255,255,0.06)] bg-[#14161d] hover:border-[rgba(255,255,255,0.12)]'
}`}
>
<div className="flex items-start justify-between gap-2">
<p className="text-sm font-semibold text-foreground line-clamp-2">{proposal.title}</p>
<span className={`shrink-0 flex items-center gap-1 rounded-md border px-1.5 py-0.5 font-label text-[0.5625rem] uppercase tracking-wider ${typeConfig.color}`}>
<p className="text-sm font-semibold text-[#e2e5eb] line-clamp-2">{proposal.title}</p>
<span className={`shrink-0 flex items-center gap-1 rounded-md border px-1.5 py-0.5 font-sans text-xs text-[0.5625rem] uppercase tracking-wider ${typeConfig.color}`}>
<TypeIcon size={10} />
{typeConfig.label}
</span>
</div>
{proposal.description && (
<p className="text-xs text-muted-foreground line-clamp-2">{proposal.description}</p>
<p className="text-xs text-[#848b9b] line-clamp-2">{proposal.description}</p>
)}
<div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground">
<div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-[#848b9b]">
{proposal.problem_domain && (
<span className="font-label rounded-md bg-primary/10 px-1.5 py-0.5 text-[0.5625rem] uppercase tracking-wider text-primary">
<span className="font-sans text-xs rounded-md bg-[rgba(34,211,238,0.10)] px-1.5 py-0.5 text-[0.5625rem] uppercase tracking-wider text-[#22d3ee]">
{proposal.problem_domain}
</span>
)}
@@ -53,7 +53,7 @@ export function ProposalCard({ proposal, isSelected, onClick }: ProposalCardProp
<Clock size={10} />
{new Date(proposal.created_at).toLocaleDateString()}
</span>
<span className="text-primary">
<span className="text-[#22d3ee]">
{Math.round(proposal.confidence_score * 100)}%
</span>
</div>

View File

@@ -61,13 +61,13 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
<div className="flex h-full flex-col">
{/* Header */}
<div className="border-b px-6 py-4" style={{ borderColor: 'var(--glass-border)' }}>
<h2 className="font-heading text-lg font-semibold text-foreground">{proposal.title}</h2>
<h2 className="font-heading text-lg font-semibold text-[#e2e5eb]">{proposal.title}</h2>
{proposal.description && (
<p className="mt-1 text-sm text-muted-foreground">{proposal.description}</p>
<p className="mt-1 text-sm text-[#848b9b]">{proposal.description}</p>
)}
<div className="mt-3 flex flex-wrap items-center gap-3 text-xs text-muted-foreground">
<div className="mt-3 flex flex-wrap items-center gap-3 text-xs text-[#848b9b]">
{proposal.problem_domain && (
<span className="font-label rounded-md bg-primary/10 px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-primary">
<span className="font-sans text-xs rounded-md bg-[rgba(34,211,238,0.10)] px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-[#22d3ee]">
{proposal.problem_domain}
</span>
)}
@@ -89,12 +89,12 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
{/* Content */}
<div className="flex-1 overflow-y-auto p-6 space-y-5">
{/* Source session link */}
<div className="glass-card-static p-4">
<h4 className="font-label text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-2">Source Session</h4>
<div className="card-flat p-4">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-2">Source Session</h4>
<Link
to={`/pilot/${proposal.source_session_id}`}
target="_blank"
className="flex items-center gap-2 text-sm text-primary hover:underline"
className="flex items-center gap-2 text-sm text-[#22d3ee] hover:underline"
>
<ExternalLink size={12} />
View session that generated this proposal
@@ -105,16 +105,16 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
{proposal.proposed_diff && (() => {
const diff = proposal.proposed_diff as { diff_description?: string; new_nodes?: Array<{ title?: string; question?: string; description?: string }> }
return (
<div className="glass-card-static border-l-2 border-l-amber-500 p-4">
<h4 className="font-label text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-2">Proposed Changes</h4>
<div className="card-flat border-l-2 border-l-amber-500 p-4">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-2">Proposed Changes</h4>
{diff.diff_description && (
<p className="text-sm text-foreground">{diff.diff_description}</p>
<p className="text-sm text-[#e2e5eb]">{diff.diff_description}</p>
)}
{diff.new_nodes && diff.new_nodes.length > 0 && (
<div className="mt-3 space-y-1.5">
<p className="text-xs font-medium text-muted-foreground">New nodes:</p>
<p className="text-xs font-medium text-[#848b9b]">New nodes:</p>
{diff.new_nodes.map((node, i) => (
<div key={i} className="rounded-lg bg-emerald-500/5 border border-emerald-500/10 px-3 py-2 text-xs text-foreground">
<div key={i} className="rounded-lg bg-emerald-500/5 border border-emerald-500/10 px-3 py-2 text-xs text-[#e2e5eb]">
<span className="text-emerald-400">+ </span>
{node.title || node.question || node.description || 'New node'}
</div>
@@ -126,16 +126,16 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
})()}
{/* Flow data preview */}
<div className="glass-card-static p-4">
<div className="card-flat p-4">
<button
onClick={() => setShowFlowData(!showFlowData)}
className="flex items-center gap-1.5 font-label text-[0.625rem] uppercase tracking-wider text-[#5a6170] hover:text-foreground transition-colors"
className="flex items-center gap-1.5 font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] hover:text-[#e2e5eb] transition-colors"
>
{showFlowData ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
Flow Data (JSON)
</button>
{showFlowData && (
<pre className="mt-3 max-h-[400px] overflow-auto rounded-lg bg-card/80 p-3 text-xs text-muted-foreground font-mono">
<pre className="mt-3 max-h-[400px] overflow-auto rounded-lg bg-[#14161d]/80 p-3 text-xs text-[#848b9b] font-mono">
{JSON.stringify(proposal.proposed_flow_data, null, 2)}
</pre>
)}
@@ -143,8 +143,8 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
{/* Supporting sessions */}
{proposal.supporting_session_ids.length > 1 && (
<div className="glass-card-static p-4">
<h4 className="font-label text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-2">
<div className="card-flat p-4">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-2">
Supporting Sessions ({proposal.supporting_session_ids.length})
</h4>
<div className="space-y-1">
@@ -153,7 +153,7 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
key={sid}
to={`/pilot/${sid}`}
target="_blank"
className="block text-xs text-primary hover:underline truncate"
className="block text-xs text-[#22d3ee] hover:underline truncate"
>
{sid}
</Link>
@@ -164,14 +164,14 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
{/* Review info (for already-reviewed proposals) */}
{proposal.reviewed_at && (
<div className="glass-card-static p-4">
<h4 className="font-label text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-2">Review</h4>
<p className="text-sm text-foreground">
<div className="card-flat p-4">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-2">Review</h4>
<p className="text-sm text-[#e2e5eb]">
<span className="capitalize">{proposal.status}</span> on{' '}
{new Date(proposal.reviewed_at).toLocaleString()}
</p>
{proposal.reviewer_notes && (
<p className="mt-1 text-xs text-muted-foreground">{proposal.reviewer_notes}</p>
<p className="mt-1 text-xs text-[#848b9b]">{proposal.reviewer_notes}</p>
)}
</div>
)}
@@ -180,15 +180,14 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
{/* Review actions bar */}
{canReview && (
<div
className="border-t px-5 py-3 space-y-3"
style={{ borderColor: 'var(--glass-border)', background: 'rgba(16, 17, 20, 0.8)', backdropFilter: 'blur(12px)' }}
className="border-t border-[#1e2130] bg-[#14161d] px-5 py-3 space-y-3"
>
{/* Notes input */}
<input
value={reviewNotes}
onChange={(e) => setReviewNotes(e.target.value)}
placeholder="Reviewer notes (optional)"
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none"
className="w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2 text-sm text-[#e2e5eb] placeholder:text-[#848b9b] focus:border-[rgba(6,182,212,0.3)] focus:outline-none"
/>
{/* Action buttons */}
@@ -203,14 +202,14 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
Approve & Publish
</button>
) : (
<span className="text-xs text-muted-foreground italic px-2">
<span className="text-xs text-[#848b9b] italic px-2">
Enhancement proposals require Edit & Publish
</span>
)}
<button
onClick={handleEditAndPublish}
disabled={isSubmitting}
className="flex items-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 text-sm font-medium text-foreground hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 transition-colors"
className="flex items-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 text-sm font-medium text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 transition-colors"
>
<Pencil size={14} />
Edit & Publish
@@ -218,7 +217,7 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
<button
onClick={() => handleAction('dismiss')}
disabled={isSubmitting}
className="flex items-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 text-sm font-medium text-muted-foreground hover:text-foreground hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 transition-colors ml-auto"
className="flex items-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 text-sm font-medium text-[#848b9b] hover:text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 transition-colors ml-auto"
>
<EyeOff size={14} />
Dismiss

View File

@@ -38,12 +38,12 @@ export function SessionBriefing({
const pkg = escalationPackage
return (
<div className="glass-card-static border-l-2 border-l-amber-500 p-5 space-y-4">
<div className="card-flat border-l-2 border-l-amber-500 p-5 space-y-4">
<div>
<h3 className="font-heading text-base font-semibold text-foreground">
<h3 className="font-heading text-base font-semibold text-[#e2e5eb]">
Escalation from {originalEngineerName || 'another engineer'}
</h3>
<p className="mt-1 text-sm text-muted-foreground">
<p className="mt-1 text-sm text-[#848b9b]">
Review the briefing below, then choose how to proceed.
</p>
</div>
@@ -51,15 +51,15 @@ export function SessionBriefing({
{/* Problem */}
{pkg.problem_summary && (
<div>
<h4 className="font-label text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">Problem</h4>
<p className="text-sm text-foreground">{pkg.problem_summary}</p>
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">Problem</h4>
<p className="text-sm text-[#e2e5eb]">{pkg.problem_summary}</p>
</div>
)}
{/* Escalation reason */}
{pkg.escalation_reason && (
<div>
<h4 className="font-label text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">Why escalated</h4>
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">Why escalated</h4>
<p className="text-sm text-amber-400">{pkg.escalation_reason}</p>
</div>
)}
@@ -69,7 +69,7 @@ export function SessionBriefing({
<div>
<button
onClick={() => setShowSteps(!showSteps)}
className="flex items-center gap-1.5 font-label text-[0.625rem] uppercase tracking-wider text-[#5a6170] hover:text-foreground transition-colors"
className="flex items-center gap-1.5 font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] hover:text-[#e2e5eb] transition-colors"
>
{showSteps ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
Steps taken ({pkg.steps_tried.length})
@@ -77,10 +77,10 @@ export function SessionBriefing({
{showSteps && (
<div className="mt-2 space-y-1.5">
{pkg.steps_tried.map((step, i) => (
<div key={i} className="rounded-lg bg-card/50 px-3 py-2 text-xs">
<p className="text-foreground">{i + 1}. {step.description}</p>
<div key={i} className="rounded-lg bg-[#14161d]/50 px-3 py-2 text-xs">
<p className="text-[#e2e5eb]">{i + 1}. {step.description}</p>
{step.response && (
<p className="mt-0.5 text-primary"> {step.response}</p>
<p className="mt-0.5 text-[#22d3ee]"> {step.response}</p>
)}
</div>
))}
@@ -92,11 +92,11 @@ export function SessionBriefing({
{/* Remaining hypotheses */}
{pkg.remaining_hypotheses && pkg.remaining_hypotheses.length > 0 && (
<div>
<h4 className="font-label text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">Remaining hypotheses</h4>
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">Remaining hypotheses</h4>
<ul className="space-y-1">
{pkg.remaining_hypotheses.map((h, i) => (
<li key={i} className="text-sm text-foreground flex items-start gap-2">
<span className="text-primary mt-0.5"></span>
<li key={i} className="text-sm text-[#e2e5eb] flex items-start gap-2">
<span className="text-[#22d3ee] mt-0.5"></span>
{h}
</li>
))}
@@ -107,10 +107,10 @@ export function SessionBriefing({
{/* Suggested next steps */}
{pkg.suggested_next_steps && pkg.suggested_next_steps.length > 0 && (
<div>
<h4 className="font-label text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">Suggested next steps</h4>
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">Suggested next steps</h4>
<ul className="space-y-1">
{pkg.suggested_next_steps.map((s, i) => (
<li key={i} className="text-sm text-foreground flex items-start gap-2">
<li key={i} className="text-sm text-[#e2e5eb] flex items-start gap-2">
<span className="text-emerald-400 mt-0.5"></span>
{s}
</li>
@@ -125,7 +125,7 @@ export function SessionBriefing({
<button
onClick={onContinue}
disabled={isProcessing}
className="flex-1 flex items-center justify-center gap-2 rounded-lg bg-gradient-brand px-4 py-2.5 text-sm font-semibold text-[#101114] shadow-lg shadow-primary/20 hover:opacity-90 active:scale-[0.97] disabled:opacity-40 transition-all"
className="flex-1 flex items-center justify-center gap-2 rounded-lg bg-[#22d3ee] text-white px-4 py-2.5 text-sm font-semibold hover:brightness-110 active:scale-[0.98] disabled:opacity-40 transition-all"
>
<ArrowRight size={14} />
Continue Where They Left Off
@@ -133,7 +133,7 @@ export function SessionBriefing({
<button
onClick={() => setFreshMode(true)}
disabled={isProcessing}
className="flex-1 flex items-center justify-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2.5 text-sm font-medium text-foreground hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 transition-colors"
className="flex-1 flex items-center justify-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2.5 text-sm font-medium text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 transition-colors"
>
<MessageSquare size={14} />
Start Fresh With Context
@@ -145,7 +145,7 @@ export function SessionBriefing({
value={freshContext}
onChange={(e) => setFreshContext(e.target.value)}
placeholder="What additional information do you have, or what would you like to investigate first?"
className="w-full rounded-lg border border-border bg-card px-4 py-3 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none"
className="w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-4 py-3 text-sm text-[#e2e5eb] placeholder:text-[#848b9b] focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none"
rows={3}
autoFocus
/>
@@ -153,14 +153,14 @@ export function SessionBriefing({
<button
onClick={() => setFreshMode(false)}
disabled={isProcessing}
className="rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 text-sm font-medium text-foreground hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 transition-colors"
className="rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 text-sm font-medium text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 transition-colors"
>
Back
</button>
<button
onClick={() => freshContext.trim() && onFresh(freshContext.trim())}
disabled={!freshContext.trim() || isProcessing}
className="flex-1 flex items-center justify-center gap-2 rounded-lg bg-gradient-brand px-4 py-2 text-sm font-semibold text-[#101114] shadow-lg shadow-primary/20 hover:opacity-90 active:scale-[0.97] disabled:opacity-40 transition-all"
className="flex-1 flex items-center justify-center gap-2 rounded-lg bg-[#22d3ee] text-white px-4 py-2 text-sm font-semibold hover:brightness-110 active:scale-[0.98] disabled:opacity-40 transition-all"
>
<ArrowRight size={14} />
Start Diagnosis

View File

@@ -107,27 +107,27 @@ export function SessionDocView({
)}
{/* Header */}
<div className="glass-card-static p-3 sm:p-4 lg:p-5">
<div className="card-flat p-3 sm:p-4 lg:p-5">
<div className="flex items-start gap-3">
<span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary">
<span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-[rgba(34,211,238,0.10)] text-[#22d3ee]">
<FileText size={16} />
</span>
<div className="flex-1">
<h3 className="font-heading text-lg font-semibold text-foreground">Session Documentation</h3>
<p className="mt-1 text-sm text-muted-foreground">{documentation.problem_summary}</p>
<h3 className="font-heading text-lg font-semibold text-[#e2e5eb]">Session Documentation</h3>
<p className="mt-1 text-sm text-[#848b9b]">{documentation.problem_summary}</p>
<div className="mt-2 flex items-center gap-3 flex-wrap">
{documentation.problem_domain && (
<span className="font-label rounded-md bg-primary/10 px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-primary">
<span className="font-sans text-xs rounded-md bg-[rgba(34,211,238,0.10)] px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-[#22d3ee]">
{documentation.problem_domain}
</span>
)}
{documentation.duration_display && (
<span className="flex items-center gap-1 text-xs text-muted-foreground">
<span className="flex items-center gap-1 text-xs text-[#848b9b]">
<Clock size={12} />
{documentation.duration_display}
</span>
)}
<span className="text-xs text-muted-foreground">
<span className="text-xs text-[#848b9b]">
{documentation.total_steps} steps
</span>
</div>
@@ -137,49 +137,49 @@ export function SessionDocView({
{/* Outcome */}
{(documentation.resolution_summary || documentation.escalation_reason) && (
<div className={`glass-card-static p-4 border-l-2 ${documentation.resolution_summary ? 'border-l-emerald-500' : 'border-l-amber-500'}`}>
<div className={`card-flat p-4 border-l-2 ${documentation.resolution_summary ? 'border-l-emerald-500' : 'border-l-amber-500'}`}>
<div className="flex items-center gap-2 mb-1">
{documentation.resolution_summary ? (
<CheckCircle2 size={14} className="text-emerald-400" />
) : (
<ArrowUpRight size={14} className="text-amber-400" />
)}
<span className="font-label text-[0.625rem] uppercase tracking-wider text-muted-foreground">
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#848b9b]">
{documentation.resolution_summary ? 'Resolved' : 'Escalated'}
</span>
</div>
<p className="text-sm text-foreground">
<p className="text-sm text-[#e2e5eb]">
{documentation.resolution_summary || documentation.escalation_reason}
</p>
</div>
)}
{/* Intake summary */}
<div className="glass-card-static p-3 sm:p-4">
<h4 className="font-label text-[0.625rem] uppercase tracking-wider text-muted-foreground mb-2">
<div className="card-flat p-3 sm:p-4">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#848b9b] mb-2">
Original intake
</h4>
<p className="text-sm text-foreground whitespace-pre-wrap">{documentation.intake_summary}</p>
<p className="text-sm text-[#e2e5eb] whitespace-pre-wrap">{documentation.intake_summary}</p>
</div>
{/* Diagnostic steps */}
<div className="space-y-2">
<h4 className="font-label text-[0.625rem] uppercase tracking-wider text-muted-foreground px-1">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#848b9b] px-1">
Diagnostic trail
</h4>
{documentation.diagnostic_steps.map((step) => (
<div key={step.step_number} className="glass-card-static p-3 sm:p-4">
<div key={step.step_number} className="card-flat p-3 sm:p-4">
<div className="flex items-start gap-3">
<span className="font-label flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-card text-[0.625rem] text-muted-foreground border border-border">
<span className="font-sans text-xs flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-[#14161d] text-[0.625rem] text-[#848b9b] border border-[#1e2130]">
{step.step_number}
</span>
<div className="flex-1">
<p className="text-sm text-foreground">{step.description}</p>
<p className="text-sm text-[#e2e5eb]">{step.description}</p>
{step.engineer_response && (
<p className="mt-1 text-xs text-primary"> {step.engineer_response}</p>
<p className="mt-1 text-xs text-[#22d3ee]"> {step.engineer_response}</p>
)}
{step.outcome && (
<p className="mt-1 text-xs text-muted-foreground">Outcome: {step.outcome}</p>
<p className="mt-1 text-xs text-[#848b9b]">Outcome: {step.outcome}</p>
)}
</div>
</div>
@@ -189,8 +189,8 @@ export function SessionDocView({
{/* Rating */}
{onRate && (
<div className="glass-card-static p-3 sm:p-4 text-center">
<p className="text-sm text-muted-foreground mb-2">How helpful was this session?</p>
<div className="card-flat p-3 sm:p-4 text-center">
<p className="text-sm text-[#848b9b] mb-2">How helpful was this session?</p>
<div className="flex items-center justify-center gap-1">
{[1, 2, 3, 4, 5].map((star) => (
<button
@@ -203,7 +203,7 @@ export function SessionDocView({
className={
(currentRating ?? 0) >= star
? 'fill-amber-400 text-amber-400'
: 'text-muted-foreground hover:text-amber-400'
: 'text-[#848b9b] hover:text-amber-400'
}
/>
</button>

View File

@@ -36,7 +36,7 @@ export function SessionTicketCard({ ticketId, ticketData, siteUrl }: SessionTick
return (
<div className="rounded-xl border border-primary/20 bg-primary/5 p-3 space-y-2">
<div className="flex items-start justify-between">
<h4 className="font-label text-[0.625rem] uppercase tracking-wider text-[#5a6170]">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170]">
Linked Ticket
</h4>
{ticketUrl && (
@@ -44,7 +44,7 @@ export function SessionTicketCard({ ticketId, ticketData, siteUrl }: SessionTick
href={ticketUrl}
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-primary transition-colors"
className="text-[#848b9b] hover:text-[#22d3ee] transition-colors"
title="Open in ConnectWise"
>
<ExternalLink size={12} />
@@ -52,14 +52,14 @@ export function SessionTicketCard({ ticketId, ticketData, siteUrl }: SessionTick
)}
</div>
<p className="text-sm font-semibold text-foreground">
<span className="text-primary">#{ticketId}</span>
<p className="text-sm font-semibold text-[#e2e5eb]">
<span className="text-[#22d3ee]">#{ticketId}</span>
{ticket?.summary && (
<span> {ticket.summary}</span>
)}
</p>
<div className="flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-muted-foreground">
<div className="flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-[#848b9b]">
{company?.name && (
<span className="flex items-center gap-1">
<Building2 size={10} />
@@ -81,13 +81,13 @@ export function SessionTicketCard({ ticketId, ticketData, siteUrl }: SessionTick
</div>
{configs && configs.length > 0 && (
<div className="border-t border-border/50 pt-2 mt-2">
<p className="font-label text-[0.5625rem] uppercase tracking-wider text-[#5a6170] mb-1">
<div className="border-t border-[#1e2130]/50 pt-2 mt-2">
<p className="font-sans text-xs text-[0.5625rem] uppercase tracking-wider text-[#5a6170] mb-1">
Devices
</p>
<div className="space-y-0.5">
{configs.slice(0, 3).map((cfg, i) => (
<div key={i} className="flex items-center gap-1.5 text-xs text-muted-foreground">
<div key={i} className="flex items-center gap-1.5 text-xs text-[#848b9b]">
<Cpu size={10} />
<span>{cfg.device_identifier}</span>
{cfg.type && <span className="text-[#5a6170]">({cfg.type})</span>}

View File

@@ -35,8 +35,8 @@ export function SimilarSessions({ sessionId }: SimilarSessionsProps) {
if (loading) {
return (
<div className="flex items-center gap-1.5 py-1">
<Loader2 size={10} className="animate-spin text-muted-foreground" />
<span className="text-[0.625rem] text-muted-foreground font-label">Loading similar sessions</span>
<Loader2 size={10} className="animate-spin text-[#848b9b]" />
<span className="text-[0.625rem] text-[#848b9b] font-sans text-xs">Loading similar sessions</span>
</div>
)
}
@@ -47,42 +47,42 @@ export function SimilarSessions({ sessionId }: SimilarSessionsProps) {
return (
<div className="space-y-2">
<h4 className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">
Similar Past Sessions
</h4>
{sessions.map((session) => (
<Link
key={session.id}
to={`/pilot/${session.id}`}
className="glass-card p-3 block hover:border-[rgba(255,255,255,0.12)] transition-all"
className="card-interactive p-3 block hover:border-[rgba(255,255,255,0.12)] transition-all"
>
<div className="flex items-start justify-between gap-2">
<p className="text-xs text-foreground line-clamp-2">
<p className="text-xs text-[#e2e5eb] line-clamp-2">
{session.problem_summary || 'Untitled session'}
</p>
<span className="text-[0.625rem] font-label text-primary shrink-0">
<span className="text-[0.625rem] font-sans text-xs text-[#22d3ee] shrink-0">
{Math.round(session.similarity * 100)}%
</span>
</div>
{session.resolution_summary && (
<p className="text-[0.625rem] text-muted-foreground mt-1 line-clamp-1">
<p className="text-[0.625rem] text-[#848b9b] mt-1 line-clamp-1">
{session.resolution_summary}
</p>
)}
<div className="flex items-center gap-2 mt-1.5">
{session.problem_domain && (
<span className="text-[0.5rem] font-label uppercase tracking-wider text-muted-foreground/70">
<span className="text-[0.5rem] font-sans text-xs uppercase tracking-wider text-[#848b9b]/70">
{session.problem_domain}
</span>
)}
<span
className={cn(
'text-[0.5rem] font-label uppercase',
'text-[0.5rem] font-sans text-xs uppercase',
session.status === 'resolved'
? 'text-emerald-400'
: session.status === 'escalated'
? 'text-amber-400'
: 'text-muted-foreground'
: 'text-[#848b9b]'
)}
>
{session.status}