refactor: migrate session, script-builder, account 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 02:08:57 -04:00
parent e4ef904707
commit 858f890ed3
30 changed files with 441 additions and 441 deletions

View File

@@ -36,27 +36,27 @@ export function DeleteAccountModal({ onClose }: Props) {
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4"> <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4">
<div className="glass-card-static w-full max-w-md p-6"> <div className="card-flat w-full max-w-md p-6">
<div className="flex items-center gap-2 text-rose-500 mb-4"> <div className="flex items-center gap-2 text-rose-500 mb-4">
<AlertTriangle className="h-5 w-5" /> <AlertTriangle className="h-5 w-5" />
<h2 className="text-lg font-semibold font-heading text-foreground">Delete Account</h2> <h2 className="text-lg font-semibold font-heading text-[#e2e5eb]">Delete Account</h2>
</div> </div>
<p className="text-sm text-muted-foreground mb-4"> <p className="text-sm text-[#848b9b] mb-4">
This action is <strong className="text-rose-400">permanent</strong>. Your account, data, This action is <strong className="text-rose-400">permanent</strong>. Your account, data,
and all associated flows will be permanently deleted. and all associated flows will be permanently deleted.
</p> </p>
<form onSubmit={handleDelete} className="space-y-4"> <form onSubmit={handleDelete} className="space-y-4">
<div> <div>
<label className="block text-sm font-medium text-foreground">Confirm Password</label> <label className="block text-sm font-medium text-[#e2e5eb]">Confirm Password</label>
<input <input
type="password" type="password"
value={password} value={password}
onChange={(e) => setPassword(e.target.value)} onChange={(e) => setPassword(e.target.value)}
required required
className={cn( className={cn(
'mt-1 block w-full rounded-[10px] border border-border bg-card px-3 py-2', 'mt-1 block w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2',
'text-foreground focus:border-primary focus:outline-hidden' 'text-[#e2e5eb] focus:border-primary focus:outline-hidden'
)} )}
/> />
</div> </div>
@@ -68,8 +68,8 @@ export function DeleteAccountModal({ onClose }: Props) {
type="button" type="button"
onClick={onClose} onClick={onClose}
className={cn( className={cn(
'rounded-[10px] px-4 py-2 text-sm font-medium', 'rounded-lg px-4 py-2 text-sm font-medium',
'bg-white/[0.04] border border-brand-border text-foreground' 'bg-white/[0.04] border border-brand-border text-[#e2e5eb]'
)} )}
> >
Cancel Cancel
@@ -78,7 +78,7 @@ export function DeleteAccountModal({ onClose }: Props) {
type="submit" type="submit"
disabled={isSubmitting || !password} disabled={isSubmitting || !password}
className={cn( className={cn(
'rounded-[10px] px-4 py-2 text-sm font-semibold', 'rounded-lg px-4 py-2 text-sm font-semibold',
'bg-rose-500 text-white hover:bg-rose-400 disabled:opacity-50' 'bg-rose-500 text-white hover:bg-rose-400 disabled:opacity-50'
)} )}
> >

View File

@@ -31,21 +31,21 @@ export function LeaveAccountModal({ accountName, onClose }: Props) {
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4"> <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4">
<div className="glass-card-static w-full max-w-md p-6"> <div className="card-flat w-full max-w-md p-6">
<div className="flex items-center gap-2 text-amber-400 mb-4"> <div className="flex items-center gap-2 text-amber-400 mb-4">
<AlertTriangle className="h-5 w-5" /> <AlertTriangle className="h-5 w-5" />
<h2 className="text-lg font-semibold font-heading text-foreground">Leave Account</h2> <h2 className="text-lg font-semibold font-heading text-[#e2e5eb]">Leave Account</h2>
</div> </div>
<p className="text-sm text-muted-foreground mb-4"> <p className="text-sm text-[#848b9b] mb-4">
Are you sure you want to leave <strong className="text-foreground">{accountName}</strong>? Are you sure you want to leave <strong className="text-[#e2e5eb]">{accountName}</strong>?
A new personal account will be created for you. A new personal account will be created for you.
</p> </p>
<div className="flex justify-end gap-3"> <div className="flex justify-end gap-3">
<button <button
onClick={onClose} onClick={onClose}
className={cn( className={cn(
'rounded-[10px] px-4 py-2 text-sm font-medium', 'rounded-lg px-4 py-2 text-sm font-medium',
'bg-white/[0.04] border border-brand-border text-foreground' 'bg-white/[0.04] border border-brand-border text-[#e2e5eb]'
)} )}
> >
Cancel Cancel
@@ -54,7 +54,7 @@ export function LeaveAccountModal({ accountName, onClose }: Props) {
onClick={handleLeave} onClick={handleLeave}
disabled={isSubmitting} disabled={isSubmitting}
className={cn( className={cn(
'rounded-[10px] px-4 py-2 text-sm font-semibold', 'rounded-lg px-4 py-2 text-sm font-semibold',
'bg-rose-500 text-white hover:bg-rose-400 disabled:opacity-50' 'bg-rose-500 text-white hover:bg-rose-400 disabled:opacity-50'
)} )}
> >

View File

@@ -173,16 +173,16 @@ export function NotificationSettings() {
{/* Section header */} {/* Section header */}
<div className="mb-6 flex items-center justify-between"> <div className="mb-6 flex items-center justify-between">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<Bell className="h-6 w-6 text-muted-foreground" /> <Bell className="h-6 w-6 text-[#848b9b]" />
<h2 className="text-xl font-semibold font-heading text-foreground">Notifications</h2> <h2 className="text-xl font-semibold font-heading text-[#e2e5eb]">Notifications</h2>
</div> </div>
<div className="relative" ref={dropdownRef}> <div className="relative" ref={dropdownRef}>
<button <button
onClick={() => setShowDropdown(!showDropdown)} onClick={() => setShowDropdown(!showDropdown)}
className={cn( className={cn(
'inline-flex items-center gap-2 rounded-[10px] px-4 py-2 text-sm font-medium', 'inline-flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium',
'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-foreground', 'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#e2e5eb]',
'hover:border-[rgba(255,255,255,0.12)] transition-all' 'hover:border-[rgba(255,255,255,0.12)] transition-all'
)} )}
> >
@@ -192,16 +192,16 @@ export function NotificationSettings() {
</button> </button>
{showDropdown && ( {showDropdown && (
<div className="absolute right-0 mt-1 z-20 w-48 rounded-xl border border-border bg-card shadow-xl"> <div className="absolute right-0 mt-1 z-20 w-48 rounded-xl border border-[#1e2130] bg-[#14161d] shadow-xl">
{(Object.entries(CHANNEL_LABELS) as [ChannelType, string][]).map(([key, label]) => { {(Object.entries(CHANNEL_LABELS) as [ChannelType, string][]).map(([key, label]) => {
const Icon = CHANNEL_ICONS[key] const Icon = CHANNEL_ICONS[key]
return ( return (
<button <button
key={key} key={key}
onClick={() => handleAddChannel(key)} onClick={() => handleAddChannel(key)}
className="flex w-full items-center gap-2.5 px-4 py-2.5 text-sm text-foreground hover:bg-[rgba(255,255,255,0.04)] first:rounded-t-xl last:rounded-b-xl transition-colors" className="flex w-full items-center gap-2.5 px-4 py-2.5 text-sm text-[#e2e5eb] hover:bg-[rgba(255,255,255,0.04)] first:rounded-t-xl last:rounded-b-xl transition-colors"
> >
<Icon className="h-4 w-4 text-muted-foreground" /> <Icon className="h-4 w-4 text-[#848b9b]" />
{label} {label}
</button> </button>
) )
@@ -214,15 +214,15 @@ export function NotificationSettings() {
{/* Loading */} {/* Loading */}
{loading && ( {loading && (
<div className="flex justify-center py-8"> <div className="flex justify-center py-8">
<Loader2 className="h-6 w-6 animate-spin text-muted-foreground" /> <Loader2 className="h-6 w-6 animate-spin text-[#848b9b]" />
</div> </div>
)} )}
{/* Empty state */} {/* Empty state */}
{!loading && configs.length === 0 && !addingChannel && ( {!loading && configs.length === 0 && !addingChannel && (
<div className="glass-card-static p-6 text-center"> <div className="card-flat p-6 text-center">
<Bell className="mx-auto h-8 w-8 text-muted-foreground/50 mb-3" /> <Bell className="mx-auto h-8 w-8 text-[#848b9b]/50 mb-3" />
<p className="text-sm text-muted-foreground"> <p className="text-sm text-[#848b9b]">
No notification channels configured. Add a channel to receive alerts for session events. No notification channels configured. Add a channel to receive alerts for session events.
</p> </p>
</div> </div>
@@ -234,11 +234,11 @@ export function NotificationSettings() {
{configs.map(config => { {configs.map(config => {
const Icon = CHANNEL_ICONS[config.channel] const Icon = CHANNEL_ICONS[config.channel]
return ( return (
<div key={config.id} className="glass-card-static p-5"> <div key={config.id} className="card-flat p-5">
{/* Header row */} {/* Header row */}
<div className="flex items-center gap-3 mb-4"> <div className="flex items-center gap-3 mb-4">
<Icon className="h-5 w-5 text-muted-foreground" /> <Icon className="h-5 w-5 text-[#848b9b]" />
<span className="text-sm font-medium text-foreground"> <span className="text-sm font-medium text-[#e2e5eb]">
{CHANNEL_LABELS[config.channel]} {CHANNEL_LABELS[config.channel]}
</span> </span>
<span <span
@@ -248,8 +248,8 @@ export function NotificationSettings() {
)} )}
/> />
<span className={cn( <span className={cn(
'text-xs font-label', 'text-xs font-sans text-xs',
config.is_active ? 'text-emerald-400' : 'text-muted-foreground' config.is_active ? 'text-emerald-400' : 'text-[#848b9b]'
)}> )}>
{config.is_active ? 'Active' : 'Inactive'} {config.is_active ? 'Active' : 'Inactive'}
</span> </span>
@@ -259,20 +259,20 @@ export function NotificationSettings() {
<div className="mb-4"> <div className="mb-4">
{config.webhook_url && ( {config.webhook_url && (
<div> <div>
<span className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">
Webhook URL Webhook URL
</span> </span>
<p className="mt-0.5 text-sm text-foreground font-mono"> <p className="mt-0.5 text-sm text-[#e2e5eb] font-mono">
{maskWebhookUrl(config.webhook_url)} {maskWebhookUrl(config.webhook_url)}
</p> </p>
</div> </div>
)} )}
{config.email_addresses && config.email_addresses.length > 0 && ( {config.email_addresses && config.email_addresses.length > 0 && (
<div> <div>
<span className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">
Email Addresses Email Addresses
</span> </span>
<p className="mt-0.5 text-sm text-foreground"> <p className="mt-0.5 text-sm text-[#e2e5eb]">
{config.email_addresses.join(', ')} {config.email_addresses.join(', ')}
</p> </p>
</div> </div>
@@ -281,7 +281,7 @@ export function NotificationSettings() {
{/* Event toggles */} {/* Event toggles */}
<div className="mb-4"> <div className="mb-4">
<span className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">
Events Events
</span> </span>
<div className="mt-2 grid gap-2 sm:grid-cols-2"> <div className="mt-2 grid gap-2 sm:grid-cols-2">
@@ -294,28 +294,28 @@ export function NotificationSettings() {
type="checkbox" type="checkbox"
checked={config.events_enabled[eventKey] ?? false} checked={config.events_enabled[eventKey] ?? false}
onChange={() => handleToggleEvent(config, eventKey)} onChange={() => handleToggleEvent(config, eventKey)}
className="h-3.5 w-3.5 rounded border-border bg-card text-primary focus:ring-primary/30 focus:ring-offset-0 cursor-pointer accent-[#06b6d4]" className="h-3.5 w-3.5 rounded border-[#1e2130] bg-[#14161d] text-primary focus:ring-primary/30 focus:ring-offset-0 cursor-pointer accent-[#06b6d4]"
/> />
<span className="text-sm text-foreground">{eventLabel}</span> <span className="text-sm text-[#e2e5eb]">{eventLabel}</span>
</label> </label>
))} ))}
</div> </div>
</div> </div>
{/* Action buttons */} {/* Action buttons */}
<div className="flex items-center gap-3 pt-2 border-t border-border"> <div className="flex items-center gap-3 pt-2 border-t border-[#1e2130]">
<button <button
onClick={() => handleToggleActive(config)} onClick={() => handleToggleActive(config)}
className={cn( className={cn(
'inline-flex items-center gap-1.5 rounded-[10px] px-3 py-1.5 text-sm font-medium', 'inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm font-medium',
'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-foreground', 'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#e2e5eb]',
'hover:border-[rgba(255,255,255,0.12)] transition-all' 'hover:border-[rgba(255,255,255,0.12)] transition-all'
)} )}
> >
{config.is_active ? ( {config.is_active ? (
<ToggleRight className="h-4 w-4 text-emerald-400" /> <ToggleRight className="h-4 w-4 text-emerald-400" />
) : ( ) : (
<ToggleLeft className="h-4 w-4 text-muted-foreground" /> <ToggleLeft className="h-4 w-4 text-[#848b9b]" />
)} )}
{config.is_active ? 'Disable' : 'Enable'} {config.is_active ? 'Disable' : 'Enable'}
</button> </button>
@@ -324,8 +324,8 @@ export function NotificationSettings() {
onClick={() => handleTest(config.id)} onClick={() => handleTest(config.id)}
disabled={testingId === config.id} disabled={testingId === config.id}
className={cn( className={cn(
'inline-flex items-center gap-1.5 rounded-[10px] px-3 py-1.5 text-sm font-medium', 'inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm font-medium',
'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-foreground', 'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#e2e5eb]',
'hover:border-[rgba(255,255,255,0.12)] transition-all', 'hover:border-[rgba(255,255,255,0.12)] transition-all',
'disabled:opacity-50 disabled:cursor-not-allowed' 'disabled:opacity-50 disabled:cursor-not-allowed'
)} )}
@@ -349,7 +349,7 @@ export function NotificationSettings() {
) : ( ) : (
<button <button
onClick={() => setConfirmDeleteId(config.id)} onClick={() => setConfirmDeleteId(config.id)}
className="ml-auto inline-flex items-center gap-1.5 text-sm text-muted-foreground hover:text-red-400 transition-colors" className="ml-auto inline-flex items-center gap-1.5 text-sm text-[#848b9b] hover:text-red-400 transition-colors"
> >
<Trash2 className="h-4 w-4" /> <Trash2 className="h-4 w-4" />
Remove Remove
@@ -362,20 +362,20 @@ export function NotificationSettings() {
{/* Inline add form */} {/* Inline add form */}
{addingChannel && ( {addingChannel && (
<div className="glass-card-static p-5"> <div className="card-flat p-5">
<div className="flex items-center gap-3 mb-4"> <div className="flex items-center gap-3 mb-4">
{(() => { {(() => {
const Icon = CHANNEL_ICONS[addingChannel] const Icon = CHANNEL_ICONS[addingChannel]
return <Icon className="h-5 w-5 text-muted-foreground" /> return <Icon className="h-5 w-5 text-[#848b9b]" />
})()} })()}
<span className="text-sm font-medium text-foreground"> <span className="text-sm font-medium text-[#e2e5eb]">
Add {CHANNEL_LABELS[addingChannel]} Add {CHANNEL_LABELS[addingChannel]}
</span> </span>
</div> </div>
{addingChannel === 'email' ? ( {addingChannel === 'email' ? (
<div> <div>
<label className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground"> <label className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">
Email Addresses Email Addresses
</label> </label>
<Input <Input
@@ -385,13 +385,13 @@ export function NotificationSettings() {
placeholder="user@example.com, team@example.com" placeholder="user@example.com, team@example.com"
className="mt-1" className="mt-1"
/> />
<p className="mt-1 text-xs text-muted-foreground"> <p className="mt-1 text-xs text-[#848b9b]">
Separate multiple addresses with commas Separate multiple addresses with commas
</p> </p>
</div> </div>
) : ( ) : (
<div> <div>
<label className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground"> <label className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">
Webhook URL Webhook URL
</label> </label>
<Input <Input
@@ -413,9 +413,9 @@ export function NotificationSettings() {
onClick={handleSaveNew} onClick={handleSaveNew}
disabled={isSaving} disabled={isSaving}
className={cn( className={cn(
'inline-flex items-center gap-2 rounded-[10px] px-5 py-2.5 text-sm font-semibold', 'inline-flex items-center gap-2 rounded-lg px-5 py-2.5 text-sm font-semibold',
'bg-gradient-brand text-[#101114] shadow-lg shadow-primary/20', 'bg-[#22d3ee] text-white',
'hover:opacity-90 active:scale-[0.97] transition-all', 'hover:brightness-110 active:scale-[0.98] transition-all',
'disabled:opacity-50 disabled:cursor-not-allowed' 'disabled:opacity-50 disabled:cursor-not-allowed'
)} )}
> >
@@ -424,7 +424,7 @@ export function NotificationSettings() {
</button> </button>
<button <button
onClick={() => setAddingChannel(null)} onClick={() => setAddingChannel(null)}
className="text-sm text-muted-foreground hover:text-foreground transition-colors" className="text-sm text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
> >
Cancel Cancel
</button> </button>

View File

@@ -40,27 +40,27 @@ export function TransferOwnershipModal({ members, onClose, onTransferred }: Prop
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4"> <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4">
<div className="glass-card-static w-full max-w-md p-6"> <div className="card-flat w-full max-w-md p-6">
<div className="flex items-center gap-2 text-amber-400 mb-4"> <div className="flex items-center gap-2 text-amber-400 mb-4">
<AlertTriangle className="h-5 w-5" /> <AlertTriangle className="h-5 w-5" />
<h2 className="text-lg font-semibold font-heading text-foreground">Transfer Ownership</h2> <h2 className="text-lg font-semibold font-heading text-[#e2e5eb]">Transfer Ownership</h2>
</div> </div>
<p className="text-sm text-muted-foreground mb-4"> <p className="text-sm text-[#848b9b] mb-4">
This will make the selected member the new account owner. You will become an engineer. This will make the selected member the new account owner. You will become an engineer.
</p> </p>
{nonOwnerMembers.length === 0 ? ( {nonOwnerMembers.length === 0 ? (
<p className="text-sm text-muted-foreground">No other members to transfer to.</p> <p className="text-sm text-[#848b9b]">No other members to transfer to.</p>
) : ( ) : (
<form onSubmit={handleSubmit} className="space-y-4"> <form onSubmit={handleSubmit} className="space-y-4">
<div> <div>
<label className="block text-sm font-medium text-foreground">New Owner</label> <label className="block text-sm font-medium text-[#e2e5eb]">New Owner</label>
<select <select
value={targetUserId} value={targetUserId}
onChange={(e) => setTargetUserId(e.target.value)} onChange={(e) => setTargetUserId(e.target.value)}
className={cn( className={cn(
'mt-1 block w-full rounded-[10px] border border-border bg-card px-3 py-2', 'mt-1 block w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2',
'text-foreground focus:border-primary focus:outline-hidden' 'text-[#e2e5eb] focus:border-primary focus:outline-hidden'
)} )}
> >
{nonOwnerMembers.map((m) => ( {nonOwnerMembers.map((m) => (
@@ -69,15 +69,15 @@ export function TransferOwnershipModal({ members, onClose, onTransferred }: Prop
</select> </select>
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-foreground">Your Password</label> <label className="block text-sm font-medium text-[#e2e5eb]">Your Password</label>
<input <input
type="password" type="password"
value={password} value={password}
onChange={(e) => setPassword(e.target.value)} onChange={(e) => setPassword(e.target.value)}
required required
className={cn( className={cn(
'mt-1 block w-full rounded-[10px] border border-border bg-card px-3 py-2', 'mt-1 block w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2',
'text-foreground focus:border-primary focus:outline-hidden' 'text-[#e2e5eb] focus:border-primary focus:outline-hidden'
)} )}
/> />
</div> </div>
@@ -89,8 +89,8 @@ export function TransferOwnershipModal({ members, onClose, onTransferred }: Prop
type="button" type="button"
onClick={onClose} onClick={onClose}
className={cn( className={cn(
'rounded-[10px] px-4 py-2 text-sm font-medium', 'rounded-lg px-4 py-2 text-sm font-medium',
'bg-white/[0.04] border border-brand-border text-foreground' 'bg-white/[0.04] border border-brand-border text-[#e2e5eb]'
)} )}
> >
Cancel Cancel
@@ -99,7 +99,7 @@ export function TransferOwnershipModal({ members, onClose, onTransferred }: Prop
type="submit" type="submit"
disabled={isSubmitting || !password} disabled={isSubmitting || !password}
className={cn( className={cn(
'rounded-[10px] px-4 py-2 text-sm font-semibold', 'rounded-lg px-4 py-2 text-sm font-semibold',
'bg-amber-500 text-brand-dark hover:bg-amber-400', 'bg-amber-500 text-brand-dark hover:bg-amber-400',
'disabled:opacity-50' 'disabled:opacity-50'
)} )}

View File

@@ -63,16 +63,16 @@ export function SaveToLibraryDialog({
return ( return (
<div <div
className="fixed inset-0 z-50 bg-black/80 backdrop-blur-sm flex items-center justify-center" className="fixed inset-0 z-50 bg-black/80 flex items-center justify-center"
onClick={(e) => { if (e.target === e.currentTarget) onClose() }} onClick={(e) => { if (e.target === e.currentTarget) onClose() }}
> >
<div className="glass-card-static max-w-md w-full mx-4 rounded-xl overflow-hidden"> <div className="card-flat max-w-md w-full mx-4 rounded-xl overflow-hidden">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between px-5 py-3.5 border-b border-[rgba(255,255,255,0.06)]"> <div className="flex items-center justify-between px-5 py-3.5 border-b border-[rgba(255,255,255,0.06)]">
<h3 className="text-sm font-heading font-bold text-foreground">Save to Library</h3> <h3 className="text-sm font-heading font-bold text-[#e2e5eb]">Save to Library</h3>
<button <button
onClick={onClose} onClick={onClose}
className="p-1.5 rounded-lg text-muted-foreground hover:text-foreground hover:bg-[rgba(255,255,255,0.06)] transition-colors" className="p-1.5 rounded-lg text-[#848b9b] hover:text-[#e2e5eb] hover:bg-[rgba(255,255,255,0.06)] transition-colors"
> >
<X size={18} /> <X size={18} />
</button> </button>
@@ -82,7 +82,7 @@ export function SaveToLibraryDialog({
<form onSubmit={handleSubmit} className="p-5 space-y-4"> <form onSubmit={handleSubmit} className="p-5 space-y-4">
{/* Name */} {/* Name */}
<div> <div>
<label className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground mb-1.5 block"> <label className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b] mb-1.5 block">
Name * Name *
</label> </label>
<input <input
@@ -91,8 +91,8 @@ export function SaveToLibraryDialog({
onChange={(e) => setName(e.target.value)} onChange={(e) => setName(e.target.value)}
required required
className={cn( className={cn(
"w-full rounded-[10px] px-3 py-2 text-sm", "w-full rounded-lg px-3 py-2 text-sm",
"border border-border bg-card text-foreground placeholder:text-muted-foreground", "border border-[#1e2130] bg-[#14161d] text-[#e2e5eb] placeholder:text-[#848b9b]",
"focus:outline-none focus:border-[rgba(6,182,212,0.3)] transition-colors" "focus:outline-none focus:border-[rgba(6,182,212,0.3)] transition-colors"
)} )}
placeholder="Script name" placeholder="Script name"
@@ -101,7 +101,7 @@ export function SaveToLibraryDialog({
{/* Description */} {/* Description */}
<div> <div>
<label className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground mb-1.5 block"> <label className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b] mb-1.5 block">
Description Description
</label> </label>
<textarea <textarea
@@ -109,8 +109,8 @@ export function SaveToLibraryDialog({
onChange={(e) => setDescription(e.target.value)} onChange={(e) => setDescription(e.target.value)}
rows={3} rows={3}
className={cn( className={cn(
"w-full rounded-[10px] px-3 py-2 text-sm resize-none", "w-full rounded-lg px-3 py-2 text-sm resize-none",
"border border-border bg-card text-foreground placeholder:text-muted-foreground", "border border-[#1e2130] bg-[#14161d] text-[#e2e5eb] placeholder:text-[#848b9b]",
"focus:outline-none focus:border-[rgba(6,182,212,0.3)] transition-colors" "focus:outline-none focus:border-[rgba(6,182,212,0.3)] transition-colors"
)} )}
placeholder="What does this script do?" placeholder="What does this script do?"
@@ -119,15 +119,15 @@ export function SaveToLibraryDialog({
{/* Category */} {/* Category */}
<div> <div>
<label className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground mb-1.5 block"> <label className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b] mb-1.5 block">
Category Category
</label> </label>
<select <select
value={categoryId} value={categoryId}
onChange={(e) => setCategoryId(e.target.value)} onChange={(e) => setCategoryId(e.target.value)}
className={cn( className={cn(
"w-full rounded-[10px] px-3 py-2 text-sm", "w-full rounded-lg px-3 py-2 text-sm",
"border border-border bg-card text-foreground", "border border-[#1e2130] bg-[#14161d] text-[#e2e5eb]",
"focus:outline-none focus:border-[rgba(6,182,212,0.3)] transition-colors" "focus:outline-none focus:border-[rgba(6,182,212,0.3)] transition-colors"
)} )}
> >
@@ -144,9 +144,9 @@ export function SaveToLibraryDialog({
type="checkbox" type="checkbox"
checked={shareWithTeam} checked={shareWithTeam}
onChange={(e) => setShareWithTeam(e.target.checked)} onChange={(e) => setShareWithTeam(e.target.checked)}
className="w-4 h-4 rounded border-border bg-card text-cyan-500 focus:ring-cyan-500/20" className="w-4 h-4 rounded border-[#1e2130] bg-[#14161d] text-cyan-500 focus:ring-cyan-500/20"
/> />
<span className="text-sm text-foreground">Share with team</span> <span className="text-sm text-[#e2e5eb]">Share with team</span>
</label> </label>
{/* Error */} {/* Error */}
@@ -160,8 +160,8 @@ export function SaveToLibraryDialog({
type="button" type="button"
onClick={onClose} onClick={onClose}
className={cn( className={cn(
"px-4 py-2 rounded-[10px] text-sm font-medium transition-colors", "px-4 py-2 rounded-lg text-sm font-medium transition-colors",
"bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-foreground hover:border-[rgba(255,255,255,0.12)]" "bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)]"
)} )}
> >
Cancel Cancel
@@ -170,8 +170,8 @@ export function SaveToLibraryDialog({
type="submit" type="submit"
disabled={!name.trim() || isSaving} disabled={!name.trim() || isSaving}
className={cn( className={cn(
"flex items-center gap-2 px-4 py-2 rounded-[10px] text-sm font-semibold transition-all", "flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-semibold transition-all",
"bg-gradient-brand text-[#101114] hover:opacity-90 active:scale-[0.97]", "bg-[#22d3ee] text-white hover:brightness-110 active:scale-[0.98]",
"disabled:opacity-50 disabled:cursor-not-allowed" "disabled:opacity-50 disabled:cursor-not-allowed"
)} )}
> >

View File

@@ -30,13 +30,13 @@ export function ScriptBuilderChat({
return ( return (
<div className="flex-1 flex items-center justify-center p-8"> <div className="flex-1 flex items-center justify-center p-8">
<div className="text-center max-w-md"> <div className="text-center max-w-md">
<div className="w-14 h-14 rounded-2xl bg-gradient-brand flex items-center justify-center mx-auto mb-4"> <div className="w-14 h-14 rounded-2xl bg-[#22d3ee] flex items-center justify-center mx-auto mb-4">
<Bot size={28} className="text-[#101114]" /> <Bot size={28} className="text-white" />
</div> </div>
<h2 className="text-lg font-heading font-bold text-foreground mb-2"> <h2 className="text-lg font-heading font-bold text-[#e2e5eb] mb-2">
Script Builder Script Builder
</h2> </h2>
<p className="text-sm text-muted-foreground leading-relaxed"> <p className="text-sm text-[#848b9b] leading-relaxed">
Describe the script you need and AI will generate it for you. You can iterate on the script, Describe the script you need and AI will generate it for you. You can iterate on the script,
preview it, and save it to your library. preview it, and save it to your library.
</p> </p>
@@ -65,8 +65,8 @@ export function ScriptBuilderChat({
className={cn( className={cn(
"max-w-[85%] rounded-xl px-4 py-3 text-sm", "max-w-[85%] rounded-xl px-4 py-3 text-sm",
msg.role === 'user' msg.role === 'user'
? "bg-[rgba(6,182,212,0.08)] border border-[rgba(6,182,212,0.15)] text-foreground" ? "bg-[rgba(6,182,212,0.08)] border border-[rgba(6,182,212,0.15)] text-[#e2e5eb]"
: "glass-card-static" : "card-flat"
)} )}
> >
{msg.role === 'assistant' ? ( {msg.role === 'assistant' ? (
@@ -90,7 +90,7 @@ export function ScriptBuilderChat({
{msg.role === 'user' && ( {msg.role === 'user' && (
<div className="shrink-0 w-8 h-8 rounded-lg bg-[rgba(255,255,255,0.06)] flex items-center justify-center mt-0.5"> <div className="shrink-0 w-8 h-8 rounded-lg bg-[rgba(255,255,255,0.06)] flex items-center justify-center mt-0.5">
<User size={16} className="text-muted-foreground" /> <User size={16} className="text-[#848b9b]" />
</div> </div>
)} )}
</div> </div>
@@ -101,9 +101,9 @@ export function ScriptBuilderChat({
<div className="shrink-0 w-8 h-8 rounded-lg bg-[rgba(6,182,212,0.1)] flex items-center justify-center"> <div className="shrink-0 w-8 h-8 rounded-lg bg-[rgba(6,182,212,0.1)] flex items-center justify-center">
<Bot size={16} className="text-cyan-400" /> <Bot size={16} className="text-cyan-400" />
</div> </div>
<div className="glass-card-static rounded-xl px-4 py-3 text-sm flex items-center gap-2"> <div className="card-flat rounded-xl px-4 py-3 text-sm flex items-center gap-2">
<Loader2 size={14} className="animate-spin text-cyan-400" /> <Loader2 size={14} className="animate-spin text-cyan-400" />
<span className="text-muted-foreground">Generating script...</span> <span className="text-[#848b9b]">Generating script...</span>
</div> </div>
</div> </div>
)} )}

View File

@@ -55,7 +55,7 @@ export function ScriptBuilderInput({
rows={1} rows={1}
className={cn( className={cn(
"flex-1 resize-none rounded-xl px-4 py-2.5 text-sm", "flex-1 resize-none rounded-xl px-4 py-2.5 text-sm",
"bg-card border border-border text-foreground placeholder:text-muted-foreground", "bg-[#14161d] border border-[#1e2130] text-[#e2e5eb] placeholder:text-[#848b9b]",
"focus:outline-none focus:border-[rgba(6,182,212,0.3)] transition-colors", "focus:outline-none focus:border-[rgba(6,182,212,0.3)] transition-colors",
"disabled:opacity-50" "disabled:opacity-50"
)} )}
@@ -67,7 +67,7 @@ export function ScriptBuilderInput({
className={cn( className={cn(
"shrink-0 flex items-center justify-center w-10 h-10 rounded-xl transition-all", "shrink-0 flex items-center justify-center w-10 h-10 rounded-xl transition-all",
canSend canSend
? "bg-gradient-brand text-[#101114] hover:opacity-90 active:scale-[0.97]" ? "bg-[#22d3ee] text-white hover:brightness-110 active:scale-[0.98]"
: "bg-[rgba(255,255,255,0.04)] text-[#5a6170] cursor-not-allowed" : "bg-[rgba(255,255,255,0.04)] text-[#5a6170] cursor-not-allowed"
)} )}
> >

View File

@@ -55,11 +55,11 @@ export function ScriptCodeBlock({
<div className="mt-3 rounded-lg border bg-[rgba(0,0,0,0.3)] border-[rgba(255,255,255,0.06)] overflow-hidden"> <div className="mt-3 rounded-lg border bg-[rgba(0,0,0,0.3)] border-[rgba(255,255,255,0.06)] overflow-hidden">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between px-3 py-2 border-b border-[rgba(255,255,255,0.06)]"> <div className="flex items-center justify-between px-3 py-2 border-b border-[rgba(255,255,255,0.06)]">
<span className="font-label text-xs text-cyan-400 truncate"> <span className="font-mono text-xs text-cyan-400 truncate">
{filename || 'script'} {filename || 'script'}
</span> </span>
{lineCount != null && ( {lineCount != null && (
<span className="font-label text-[0.625rem] text-muted-foreground ml-2 shrink-0"> <span className="font-mono text-[0.625rem] text-[#848b9b] ml-2 shrink-0">
{lineCount} lines {lineCount} lines
</span> </span>
)} )}
@@ -85,7 +85,7 @@ export function ScriptCodeBlock({
{previewLines} {previewLines}
</SyntaxHighlighter> </SyntaxHighlighter>
{remainingLines > 0 && ( {remainingLines > 0 && (
<div className="px-3 pb-2 font-label text-[0.625rem] text-[#5a6170]"> <div className="px-3 pb-2 font-mono text-[0.625rem] text-[#5a6170]">
{"··· "}{remainingLines} more line{remainingLines !== 1 ? 's' : ''} {"··· "}{remainingLines} more line{remainingLines !== 1 ? 's' : ''}
</div> </div>
)} )}
@@ -96,8 +96,8 @@ export function ScriptCodeBlock({
<button <button
onClick={onViewFull} onClick={onViewFull}
className={cn( className={cn(
"flex items-center gap-1.5 px-3 py-1.5 rounded-[10px] text-xs font-semibold transition-all", "flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-semibold transition-all",
"bg-gradient-brand text-[#101114] hover:opacity-90 active:scale-[0.97]" "bg-[#22d3ee] text-white hover:brightness-110 active:scale-[0.98]"
)} )}
> >
<Eye size={14} /> <Eye size={14} />
@@ -106,8 +106,8 @@ export function ScriptCodeBlock({
<button <button
onClick={handleCopy} onClick={handleCopy}
className={cn( className={cn(
"flex items-center gap-1.5 px-3 py-1.5 rounded-[10px] text-xs font-medium transition-colors", "flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition-colors",
"bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-foreground hover:border-[rgba(255,255,255,0.12)]" "bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)]"
)} )}
> >
{copied ? <Check size={14} className="text-emerald-400" /> : <Copy size={14} />} {copied ? <Check size={14} className="text-emerald-400" /> : <Copy size={14} />}
@@ -116,7 +116,7 @@ export function ScriptCodeBlock({
<button <button
onClick={(e) => { e.stopPropagation(); onSave() }} onClick={(e) => { e.stopPropagation(); onSave() }}
className={cn( className={cn(
"flex items-center gap-1.5 px-3 py-1.5 rounded-[10px] text-xs font-medium transition-colors", "flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition-colors",
"bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 hover:bg-emerald-500/15" "bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 hover:bg-emerald-500/15"
)} )}
> >

View File

@@ -55,17 +55,17 @@ export function ScriptPreviewModal({
return ( return (
<div <div
className="fixed inset-0 z-50 bg-black/80 backdrop-blur-sm flex items-center justify-center" className="fixed inset-0 z-50 bg-black/80 flex items-center justify-center"
onClick={(e) => { if (e.target === e.currentTarget) onClose() }} onClick={(e) => { if (e.target === e.currentTarget) onClose() }}
> >
<div className="bg-[#18191f] rounded-xl border border-[rgba(255,255,255,0.08)] max-w-[900px] w-full mx-4 max-h-[85vh] flex flex-col"> <div className="bg-[#18191f] rounded-xl border border-[rgba(255,255,255,0.08)] max-w-[900px] w-full mx-4 max-h-[85vh] flex flex-col">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between px-5 py-3.5 border-b border-[rgba(255,255,255,0.06)]"> <div className="flex items-center justify-between px-5 py-3.5 border-b border-[rgba(255,255,255,0.06)]">
<div className="flex items-center gap-3 min-w-0"> <div className="flex items-center gap-3 min-w-0">
<span className="font-label text-sm text-cyan-400 truncate"> <span className="font-mono text-sm text-cyan-400 truncate">
{filename || 'script'} {filename || 'script'}
</span> </span>
<span className="shrink-0 font-label text-[0.625rem] uppercase tracking-wider px-2 py-0.5 rounded-full bg-[rgba(255,255,255,0.06)] text-muted-foreground"> <span className="shrink-0 font-mono text-[0.625rem] uppercase tracking-wider px-2 py-0.5 rounded-full bg-[rgba(255,255,255,0.06)] text-[#848b9b]">
{LANGUAGE_LABELS[language] || language} {LANGUAGE_LABELS[language] || language}
</span> </span>
</div> </div>
@@ -73,8 +73,8 @@ export function ScriptPreviewModal({
<button <button
onClick={handleCopy} onClick={handleCopy}
className={cn( className={cn(
"flex items-center gap-1.5 px-3 py-1.5 rounded-[10px] text-xs font-medium transition-colors", "flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition-colors",
"bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-foreground hover:border-[rgba(255,255,255,0.12)]" "bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)]"
)} )}
> >
{copied ? <Check size={14} className="text-emerald-400" /> : <Copy size={14} />} {copied ? <Check size={14} className="text-emerald-400" /> : <Copy size={14} />}
@@ -83,7 +83,7 @@ export function ScriptPreviewModal({
<button <button
onClick={onSave} onClick={onSave}
className={cn( className={cn(
"flex items-center gap-1.5 px-3 py-1.5 rounded-[10px] text-xs font-medium transition-colors", "flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition-colors",
"bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 hover:bg-emerald-500/15" "bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 hover:bg-emerald-500/15"
)} )}
> >
@@ -92,7 +92,7 @@ export function ScriptPreviewModal({
</button> </button>
<button <button
onClick={onClose} onClick={onClose}
className="p-1.5 rounded-lg text-muted-foreground hover:text-foreground hover:bg-[rgba(255,255,255,0.06)] transition-colors" className="p-1.5 rounded-lg text-[#848b9b] hover:text-[#e2e5eb] hover:bg-[rgba(255,255,255,0.06)] transition-colors"
> >
<X size={18} /> <X size={18} />
</button> </button>
@@ -126,14 +126,14 @@ export function ScriptPreviewModal({
{/* Footer */} {/* Footer */}
<div className="flex items-center justify-between px-5 py-3 border-t border-[rgba(255,255,255,0.06)]"> <div className="flex items-center justify-between px-5 py-3 border-t border-[rgba(255,255,255,0.06)]">
<span className="font-label text-[0.625rem] text-muted-foreground"> <span className="font-mono text-[0.625rem] text-[#848b9b]">
{lineCount} line{lineCount !== 1 ? 's' : ''} {lineCount} line{lineCount !== 1 ? 's' : ''}
</span> </span>
<button <button
onClick={onClose} onClick={onClose}
className={cn( className={cn(
"px-4 py-1.5 rounded-[10px] text-xs font-medium transition-colors", "px-4 py-1.5 rounded-lg text-xs font-medium transition-colors",
"bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-foreground hover:border-[rgba(255,255,255,0.12)]" "bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)]"
)} )}
> >
Close & Return to Chat Close & Return to Chat

View File

@@ -130,8 +130,8 @@ export function AddSupportingDataModal({ isOpen, onClose, sessionId, onAdded }:
className={cn( className={cn(
'flex flex-1 items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors', 'flex flex-1 items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors',
activeTab === 'text_snippet' activeTab === 'text_snippet'
? 'bg-card text-foreground shadow-sm' ? 'bg-[#14161d] text-[#e2e5eb] shadow-sm'
: 'text-muted-foreground hover:text-foreground' : 'text-[#848b9b] hover:text-[#e2e5eb]'
)} )}
> >
<Code2 className="h-4 w-4" /> <Code2 className="h-4 w-4" />
@@ -143,8 +143,8 @@ export function AddSupportingDataModal({ isOpen, onClose, sessionId, onAdded }:
className={cn( className={cn(
'flex flex-1 items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors', 'flex flex-1 items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors',
activeTab === 'screenshot' activeTab === 'screenshot'
? 'bg-card text-foreground shadow-sm' ? 'bg-[#14161d] text-[#e2e5eb] shadow-sm'
: 'text-muted-foreground hover:text-foreground' : 'text-[#848b9b] hover:text-[#e2e5eb]'
)} )}
> >
<ImageIcon className="h-4 w-4" /> <ImageIcon className="h-4 w-4" />
@@ -154,7 +154,7 @@ export function AddSupportingDataModal({ isOpen, onClose, sessionId, onAdded }:
{/* Label */} {/* Label */}
<div className="mb-4"> <div className="mb-4">
<label htmlFor="sd-label" className="mb-1 block text-sm font-medium text-foreground"> <label htmlFor="sd-label" className="mb-1 block text-sm font-medium text-[#e2e5eb]">
Label Label
</label> </label>
<input <input
@@ -164,8 +164,8 @@ export function AddSupportingDataModal({ isOpen, onClose, sessionId, onAdded }:
onChange={(e) => setLabel(e.target.value)} onChange={(e) => setLabel(e.target.value)}
placeholder={activeTab === 'text_snippet' ? 'e.g. Error log output' : 'e.g. Blue screen photo'} placeholder={activeTab === 'text_snippet' ? 'e.g. Error log output' : 'e.g. Blue screen photo'}
className={cn( className={cn(
'w-full rounded-md border border-border bg-card px-3 py-2 text-sm', 'w-full rounded-md border border-[#1e2130] bg-[#14161d] px-3 py-2 text-sm',
'text-foreground placeholder:text-muted-foreground', 'text-[#e2e5eb] placeholder:text-[#848b9b]',
'focus:border-[rgba(6,182,212,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20' 'focus:border-[rgba(6,182,212,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20'
)} )}
/> />
@@ -174,7 +174,7 @@ export function AddSupportingDataModal({ isOpen, onClose, sessionId, onAdded }:
{/* Text Snippet Tab Content */} {/* Text Snippet Tab Content */}
{activeTab === 'text_snippet' && ( {activeTab === 'text_snippet' && (
<div className="mb-4"> <div className="mb-4">
<label htmlFor="sd-content" className="mb-1 block text-sm font-medium text-foreground"> <label htmlFor="sd-content" className="mb-1 block text-sm font-medium text-[#e2e5eb]">
Content Content
</label> </label>
<textarea <textarea
@@ -184,8 +184,8 @@ export function AddSupportingDataModal({ isOpen, onClose, sessionId, onAdded }:
placeholder="Paste log output, error messages, config snippets..." placeholder="Paste log output, error messages, config snippets..."
rows={8} rows={8}
className={cn( className={cn(
'w-full resize-y rounded-md border border-border bg-card px-3 py-2 text-sm', 'w-full resize-y rounded-md border border-[#1e2130] bg-[#14161d] px-3 py-2 text-sm',
'font-mono text-foreground placeholder:text-muted-foreground', 'font-mono text-[#e2e5eb] placeholder:text-[#848b9b]',
'focus:border-[rgba(6,182,212,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20' 'focus:border-[rgba(6,182,212,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20'
)} )}
/> />
@@ -195,17 +195,17 @@ export function AddSupportingDataModal({ isOpen, onClose, sessionId, onAdded }:
{/* Screenshot Tab Content */} {/* Screenshot Tab Content */}
{activeTab === 'screenshot' && ( {activeTab === 'screenshot' && (
<div className="mb-4" onPaste={handlePaste}> <div className="mb-4" onPaste={handlePaste}>
<label className="mb-1 block text-sm font-medium text-foreground"> <label className="mb-1 block text-sm font-medium text-[#e2e5eb]">
Image Image
</label> </label>
{imageBase64 ? ( {imageBase64 ? (
<div className="relative rounded-md border border-border bg-card p-2"> <div className="relative rounded-md border border-[#1e2130] bg-[#14161d] p-2">
<img <img
src={`data:${imageContentType};base64,${imageBase64}`} src={`data:${imageContentType};base64,${imageBase64}`}
alt="Preview" alt="Preview"
className="mx-auto max-h-48 rounded object-contain" className="mx-auto max-h-48 rounded object-contain"
/> />
<p className="mt-2 text-center text-xs text-muted-foreground">{imageFileName}</p> <p className="mt-2 text-center text-xs text-[#848b9b]">{imageFileName}</p>
<button <button
type="button" type="button"
onClick={() => { onClick={() => {
@@ -214,7 +214,7 @@ export function AddSupportingDataModal({ isOpen, onClose, sessionId, onAdded }:
setImageFileName(null) setImageFileName(null)
if (fileInputRef.current) fileInputRef.current.value = '' if (fileInputRef.current) fileInputRef.current.value = ''
}} }}
className="mt-2 w-full text-center text-xs text-muted-foreground hover:text-foreground" className="mt-2 w-full text-center text-xs text-[#848b9b] hover:text-[#e2e5eb]"
> >
Remove and choose another Remove and choose another
</button> </button>
@@ -223,13 +223,13 @@ export function AddSupportingDataModal({ isOpen, onClose, sessionId, onAdded }:
<div <div
onClick={() => fileInputRef.current?.click()} onClick={() => fileInputRef.current?.click()}
className={cn( className={cn(
'flex cursor-pointer flex-col items-center justify-center gap-2 rounded-md border-2 border-dashed border-border', 'flex cursor-pointer flex-col items-center justify-center gap-2 rounded-md border-2 border-dashed border-[#1e2130]',
'bg-card/50 py-10 transition-colors hover:border-muted-foreground' 'bg-[#14161d]/50 py-10 transition-colors hover:border-muted-foreground'
)} )}
> >
<Upload className="h-8 w-8 text-muted-foreground" /> <Upload className="h-8 w-8 text-[#848b9b]" />
<p className="text-sm text-muted-foreground">Click to upload or paste from clipboard</p> <p className="text-sm text-[#848b9b]">Click to upload or paste from clipboard</p>
<p className="text-xs text-muted-foreground">PNG, JPEG, or SVG - max 2MB</p> <p className="text-xs text-[#848b9b]">PNG, JPEG, or SVG - max 2MB</p>
</div> </div>
)} )}
<input <input

View File

@@ -40,7 +40,7 @@ export function CSATModal({ isOpen, onClose, sessionId }: CSATModalProps) {
return ( return (
<Modal isOpen={isOpen} onClose={handleSkip} title="How was this flow?" size="sm"> <Modal isOpen={isOpen} onClose={handleSkip} title="How was this flow?" size="sm">
<div className="space-y-4"> <div className="space-y-4">
<p className="text-sm text-muted-foreground"> <p className="text-sm text-[#848b9b]">
Your feedback helps flow authors improve troubleshooting paths. Your feedback helps flow authors improve troubleshooting paths.
</p> </p>
@@ -60,7 +60,7 @@ export function CSATModal({ isOpen, onClose, sessionId }: CSATModalProps) {
'transition-colors', 'transition-colors',
(hoveredRating || rating) >= value (hoveredRating || rating) >= value
? 'fill-yellow-400 text-yellow-400' ? 'fill-yellow-400 text-yellow-400'
: 'fill-none text-muted-foreground' : 'fill-none text-[#848b9b]'
)} )}
/> />
</button> </button>
@@ -74,21 +74,21 @@ export function CSATModal({ isOpen, onClose, sessionId }: CSATModalProps) {
placeholder="Any comments? (optional)" placeholder="Any comments? (optional)"
maxLength={500} maxLength={500}
rows={3} rows={3}
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20 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-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20 resize-none"
/> />
{/* Actions */} {/* Actions */}
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<button <button
onClick={handleSkip} onClick={handleSkip}
className="text-sm text-muted-foreground hover:text-foreground transition-colors" className="text-sm text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
> >
Skip Skip
</button> </button>
<button <button
onClick={handleSubmit} onClick={handleSubmit}
disabled={rating === 0 || submitting} disabled={rating === 0 || submitting}
className="rounded-lg bg-gradient-brand px-4 py-2 text-sm font-semibold text-white shadow-lg shadow-primary/20 hover:opacity-90 transition-opacity disabled:opacity-50" className="rounded-lg bg-[#22d3ee] text-white px-4 py-2 text-sm font-semibold hover:brightness-110 transition-opacity disabled:opacity-50"
> >
{submitting ? 'Submitting...' : 'Submit'} {submitting ? 'Submitting...' : 'Submit'}
</button> </button>

View File

@@ -47,7 +47,7 @@ export function ContinuationModal({
{/* Descendant Selection */} {/* Descendant Selection */}
{hasDescendants && ( {hasDescendants && (
<div> <div>
<p className="mb-4 text-sm text-muted-foreground"> <p className="mb-4 text-sm text-[#848b9b]">
Select the next step in your troubleshooting path: Select the next step in your troubleshooting path:
</p> </p>
@@ -58,20 +58,20 @@ export function ContinuationModal({
onClick={() => onSelectNode(node.id)} onClick={() => onSelectNode(node.id)}
title={`From: ${node.parentOptionLabel}`} title={`From: ${node.parentOptionLabel}`}
className={cn( className={cn(
'flex w-full items-center gap-3 rounded-lg border border-border p-3 text-left transition-colors', 'flex w-full items-center gap-3 rounded-lg border border-[#1e2130] p-3 text-left transition-colors',
'hover:border-border hover:bg-accent' 'hover:border-[#1e2130] hover:bg-accent'
)} )}
> >
<div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-accent"> <div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-accent">
{nodeTypeIcons[node.type]} {nodeTypeIcons[node.type]}
</div> </div>
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<p className="truncate font-medium text-foreground">{node.label}</p> <p className="truncate font-medium text-[#e2e5eb]">{node.label}</p>
<p className="text-xs text-muted-foreground"> <p className="text-xs text-[#848b9b]">
{nodeTypeLabels[node.type]} {nodeTypeLabels[node.type]}
</p> </p>
</div> </div>
<ArrowRight className="h-4 w-4 shrink-0 text-muted-foreground" /> <ArrowRight className="h-4 w-4 shrink-0 text-[#848b9b]" />
</button> </button>
))} ))}
</div> </div>
@@ -81,11 +81,11 @@ export function ContinuationModal({
{/* Divider */} {/* Divider */}
{hasDescendants && ( {hasDescendants && (
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<div className="h-px flex-1 bg-border" /> <div className="h-px flex-1 bg-[#1e2130]" />
<span className="text-xs font-medium uppercase tracking-wide text-muted-foreground"> <span className="text-xs font-medium uppercase tracking-wide text-[#848b9b]">
Or Or
</span> </span>
<div className="h-px flex-1 bg-border" /> <div className="h-px flex-1 bg-[#1e2130]" />
</div> </div>
)} )}
@@ -102,8 +102,8 @@ export function ContinuationModal({
<GitBranch className="h-5 w-5 text-amber-500" /> <GitBranch className="h-5 w-5 text-amber-500" />
</div> </div>
<div className="flex-1"> <div className="flex-1">
<p className="font-medium text-foreground">Build Custom Branch</p> <p className="font-medium text-[#e2e5eb]">Build Custom Branch</p>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-[#848b9b]">
Create your own troubleshooting path with custom steps Create your own troubleshooting path with custom steps
</p> </p>
</div> </div>

View File

@@ -73,9 +73,9 @@ export function ExportPreviewModal({
<Modal isOpen={isOpen} onClose={handleClose} title="Export Preview" size="xl"> <Modal isOpen={isOpen} onClose={handleClose} title="Export Preview" size="xl">
{/* Filename, format info, and controls */} {/* Filename, format info, and controls */}
<div className="mb-3 flex flex-wrap items-center justify-between gap-2"> <div className="mb-3 flex flex-wrap items-center justify-between gap-2">
<p className="text-sm text-muted-foreground"> <p className="text-sm text-[#848b9b]">
Filename: <span className="font-mono text-foreground">{filename}</span> Filename: <span className="font-mono text-[#e2e5eb]">{filename}</span>
<span className="ml-3 rounded bg-accent px-2 py-0.5 text-xs text-muted-foreground"> <span className="ml-3 rounded bg-accent px-2 py-0.5 text-xs text-[#848b9b]">
{format === 'markdown' ? 'Markdown' : format === 'html' ? 'HTML' : format === 'psa' ? 'PSA' : format === 'pdf' ? 'PDF' : 'Plain Text'} {format === 'markdown' ? 'Markdown' : format === 'html' ? 'HTML' : format === 'psa' ? 'PSA' : format === 'pdf' ? 'PDF' : 'Plain Text'}
</span> </span>
{isModified && ( {isModified && (
@@ -85,23 +85,23 @@ export function ExportPreviewModal({
<div className="flex flex-col items-end gap-1"> <div className="flex flex-col items-end gap-1">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
{onToggleSummary && ( {onToggleSummary && (
<label className="flex items-center gap-2 text-sm text-muted-foreground cursor-pointer"> <label className="flex items-center gap-2 text-sm text-[#848b9b] cursor-pointer">
<input <input
type="checkbox" type="checkbox"
checked={includeSummary} checked={includeSummary}
onChange={(e) => onToggleSummary(e.target.checked)} onChange={(e) => onToggleSummary(e.target.checked)}
className="h-4 w-4 rounded border-border bg-card" className="h-4 w-4 rounded border-[#1e2130] bg-[#14161d]"
/> />
Include Summary Include Summary
</label> </label>
)} )}
{onToggleRedaction && ( {onToggleRedaction && (
<label className="flex items-center gap-2 text-sm text-muted-foreground cursor-pointer"> <label className="flex items-center gap-2 text-sm text-[#848b9b] cursor-pointer">
<input <input
type="checkbox" type="checkbox"
checked={redactionEnabled} checked={redactionEnabled}
onChange={(e) => onToggleRedaction(e.target.checked)} onChange={(e) => onToggleRedaction(e.target.checked)}
className="h-4 w-4 rounded border-border bg-card" className="h-4 w-4 rounded border-[#1e2130] bg-[#14161d]"
/> />
Mask Sensitive Data Mask Sensitive Data
</label> </label>
@@ -118,13 +118,13 @@ export function ExportPreviewModal({
</p> </p>
)} )}
{redactionEnabled && redactionSummary && redactionSummary.total === 0 && ( {redactionEnabled && redactionSummary && redactionSummary.total === 0 && (
<p className="text-xs text-muted-foreground">No sensitive data detected</p> <p className="text-xs text-[#848b9b]">No sensitive data detected</p>
)} )}
{isModified && ( {isModified && (
<button <button
type="button" type="button"
onClick={handleReset} onClick={handleReset}
className="flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground" className="flex items-center gap-1 text-xs text-[#848b9b] hover:text-[#e2e5eb]"
title="Reset to original" title="Reset to original"
> >
<RotateCcw className="h-3 w-3" /> <RotateCcw className="h-3 w-3" />
@@ -137,15 +137,15 @@ export function ExportPreviewModal({
{format === 'pdf' ? ( {format === 'pdf' ? (
/* PDF download-only UI */ /* PDF download-only UI */
<div className="flex flex-col items-center justify-center py-12"> <div className="flex flex-col items-center justify-center py-12">
<FileDown className="mb-4 h-12 w-12 text-muted-foreground" /> <FileDown className="mb-4 h-12 w-12 text-[#848b9b]" />
<p className="text-muted-foreground mb-4">PDF exports are generated server-side with your team&apos;s branding.</p> <p className="text-[#848b9b] mb-4">PDF exports are generated server-side with your team&apos;s branding.</p>
<button <button
type="button" type="button"
onClick={onDownloadPdf} onClick={onDownloadPdf}
disabled={pdfLoading} disabled={pdfLoading}
className={cn( className={cn(
'inline-flex items-center gap-2 rounded-[10px] bg-gradient-brand px-6 py-3 text-sm font-semibold text-[#101114]', 'inline-flex items-center gap-2 rounded-lg bg-[#22d3ee] text-white px-6 py-3 text-sm font-semibold',
'hover:opacity-90 active:scale-[0.97] transition-all', 'hover:brightness-110 active:scale-[0.98] transition-all',
'disabled:opacity-60 disabled:cursor-not-allowed' 'disabled:opacity-60 disabled:cursor-not-allowed'
)} )}
> >
@@ -168,8 +168,8 @@ export function ExportPreviewModal({
value={editedContent} value={editedContent}
onChange={(e) => setEditedContent(e.target.value)} onChange={(e) => setEditedContent(e.target.value)}
className={cn( className={cn(
'h-96 w-full resize-y rounded-md border border-border bg-card p-4', 'h-96 w-full resize-y rounded-md border border-[#1e2130] bg-[#14161d] p-4',
'font-mono text-sm text-foreground', 'font-mono text-sm text-[#e2e5eb]',
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20' 'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20'
)} )}
/> />
@@ -180,8 +180,8 @@ export function ExportPreviewModal({
type="button" type="button"
onClick={handleCopy} onClick={handleCopy}
className={cn( className={cn(
'flex items-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium', 'flex items-center gap-2 rounded-md border border-[#1e2130] px-3 py-2 text-sm font-medium',
'text-muted-foreground hover:bg-accent hover:text-foreground', 'text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]',
'focus:outline-hidden focus:ring-2 focus:ring-primary/20' 'focus:outline-hidden focus:ring-2 focus:ring-primary/20'
)} )}
> >
@@ -201,8 +201,8 @@ export function ExportPreviewModal({
type="button" type="button"
onClick={handleDownload} onClick={handleDownload}
className={cn( className={cn(
'flex items-center gap-2 rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-3 py-2 text-sm font-medium', 'flex items-center gap-2 rounded-md bg-[#22d3ee] text-white px-3 py-2 text-sm font-medium',
'hover:opacity-90 focus:outline-hidden focus:ring-2 focus:ring-primary/20' 'hover:brightness-110 focus:outline-hidden focus:ring-2 focus:ring-primary/20'
)} )}
> >
<Download className="h-4 w-4" /> <Download className="h-4 w-4" />

View File

@@ -69,11 +69,11 @@ export function ForkTreeModal({
<div className="space-y-4"> <div className="space-y-4">
<div className="flex items-start gap-3 rounded-lg bg-accent/50 p-4"> <div className="flex items-start gap-3 rounded-lg bg-accent/50 p-4">
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-accent"> <div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-accent">
<GitFork className="h-5 w-5 text-foreground" /> <GitFork className="h-5 w-5 text-[#e2e5eb]" />
</div> </div>
<div> <div>
<p className="font-medium text-foreground">You've created a custom troubleshooting path!</p> <p className="font-medium text-[#e2e5eb]">You've created a custom troubleshooting path!</p>
<p className="mt-1 text-sm text-muted-foreground"> <p className="mt-1 text-sm text-[#848b9b]">
Save it as your own personal tree to reuse this troubleshooting flow in the future. Save it as your own personal tree to reuse this troubleshooting flow in the future.
</p> </p>
</div> </div>
@@ -81,7 +81,7 @@ export function ForkTreeModal({
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<label htmlFor="tree-name" className="mb-1.5 block text-sm font-medium text-foreground"> <label htmlFor="tree-name" className="mb-1.5 block text-sm font-medium text-[#e2e5eb]">
Tree Name <span className="text-red-400">*</span> Tree Name <span className="text-red-400">*</span>
</label> </label>
<Input <Input
@@ -94,8 +94,8 @@ export function ForkTreeModal({
</div> </div>
<div> <div>
<label htmlFor="tree-description" className="mb-1.5 block text-sm font-medium text-foreground"> <label htmlFor="tree-description" className="mb-1.5 block text-sm font-medium text-[#e2e5eb]">
Description <span className="text-muted-foreground">(optional)</span> Description <span className="text-[#848b9b]">(optional)</span>
</label> </label>
<Textarea <Textarea
id="tree-description" id="tree-description"
@@ -112,7 +112,7 @@ export function ForkTreeModal({
<p className="text-sm text-red-400">{error}</p> <p className="text-sm text-red-400">{error}</p>
)} )}
<p className="text-xs text-muted-foreground"> <p className="text-xs text-[#848b9b]">
The new tree will include your custom steps and will be saved to your personal tree library. The new tree will include your custom steps and will be saved to your personal tree library.
</p> </p>
</div> </div>

View File

@@ -28,8 +28,8 @@ export function PostStepActionModal({
return ( return (
<Modal isOpen={isOpen} onClose={onClose} title="What would you like to do?"> <Modal isOpen={isOpen} onClose={onClose} title="What would you like to do?">
<div className="space-y-3"> <div className="space-y-3">
<p className="mb-4 text-sm text-muted-foreground"> <p className="mb-4 text-sm text-[#848b9b]">
You've created: <strong className="text-foreground">{step.title}</strong> You've created: <strong className="text-[#e2e5eb]">{step.title}</strong>
</p> </p>
{/* Save for Later - Only show if not already from library */} {/* Save for Later - Only show if not already from library */}
@@ -38,7 +38,7 @@ export function PostStepActionModal({
onClick={onSaveForLater} onClick={onSaveForLater}
disabled={isSaving} disabled={isSaving}
className={cn( className={cn(
'w-full rounded-lg border border-border p-4 text-left transition-colors', 'w-full rounded-lg border border-[#1e2130] p-4 text-left transition-colors',
'hover:border-primary hover:bg-accent', 'hover:border-primary hover:bg-accent',
'disabled:cursor-not-allowed disabled:opacity-50' 'disabled:cursor-not-allowed disabled:opacity-50'
)} )}
@@ -48,8 +48,8 @@ export function PostStepActionModal({
<Bookmark className="h-5 w-5 text-blue-500" /> <Bookmark className="h-5 w-5 text-blue-500" />
</div> </div>
<div> <div>
<p className="font-medium text-foreground">Save for Later</p> <p className="font-medium text-[#e2e5eb]">Save for Later</p>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-[#848b9b]">
Add to your step library for future use Add to your step library for future use
</p> </p>
</div> </div>
@@ -62,8 +62,8 @@ export function PostStepActionModal({
onClick={onUseNow} onClick={onUseNow}
disabled={isSaving} disabled={isSaving}
className={cn( className={cn(
'w-full rounded-lg border border-border p-4 text-left transition-colors', 'w-full rounded-lg border border-[#1e2130] p-4 text-left transition-colors',
'hover:border-border hover:bg-accent', 'hover:border-[#1e2130] hover:bg-accent',
'disabled:cursor-not-allowed disabled:opacity-50' 'disabled:cursor-not-allowed disabled:opacity-50'
)} )}
> >
@@ -73,7 +73,7 @@ export function PostStepActionModal({
</div> </div>
<div> <div>
<p className="font-medium">Use Now</p> <p className="font-medium">Use Now</p>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-[#848b9b]">
Insert into this session and continue troubleshooting Insert into this session and continue troubleshooting
</p> </p>
</div> </div>
@@ -86,7 +86,7 @@ export function PostStepActionModal({
onClick={onBoth} onClick={onBoth}
disabled={isSaving} disabled={isSaving}
className={cn( className={cn(
'w-full rounded-lg border border-border p-4 text-left transition-colors', 'w-full rounded-lg border border-[#1e2130] p-4 text-left transition-colors',
'hover:border-primary hover:bg-accent', 'hover:border-primary hover:bg-accent',
'disabled:cursor-not-allowed disabled:opacity-50' 'disabled:cursor-not-allowed disabled:opacity-50'
)} )}
@@ -96,8 +96,8 @@ export function PostStepActionModal({
<BookmarkPlus className="h-5 w-5 text-purple-500" /> <BookmarkPlus className="h-5 w-5 text-purple-500" />
</div> </div>
<div> <div>
<p className="font-medium text-foreground">Do Both</p> <p className="font-medium text-[#e2e5eb]">Do Both</p>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-[#848b9b]">
Save to library AND use in this session Save to library AND use in this session
</p> </p>
</div> </div>
@@ -106,7 +106,7 @@ export function PostStepActionModal({
)} )}
{isSaving && ( {isSaving && (
<p className="text-center text-sm text-muted-foreground">Saving...</p> <p className="text-center text-sm text-[#848b9b]">Saving...</p>
)} )}
</div> </div>
</Modal> </Modal>

View File

@@ -36,21 +36,21 @@ export function SaveSessionAsTreeModal({
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-xs"> <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-xs">
<div className="bg-card border border-border w-full max-w-lg rounded-2xl p-6 shadow-lg"> <div className="bg-[#14161d] border border-[#1e2130] w-full max-w-lg rounded-lg p-6 shadow-lg">
{/* Header */} {/* Header */}
<div className="mb-4 flex items-center justify-between"> <div className="mb-4 flex items-center justify-between">
<h2 className="text-lg font-semibold text-foreground">Save Session as Tree</h2> <h2 className="text-lg font-semibold text-[#e2e5eb]">Save Session as Tree</h2>
<button <button
onClick={onClose} onClick={onClose}
disabled={isSaving} disabled={isSaving}
className="rounded-full p-1 text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-50" className="rounded-full p-1 text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb] disabled:opacity-50"
> >
<X className="h-5 w-5" /> <X className="h-5 w-5" />
</button> </button>
</div> </div>
{/* Info */} {/* Info */}
<p className="mb-4 text-sm text-muted-foreground"> <p className="mb-4 text-sm text-[#848b9b]">
Create a new tree from this session's path. The tree will be linked to the original tree as a fork. Create a new tree from this session's path. The tree will be linked to the original tree as a fork.
</p> </p>
@@ -58,8 +58,8 @@ export function SaveSessionAsTreeModal({
<form onSubmit={handleSubmit} className="space-y-4"> <form onSubmit={handleSubmit} className="space-y-4">
{/* Tree Name */} {/* Tree Name */}
<div> <div>
<label htmlFor="treeName" className="mb-1 block text-sm font-medium text-foreground"> <label htmlFor="treeName" className="mb-1 block text-sm font-medium text-[#e2e5eb]">
Tree Name <span className="text-muted-foreground">(optional)</span> Tree Name <span className="text-[#848b9b]">(optional)</span>
</label> </label>
<Input <Input
id="treeName" id="treeName"
@@ -74,8 +74,8 @@ export function SaveSessionAsTreeModal({
{/* Description */} {/* Description */}
<div> <div>
<label htmlFor="description" className="mb-1 block text-sm font-medium text-foreground"> <label htmlFor="description" className="mb-1 block text-sm font-medium text-[#e2e5eb]">
Description <span className="text-muted-foreground">(optional)</span> Description <span className="text-[#848b9b]">(optional)</span>
</label> </label>
<Textarea <Textarea
id="description" id="description"
@@ -89,7 +89,7 @@ export function SaveSessionAsTreeModal({
{/* Status */} {/* Status */}
<div> <div>
<label className="mb-2 block text-sm font-medium text-foreground">Status</label> <label className="mb-2 block text-sm font-medium text-[#e2e5eb]">Status</label>
<div className="flex gap-4"> <div className="flex gap-4">
<label className="flex cursor-pointer items-center gap-2"> <label className="flex cursor-pointer items-center gap-2">
<input <input
@@ -99,9 +99,9 @@ export function SaveSessionAsTreeModal({
checked={status === 'draft'} checked={status === 'draft'}
onChange={() => setStatus('draft')} onChange={() => setStatus('draft')}
disabled={isSaving} disabled={isSaving}
className="h-4 w-4 border-border text-foreground focus:ring-2 focus:ring-primary/20 focus:ring-offset-0" className="h-4 w-4 border-[#1e2130] text-[#e2e5eb] focus:ring-2 focus:ring-primary/20 focus:ring-offset-0"
/> />
<span className="text-sm text-foreground">Draft</span> <span className="text-sm text-[#e2e5eb]">Draft</span>
</label> </label>
<label className="flex cursor-pointer items-center gap-2"> <label className="flex cursor-pointer items-center gap-2">
<input <input
@@ -111,9 +111,9 @@ export function SaveSessionAsTreeModal({
checked={status === 'published'} checked={status === 'published'}
onChange={() => setStatus('published')} onChange={() => setStatus('published')}
disabled={isSaving} disabled={isSaving}
className="h-4 w-4 border-border text-foreground focus:ring-2 focus:ring-primary/20 focus:ring-offset-0" className="h-4 w-4 border-[#1e2130] text-[#e2e5eb] focus:ring-2 focus:ring-primary/20 focus:ring-offset-0"
/> />
<span className="text-sm text-foreground">Published</span> <span className="text-sm text-[#e2e5eb]">Published</span>
</label> </label>
</div> </div>
</div> </div>

View File

@@ -124,8 +124,8 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
onClick={() => setIsCollapsed(false)} onClick={() => setIsCollapsed(false)}
className={cn( className={cn(
'fixed right-2 top-1/2 z-40 -translate-y-1/2 rounded-md p-2.5', 'fixed right-2 top-1/2 z-40 -translate-y-1/2 rounded-md p-2.5',
'bg-card border border-border shadow-md', 'bg-[#14161d] border border-[#1e2130] shadow-md',
'text-muted-foreground hover:bg-accent hover:text-foreground', 'text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]',
'transition-opacity duration-200', 'transition-opacity duration-200',
isCollapsed ? 'opacity-100' : 'pointer-events-none opacity-0' isCollapsed ? 'opacity-100' : 'pointer-events-none opacity-0'
)} )}
@@ -153,29 +153,29 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
'fixed z-40', 'fixed z-40',
'inset-0 sm:inset-auto sm:right-2 sm:top-1/2 sm:-translate-y-1/2', 'inset-0 sm:inset-auto sm:right-2 sm:top-1/2 sm:-translate-y-1/2',
'flex w-full flex-col sm:h-[55vh] sm:w-[420px]', 'flex w-full flex-col sm:h-[55vh] sm:w-[420px]',
'border-border bg-card/95 backdrop-blur-md shadow-xl sm:rounded-lg sm:border', 'border-[#1e2130] bg-[#14161d]/95 shadow-xl sm:rounded-lg sm:border',
'transition-transform duration-200 ease-out', 'transition-transform duration-200 ease-out',
isCollapsed ? 'translate-x-full' : 'translate-x-0' isCollapsed ? 'translate-x-full' : 'translate-x-0'
)} )}
> >
{/* Header */} {/* Header */}
<div className="flex items-center justify-between border-b border-border px-3 py-2"> <div className="flex items-center justify-between border-b border-[#1e2130] px-3 py-2">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<StickyNote className="h-4 w-4 text-muted-foreground" /> <StickyNote className="h-4 w-4 text-[#848b9b]" />
<span className="text-sm font-medium text-foreground">Scratchpad</span> <span className="text-sm font-medium text-[#e2e5eb]">Scratchpad</span>
<span className="text-xs text-muted-foreground">Ctrl+/</span> <span className="text-xs text-[#848b9b]">Ctrl+/</span>
</div> </div>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<button <button
onClick={() => setShowPreview(!showPreview)} onClick={() => setShowPreview(!showPreview)}
className="rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground" className="rounded p-1 text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]"
title={showPreview ? 'Edit' : 'Preview'} title={showPreview ? 'Edit' : 'Preview'}
> >
{showPreview ? <Pencil className="h-3.5 w-3.5" /> : <Eye className="h-3.5 w-3.5" />} {showPreview ? <Pencil className="h-3.5 w-3.5" /> : <Eye className="h-3.5 w-3.5" />}
</button> </button>
<button <button
onClick={() => setIsCollapsed(true)} onClick={() => setIsCollapsed(true)}
className="rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground" className="rounded p-1 text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]"
title="Close scratchpad" title="Close scratchpad"
aria-label="Close scratchpad" aria-label="Close scratchpad"
> >
@@ -191,7 +191,7 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
{content.trim() ? ( {content.trim() ? (
<MarkdownContent content={content} className="text-sm" /> <MarkdownContent content={content} className="text-sm" />
) : ( ) : (
<p className="text-sm italic text-muted-foreground">Nothing to preview</p> <p className="text-sm italic text-[#848b9b]">Nothing to preview</p>
)} )}
</div> </div>
) : ( ) : (
@@ -202,7 +202,7 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
placeholder={"Capture IPs, error codes, server names, user info...\n\nSupports markdown formatting."} placeholder={"Capture IPs, error codes, server names, user info...\n\nSupports markdown formatting."}
className={cn( className={cn(
'h-full min-h-[200px] w-full resize-none rounded-md border-0 bg-transparent p-0 text-sm', 'h-full min-h-[200px] w-full resize-none rounded-md border-0 bg-transparent p-0 text-sm',
'text-foreground placeholder:text-muted-foreground', 'text-[#e2e5eb] placeholder:text-[#848b9b]',
'focus:outline-hidden focus:ring-0' 'focus:outline-hidden focus:ring-0'
)} )}
/> />
@@ -210,15 +210,15 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
</div> </div>
{/* Save Indicator */} {/* Save Indicator */}
<div className="border-t border-border px-3 py-1.5"> <div className="border-t border-[#1e2130] px-3 py-1.5">
<div className="flex items-center gap-1.5 text-xs"> <div className="flex items-center gap-1.5 text-xs">
{saveStatus === 'unsaved' && ( {saveStatus === 'unsaved' && (
<span className="text-muted-foreground">Unsaved changes</span> <span className="text-[#848b9b]">Unsaved changes</span>
)} )}
{saveStatus === 'saving' && ( {saveStatus === 'saving' && (
<> <>
<Loader2 className="h-3 w-3 animate-spin text-muted-foreground" /> <Loader2 className="h-3 w-3 animate-spin text-[#848b9b]" />
<span className="text-muted-foreground">Saving...</span> <span className="text-[#848b9b]">Saving...</span>
</> </>
)} )}
{saveStatus === 'saved' && ( {saveStatus === 'saved' && (
@@ -228,7 +228,7 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
<span className="text-red-400">Save failed</span> <span className="text-red-400">Save failed</span>
)} )}
{saveStatus === 'idle' && ( {saveStatus === 'idle' && (
<span className="text-muted-foreground">Markdown supported</span> <span className="text-[#848b9b]">Markdown supported</span>
)} )}
</div> </div>
</div> </div>

View File

@@ -93,15 +93,15 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
<div className="flex flex-col gap-3 sm:flex-row"> <div className="flex flex-col gap-3 sm:flex-row">
{/* Ticket Number Search */} {/* Ticket Number Search */}
<div className="relative flex-1"> <div className="relative flex-1">
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" /> <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[#848b9b]" />
<input <input
type="text" type="text"
placeholder="Search by ticket number..." placeholder="Search by ticket number..."
value={filters.ticketNumber} value={filters.ticketNumber}
onChange={(e) => handleFilterChange('ticketNumber', e.target.value)} onChange={(e) => handleFilterChange('ticketNumber', e.target.value)}
className={cn( className={cn(
'w-full rounded-md border border-border bg-card py-2 pl-9 pr-3', 'w-full rounded-md border border-[#1e2130] bg-[#14161d] py-2 pl-9 pr-3',
'text-foreground placeholder:text-muted-foreground', 'text-[#e2e5eb] placeholder:text-[#848b9b]',
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20' 'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20'
)} )}
/> />
@@ -109,15 +109,15 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
{/* Client Name Search */} {/* Client Name Search */}
<div className="relative flex-1"> <div className="relative flex-1">
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" /> <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[#848b9b]" />
<input <input
type="text" type="text"
placeholder="Search by client name..." placeholder="Search by client name..."
value={filters.clientName} value={filters.clientName}
onChange={(e) => handleFilterChange('clientName', e.target.value)} onChange={(e) => handleFilterChange('clientName', e.target.value)}
className={cn( className={cn(
'w-full rounded-md border border-border bg-card py-2 pl-9 pr-3', 'w-full rounded-md border border-[#1e2130] bg-[#14161d] py-2 pl-9 pr-3',
'text-foreground placeholder:text-muted-foreground', 'text-[#e2e5eb] placeholder:text-[#848b9b]',
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20' 'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20'
)} )}
/> />
@@ -128,8 +128,8 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
value={filters.treeName} value={filters.treeName}
onChange={(e) => handleFilterChange('treeName', e.target.value)} onChange={(e) => handleFilterChange('treeName', e.target.value)}
className={cn( className={cn(
'rounded-md border border-border bg-card px-3 py-2', 'rounded-md border border-[#1e2130] bg-[#14161d] px-3 py-2',
'text-foreground focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20', 'text-[#e2e5eb] focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20',
'sm:min-w-[200px]' 'sm:min-w-[200px]'
)} )}
> >
@@ -148,19 +148,19 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
<button <button
onClick={() => setShowDatePicker(!showDatePicker)} onClick={() => setShowDatePicker(!showDatePicker)}
className={cn( className={cn(
'flex w-full items-center gap-2 rounded-md border border-border bg-card px-3 py-2 text-sm', 'flex w-full items-center gap-2 rounded-md border border-[#1e2130] bg-[#14161d] px-3 py-2 text-sm',
'text-foreground hover:bg-accent', 'text-[#e2e5eb] hover:bg-accent',
filters.dateRange?.from && 'border-primary/30' filters.dateRange?.from && 'border-primary/30'
)} )}
> >
<Calendar className="h-4 w-4 text-muted-foreground" /> <Calendar className="h-4 w-4 text-[#848b9b]" />
<span className={cn(!filters.dateRange?.from && 'text-muted-foreground')}> <span className={cn(!filters.dateRange?.from && 'text-[#848b9b]')}>
{formatDateRange(filters.dateRange)} {formatDateRange(filters.dateRange)}
</span> </span>
</button> </button>
{showDatePicker && ( {showDatePicker && (
<div className="absolute left-0 top-full z-50 mt-2 rounded-lg border border-border bg-background p-4 shadow-lg"> <div className="absolute left-0 top-full z-50 mt-2 rounded-lg border border-[#1e2130] bg-[#0c0d10] p-4 shadow-lg">
{/* Date Type Toggle */} {/* Date Type Toggle */}
<div className="mb-3 flex gap-2"> <div className="mb-3 flex gap-2">
<button <button
@@ -168,8 +168,8 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
className={cn( className={cn(
'flex-1 rounded-md px-3 py-1.5 text-sm font-medium transition-colors', 'flex-1 rounded-md px-3 py-1.5 text-sm font-medium transition-colors',
filters.dateType === 'started' filters.dateType === 'started'
? 'bg-gradient-brand text-white shadow-lg shadow-primary/20' ? 'bg-[#22d3ee] text-white'
: 'border border-border text-muted-foreground hover:bg-accent hover:text-foreground' : 'border border-[#1e2130] text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]'
)} )}
> >
Started Started
@@ -179,8 +179,8 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
className={cn( className={cn(
'flex-1 rounded-md px-3 py-1.5 text-sm font-medium transition-colors', 'flex-1 rounded-md px-3 py-1.5 text-sm font-medium transition-colors',
filters.dateType === 'completed' filters.dateType === 'completed'
? 'bg-gradient-brand text-white shadow-lg shadow-primary/20' ? 'bg-[#22d3ee] text-white'
: 'border border-border text-muted-foreground hover:bg-accent hover:text-foreground' : 'border border-[#1e2130] text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]'
)} )}
> >
Completed Completed
@@ -194,8 +194,8 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
key={preset.value} key={preset.value}
onClick={() => applyDatePreset(preset.value)} onClick={() => applyDatePreset(preset.value)}
className={cn( className={cn(
'rounded-md bg-accent px-3 py-1.5 text-sm font-medium text-muted-foreground', 'rounded-md bg-accent px-3 py-1.5 text-sm font-medium text-[#848b9b]',
'hover:bg-accent/80 hover:text-foreground' 'hover:bg-accent/80 hover:text-[#e2e5eb]'
)} )}
> >
{preset.label} {preset.label}
@@ -228,7 +228,7 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
}} }}
className={cn( className={cn(
'flex-1 rounded-md bg-gradient-brand px-3 py-1.5 text-sm font-medium text-white shadow-lg shadow-primary/20', 'flex-1 rounded-md bg-gradient-brand px-3 py-1.5 text-sm font-medium text-white shadow-lg shadow-primary/20',
'hover:opacity-90' 'hover:brightness-110'
)} )}
> >
Apply Apply
@@ -236,8 +236,8 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
<button <button
onClick={() => setShowDatePicker(false)} onClick={() => setShowDatePicker(false)}
className={cn( className={cn(
'rounded-md border border-border px-3 py-1.5 text-sm font-medium text-muted-foreground', 'rounded-md border border-[#1e2130] px-3 py-1.5 text-sm font-medium text-[#848b9b]',
'hover:bg-accent hover:text-foreground' 'hover:bg-accent hover:text-[#e2e5eb]'
)} )}
> >
Cancel Cancel
@@ -252,8 +252,8 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
<button <button
onClick={onClear} onClick={onClear}
className={cn( className={cn(
'flex items-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium', 'flex items-center gap-2 rounded-md border border-[#1e2130] px-3 py-2 text-sm font-medium',
'text-muted-foreground hover:bg-accent hover:text-foreground' 'text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]'
)} )}
> >
<Filter className="h-4 w-4" /> <Filter className="h-4 w-4" />
@@ -265,9 +265,9 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
{/* Active Filter Chips */} {/* Active Filter Chips */}
{hasActiveFilters && ( {hasActiveFilters && (
<div className="flex flex-wrap items-center gap-2"> <div className="flex flex-wrap items-center gap-2">
<span className="text-sm text-muted-foreground">Active filters:</span> <span className="text-sm text-[#848b9b]">Active filters:</span>
{filters.ticketNumber && ( {filters.ticketNumber && (
<span className="inline-flex items-center gap-1 rounded-full bg-accent px-3 py-1 text-sm text-muted-foreground"> <span className="inline-flex items-center gap-1 rounded-full bg-accent px-3 py-1 text-sm text-[#848b9b]">
Ticket: {filters.ticketNumber} Ticket: {filters.ticketNumber}
<button <button
onClick={() => handleFilterChange('ticketNumber', '')} onClick={() => handleFilterChange('ticketNumber', '')}
@@ -278,7 +278,7 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
</span> </span>
)} )}
{filters.clientName && ( {filters.clientName && (
<span className="inline-flex items-center gap-1 rounded-full bg-accent px-3 py-1 text-sm text-muted-foreground"> <span className="inline-flex items-center gap-1 rounded-full bg-accent px-3 py-1 text-sm text-[#848b9b]">
Client: {filters.clientName} Client: {filters.clientName}
<button <button
onClick={() => handleFilterChange('clientName', '')} onClick={() => handleFilterChange('clientName', '')}
@@ -289,7 +289,7 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
</span> </span>
)} )}
{filters.treeName && ( {filters.treeName && (
<span className="inline-flex items-center gap-1 rounded-full bg-accent px-3 py-1 text-sm text-muted-foreground"> <span className="inline-flex items-center gap-1 rounded-full bg-accent px-3 py-1 text-sm text-[#848b9b]">
Tree: {filters.treeName} Tree: {filters.treeName}
<button <button
onClick={() => handleFilterChange('treeName', '')} onClick={() => handleFilterChange('treeName', '')}
@@ -300,7 +300,7 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
</span> </span>
)} )}
{filters.dateRange?.from && ( {filters.dateRange?.from && (
<span className="inline-flex items-center gap-1 rounded-full bg-accent px-3 py-1 text-sm text-muted-foreground"> <span className="inline-flex items-center gap-1 rounded-full bg-accent px-3 py-1 text-sm text-[#848b9b]">
{formatDateRange(filters.dateRange)} ({filters.dateType}) {formatDateRange(filters.dateRange)} ({filters.dateType})
<button <button
onClick={clearDateRange} onClick={clearDateRange}

View File

@@ -66,7 +66,7 @@ export function SessionOutcomeModal({
)} )}
> >
<form key={String(isOpen)} ref={formRef} className="space-y-4"> <form key={String(isOpen)} ref={formRef} className="space-y-4">
<p className="text-sm text-muted-foreground"> <p className="text-sm text-[#848b9b]">
Select the session outcome before completion. Select the session outcome before completion.
</p> </p>
<div className="space-y-2"> <div className="space-y-2">
@@ -74,7 +74,7 @@ export function SessionOutcomeModal({
<label <label
key={option.value} key={option.value}
className={cn( className={cn(
'block cursor-pointer rounded-lg border border-border p-3 transition-colors', 'block cursor-pointer rounded-lg border border-[#1e2130] p-3 transition-colors',
'hover:bg-accent/50' 'hover:bg-accent/50'
)} )}
> >
@@ -87,8 +87,8 @@ export function SessionOutcomeModal({
className="mt-1 h-4 w-4" className="mt-1 h-4 w-4"
/> />
<div> <div>
<p className="text-sm font-medium text-foreground">{option.label}</p> <p className="text-sm font-medium text-[#e2e5eb]">{option.label}</p>
<p className="text-xs text-muted-foreground">{option.description}</p> <p className="text-xs text-[#848b9b]">{option.description}</p>
</div> </div>
</div> </div>
</label> </label>
@@ -96,30 +96,30 @@ export function SessionOutcomeModal({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-foreground">Outcome Notes (optional)</label> <label className="block text-sm font-medium text-[#e2e5eb]">Outcome Notes (optional)</label>
<textarea <textarea
name="outcome-notes" name="outcome-notes"
defaultValue="" defaultValue=""
rows={3} rows={3}
placeholder="Add context for this outcome..." placeholder="Add context for this outcome..."
className={cn( className={cn(
'mt-1 block w-full rounded-md border border-border bg-card px-3 py-2', 'mt-1 block w-full rounded-md border border-[#1e2130] bg-[#14161d] px-3 py-2',
'text-sm text-foreground placeholder:text-muted-foreground', 'text-sm text-[#e2e5eb] placeholder:text-[#848b9b]',
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20' 'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20'
)} )}
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-foreground">Next Steps / Follow-Up (optional)</label> <label className="block text-sm font-medium text-[#e2e5eb]">Next Steps / Follow-Up (optional)</label>
<textarea <textarea
name="next-steps" name="next-steps"
defaultValue="" defaultValue=""
rows={3} rows={3}
placeholder="Actions to take after this session..." placeholder="Actions to take after this session..."
className={cn( className={cn(
'mt-1 block w-full rounded-md border border-border bg-card px-3 py-2', 'mt-1 block w-full rounded-md border border-[#1e2130] bg-[#14161d] px-3 py-2',
'text-sm text-foreground placeholder:text-muted-foreground', 'text-sm text-[#e2e5eb] placeholder:text-[#848b9b]',
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20' 'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20'
)} )}
/> />

View File

@@ -53,7 +53,7 @@ export function SessionTimeline({
if (treeType === 'procedural') { if (treeType === 'procedural') {
return ( return (
<div className="mb-8"> <div className="mb-8">
<h2 className="mb-4 text-lg font-semibold text-foreground">Procedure Steps</h2> <h2 className="mb-4 text-lg font-semibold text-[#e2e5eb]">Procedure Steps</h2>
<div className="space-y-2"> <div className="space-y-2">
{decisions.map((decision, index) => { {decisions.map((decision, index) => {
const isCompleted = decision.answer === 'completed' const isCompleted = decision.answer === 'completed'
@@ -61,31 +61,31 @@ export function SessionTimeline({
<div <div
key={index} key={index}
className={cn( className={cn(
'bg-card border border-border rounded-xl p-4', 'bg-[#14161d] border border-[#1e2130] rounded-xl p-4',
isCompleted && 'border-l-2 border-emerald-400/50' isCompleted && 'border-l-2 border-emerald-400/50'
)} )}
> >
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<span className={cn( <span className={cn(
'mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-xs font-medium', 'mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-xs font-medium',
isCompleted ? 'bg-emerald-400/10 text-emerald-400' : 'bg-accent text-muted-foreground' isCompleted ? 'bg-emerald-400/10 text-emerald-400' : 'bg-accent text-[#848b9b]'
)}> )}>
{isCompleted ? '\u2713' : index + 1} {isCompleted ? '\u2713' : index + 1}
</span> </span>
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<p className="font-medium text-foreground">{decision.question || 'Step'}</p> <p className="font-medium text-[#e2e5eb]">{decision.question || 'Step'}</p>
{decision.notes && ( {decision.notes && (
<p className="mt-1.5 rounded bg-white/5 p-2 text-sm text-muted-foreground"> <p className="mt-1.5 rounded bg-white/5 p-2 text-sm text-[#848b9b]">
Notes: {decision.notes} Notes: {decision.notes}
</p> </p>
)} )}
{decision.command_output && ( {decision.command_output && (
<p className="mt-1 text-sm text-muted-foreground"> <p className="mt-1 text-sm text-[#848b9b]">
Verification: {decision.command_output} Verification: {decision.command_output}
</p> </p>
)} )}
{decision.duration_seconds != null && ( {decision.duration_seconds != null && (
<p className="mt-1 text-xs text-muted-foreground"> <p className="mt-1 text-xs text-[#848b9b]">
Duration: {formatDuration(decision.duration_seconds)} Duration: {formatDuration(decision.duration_seconds)}
</p> </p>
)} )}
@@ -94,7 +94,7 @@ export function SessionTimeline({
<button <button
onClick={() => handleCopyStep(decision, index)} onClick={() => handleCopyStep(decision, index)}
title="Copy step to clipboard" title="Copy step to clipboard"
className="rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground" className="rounded p-1 text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]"
> >
{copiedStepIndex === index ? ( {copiedStepIndex === index ? (
<Check className="h-4 w-4 text-emerald-400" /> <Check className="h-4 w-4 text-emerald-400" />
@@ -123,52 +123,52 @@ export function SessionTimeline({
// Default: troubleshooting decision timeline // Default: troubleshooting decision timeline
return ( return (
<div className="mb-8"> <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-[#e2e5eb]">Decision Timeline</h2>
<div className="space-y-4"> <div className="space-y-4">
<div className="flex items-center gap-3 text-sm"> <div className="flex items-center gap-3 text-sm">
<span className="h-3 w-3 rounded-full bg-foreground" /> <span className="h-3 w-3 rounded-full bg-[#e2e5eb]" />
<span className="text-muted-foreground"> <span className="text-[#848b9b]">
Session started: {formatDate(startedAt)} Session started: {formatDate(startedAt)}
</span> </span>
</div> </div>
{decisions.map((decision, index) => ( {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-[#1e2130] pl-6">
<div className="relative"> <div className="relative">
<span className="absolute -left-6.5 top-1 h-2 w-2 rounded-full bg-muted-foreground" /> <span className="absolute -left-6.5 top-1 h-2 w-2 rounded-full bg-[#848b9b]" />
<div className="bg-card border border-border rounded-xl p-4"> <div className="bg-[#14161d] border border-[#1e2130] rounded-xl p-4">
<div className="flex items-start justify-between gap-2"> <div className="flex items-start justify-between gap-2">
<div className="flex-1"> <div className="flex-1">
{decision.question && ( {decision.question && (
<p className="font-medium text-foreground">{decision.question}</p> <p className="font-medium text-[#e2e5eb]">{decision.question}</p>
)} )}
{decision.answer && ( {decision.answer && (
<p className="mt-1 text-sm text-foreground">Answer: {decision.answer}</p> <p className="mt-1 text-sm text-[#e2e5eb]">Answer: {decision.answer}</p>
)} )}
{decision.action_performed && ( {decision.action_performed && (
<p className="mt-1 text-sm text-muted-foreground"> <p className="mt-1 text-sm text-[#848b9b]">
Action: {decision.action_performed} Action: {decision.action_performed}
</p> </p>
)} )}
{decision.notes && ( {decision.notes && (
<p className="mt-2 rounded bg-white/5 p-2 text-sm text-muted-foreground"> <p className="mt-2 rounded bg-white/5 p-2 text-sm text-[#848b9b]">
Notes: {decision.notes} Notes: {decision.notes}
</p> </p>
)} )}
{decision.command_output && ( {decision.command_output && (
<div className="mt-2"> <div className="mt-2">
<p className="mb-1 text-xs font-medium text-muted-foreground">Command Output</p> <p className="mb-1 text-xs font-medium text-[#848b9b]">Command Output</p>
<pre className="overflow-x-auto rounded bg-white/5 p-2 text-xs font-mono text-muted-foreground whitespace-pre-wrap"> <pre className="overflow-x-auto rounded bg-white/5 p-2 text-xs font-mono text-[#848b9b] whitespace-pre-wrap">
{decision.command_output} {decision.command_output}
</pre> </pre>
</div> </div>
)} )}
{decision.duration_seconds != null && ( {decision.duration_seconds != null && (
<p className="mt-2 text-xs text-muted-foreground"> <p className="mt-2 text-xs text-[#848b9b]">
Duration: {formatDuration(decision.duration_seconds)} Duration: {formatDuration(decision.duration_seconds)}
</p> </p>
)} )}
<p className="mt-2 text-xs text-muted-foreground"> <p className="mt-2 text-xs text-[#848b9b]">
{formatDate(decision.timestamp)} {formatDate(decision.timestamp)}
</p> </p>
</div> </div>
@@ -176,7 +176,7 @@ export function SessionTimeline({
<button <button
onClick={() => handleCopyStep(decision, index)} onClick={() => handleCopyStep(decision, index)}
title="Copy step to clipboard" title="Copy step to clipboard"
className="rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground" className="rounded p-1 text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]"
> >
{copiedStepIndex === index ? ( {copiedStepIndex === index ? (
<Check className="h-4 w-4 text-emerald-400" /> <Check className="h-4 w-4 text-emerald-400" />

View File

@@ -191,14 +191,14 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
} }
> >
{/* Subtitle */} {/* Subtitle */}
<p className="-mt-2 mb-4 text-sm text-muted-foreground">{sessionLabel}</p> <p className="-mt-2 mb-4 text-sm text-[#848b9b]">{sessionLabel}</p>
<div className="space-y-6"> <div className="space-y-6">
{/* Create Share Form */} {/* Create Share Form */}
<div className="space-y-4"> <div className="space-y-4">
{/* Visibility */} {/* Visibility */}
<div> <div>
<label className="mb-2 block text-sm font-medium text-foreground"> <label className="mb-2 block text-sm font-medium text-[#e2e5eb]">
Visibility Visibility
</label> </label>
<div className="space-y-2"> <div className="space-y-2">
@@ -207,14 +207,14 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
className={cn( className={cn(
'flex w-full items-center gap-3 rounded-md border px-4 py-3 text-left transition-colors', 'flex w-full items-center gap-3 rounded-md border px-4 py-3 text-left transition-colors',
visibility === 'account' visibility === 'account'
? 'border-primary/30 bg-primary/10 text-foreground' ? 'border-primary/30 bg-[rgba(34,211,238,0.10)] text-[#e2e5eb]'
: 'border-border bg-transparent text-muted-foreground hover:border-border hover:bg-accent' : 'border-[#1e2130] bg-transparent text-[#848b9b] hover:border-[#1e2130] hover:bg-accent'
)} )}
> >
<Users className="h-4 w-4" /> <Users className="h-4 w-4" />
<div className="flex-1"> <div className="flex-1">
<div className="text-sm font-medium">Account Only</div> <div className="text-sm font-medium">Account Only</div>
<div className="text-xs text-muted-foreground">Visible to your team</div> <div className="text-xs text-[#848b9b]">Visible to your team</div>
</div> </div>
{visibility === 'account' && ( {visibility === 'account' && (
<div className="h-2 w-2 rounded-full bg-primary" /> <div className="h-2 w-2 rounded-full bg-primary" />
@@ -225,14 +225,14 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
className={cn( className={cn(
'flex w-full items-center gap-3 rounded-md border px-4 py-3 text-left transition-colors', 'flex w-full items-center gap-3 rounded-md border px-4 py-3 text-left transition-colors',
visibility === 'public' visibility === 'public'
? 'border-primary/30 bg-primary/10 text-foreground' ? 'border-primary/30 bg-[rgba(34,211,238,0.10)] text-[#e2e5eb]'
: 'border-border bg-transparent text-muted-foreground hover:border-border hover:bg-accent' : 'border-[#1e2130] bg-transparent text-[#848b9b] hover:border-[#1e2130] hover:bg-accent'
)} )}
> >
<Globe className="h-4 w-4" /> <Globe className="h-4 w-4" />
<div className="flex-1"> <div className="flex-1">
<div className="text-sm font-medium">Public</div> <div className="text-sm font-medium">Public</div>
<div className="text-xs text-muted-foreground">Anyone with the link</div> <div className="text-xs text-[#848b9b]">Anyone with the link</div>
</div> </div>
{visibility === 'public' && ( {visibility === 'public' && (
<div className="h-2 w-2 rounded-full bg-primary" /> <div className="h-2 w-2 rounded-full bg-primary" />
@@ -246,8 +246,8 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
{/* Share Name */} {/* Share Name */}
<div> <div>
<label className="mb-2 block text-sm font-medium text-foreground"> <label className="mb-2 block text-sm font-medium text-[#e2e5eb]">
Share Name <span className="text-muted-foreground">(optional)</span> Share Name <span className="text-[#848b9b]">(optional)</span>
</label> </label>
<Input <Input
type="text" type="text"
@@ -260,7 +260,7 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
{/* Expiration */} {/* Expiration */}
<div> <div>
<label className="mb-2 block text-sm font-medium text-foreground"> <label className="mb-2 block text-sm font-medium text-[#e2e5eb]">
Expiration Expiration
</label> </label>
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
@@ -271,8 +271,8 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
className={cn( className={cn(
'rounded-md border px-3 py-1.5 text-sm transition-colors', 'rounded-md border px-3 py-1.5 text-sm transition-colors',
expirationPreset === preset.value expirationPreset === preset.value
? 'border-primary/30 bg-primary/10 text-foreground' ? 'border-primary/30 bg-[rgba(34,211,238,0.10)] text-[#e2e5eb]'
: 'border-border text-muted-foreground hover:border-border hover:bg-accent' : 'border-[#1e2130] text-[#848b9b] hover:border-[#1e2130] hover:bg-accent'
)} )}
> >
{preset.label} {preset.label}
@@ -285,7 +285,7 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
value={customDatetime} value={customDatetime}
onChange={(e) => setCustomDatetime(e.target.value)} onChange={(e) => setCustomDatetime(e.target.value)}
className={cn( className={cn(
'mt-2 w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground', 'mt-2 w-full rounded-md border border-[#1e2130] bg-[#14161d] px-3 py-2 text-sm text-[#e2e5eb]',
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20', 'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20',
'scheme-dark' 'scheme-dark'
)} )}
@@ -308,7 +308,7 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
{/* Existing Shares */} {/* Existing Shares */}
{shares.length > 0 && ( {shares.length > 0 && (
<div> <div>
<h3 className="mb-3 text-sm font-medium text-foreground"> <h3 className="mb-3 text-sm font-medium text-[#e2e5eb]">
Active Shares ({shares.length}) Active Shares ({shares.length})
</h3> </h3>
<div className="space-y-3"> <div className="space-y-3">
@@ -318,7 +318,7 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
return ( return (
<div <div
key={share.id} key={share.id}
className="bg-card border border-border rounded-xl p-4 space-y-2" className="bg-[#14161d] border border-[#1e2130] rounded-lg p-4 space-y-2"
> >
<div className="flex items-start justify-between gap-2"> <div className="flex items-start justify-between gap-2">
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
@@ -326,8 +326,8 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
<span className={cn( <span className={cn(
'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs', 'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs',
share.visibility === 'public' share.visibility === 'public'
? 'bg-accent text-muted-foreground' ? 'bg-accent text-[#848b9b]'
: 'bg-accent text-muted-foreground' : 'bg-accent text-[#848b9b]'
)}> )}>
{share.visibility === 'public' ? ( {share.visibility === 'public' ? (
<Globe className="h-3 w-3" /> <Globe className="h-3 w-3" />
@@ -336,11 +336,11 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
)} )}
{share.visibility === 'public' ? 'Public' : 'Account'} {share.visibility === 'public' ? 'Public' : 'Account'}
</span> </span>
<span className="truncate text-sm font-medium text-foreground"> <span className="truncate text-sm font-medium text-[#e2e5eb]">
{share.share_name || 'Untitled share'} {share.share_name || 'Untitled share'}
</span> </span>
</div> </div>
<div className="mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground"> <div className="mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-[#848b9b]">
<span>{getRelativeTime(share.created_at)}</span> <span>{getRelativeTime(share.created_at)}</span>
<span> <span>
{share.view_count > 0 {share.view_count > 0
@@ -361,10 +361,10 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
onClick={() => handleCopyUrl(share)} onClick={() => handleCopyUrl(share)}
title="Copy share URL" title="Copy share URL"
className={cn( className={cn(
'rounded-md border border-border p-1.5 text-sm transition-colors', 'rounded-md border border-[#1e2130] p-1.5 text-sm transition-colors',
isCopied isCopied
? 'border-emerald-500/30 bg-emerald-500/10 text-emerald-400' ? 'border-emerald-500/30 bg-emerald-500/10 text-emerald-400'
: 'text-muted-foreground hover:bg-accent hover:text-foreground' : 'text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]'
)} )}
> >
{isCopied ? ( {isCopied ? (
@@ -376,7 +376,7 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
<button <button
onClick={() => handleRevoke(share.id)} onClick={() => handleRevoke(share.id)}
title="Revoke share" title="Revoke share"
className="rounded-md border border-border p-1.5 text-muted-foreground hover:bg-red-500/10 hover:border-red-500/30 hover:text-red-400 transition-colors" className="rounded-md border border-[#1e2130] p-1.5 text-[#848b9b] hover:bg-red-500/10 hover:border-red-500/30 hover:text-red-400 transition-colors"
> >
<Trash2 className="h-3.5 w-3.5" /> <Trash2 className="h-3.5 w-3.5" />
</button> </button>

View File

@@ -7,11 +7,11 @@ interface SharedSessionTreePreviewProps {
} }
const nodeTypeColors: Record<string, string> = { const nodeTypeColors: Record<string, string> = {
root: 'bg-foreground', root: 'bg-[#e2e5eb]',
decision: 'bg-blue-400', decision: 'bg-blue-400',
action: 'bg-yellow-400', action: 'bg-yellow-400',
solution: 'bg-emerald-400', solution: 'bg-emerald-400',
information: 'bg-muted-foreground', information: 'bg-[#848b9b]',
} }
function getNodeTitle(node: Record<string, unknown>): string { function getNodeTitle(node: Record<string, unknown>): string {
@@ -36,7 +36,7 @@ function TreeNode({
const nodeType = (node.node_type as string) || 'decision' const nodeType = (node.node_type as string) || 'decision'
const isInPath = pathTaken.includes(nodeId) const isInPath = pathTaken.includes(nodeId)
const children = (node.children as Record<string, unknown>[]) || [] const children = (node.children as Record<string, unknown>[]) || []
const colorClass = nodeTypeColors[nodeType] || 'bg-muted-foreground' const colorClass = nodeTypeColors[nodeType] || 'bg-[#848b9b]'
return ( return (
<> <>
@@ -44,8 +44,8 @@ function TreeNode({
className={cn( className={cn(
'flex items-center gap-2 px-3 py-1.5 text-sm', 'flex items-center gap-2 px-3 py-1.5 text-sm',
isInPath isInPath
? 'rounded-md border-l-2 border-muted-foreground bg-accent font-medium text-foreground' ? 'rounded-md border-l-2 border-muted-foreground bg-accent font-medium text-[#e2e5eb]'
: 'text-muted-foreground' : 'text-[#848b9b]'
)} )}
style={{ paddingLeft: `${depth * 16 + 12}px` }} style={{ paddingLeft: `${depth * 16 + 12}px` }}
> >
@@ -75,9 +75,9 @@ export function SharedSessionTreePreview({
} }
return ( return (
<div className="bg-card border border-border rounded-2xl"> <div className="bg-[#14161d] border border-[#1e2130] rounded-lg">
<div className="sticky top-0 z-10 rounded-t-2xl border-b border-border bg-black/80 px-6 py-4 backdrop-blur-sm"> <div className="sticky top-0 z-10 rounded-t-2xl border-b border-[#1e2130] bg-black/80 px-6 py-4 ">
<h3 className="text-sm font-semibold text-foreground">Tree Structure</h3> <h3 className="text-sm font-semibold text-[#e2e5eb]">Tree Structure</h3>
</div> </div>
<div className="max-h-[600px] overflow-y-auto py-2"> <div className="max-h-[600px] overflow-y-auto py-2">
<TreeNode node={treeStructure as unknown as Record<string, unknown>} depth={0} pathTaken={pathTaken} /> <TreeNode node={treeStructure as unknown as Record<string, unknown>} depth={0} pathTaken={pathTaken} />

View File

@@ -44,7 +44,7 @@ export function StepFeedback({ stepId, sessionId }: StepFeedbackProps) {
return ( return (
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{showHint && ( {showHint && (
<span className="text-xs text-muted-foreground">Was this step helpful?</span> <span className="text-xs text-[#848b9b]">Was this step helpful?</span>
)} )}
<button <button
onClick={() => handleFeedback(true)} onClick={() => handleFeedback(true)}
@@ -53,7 +53,7 @@ export function StepFeedback({ stepId, sessionId }: StepFeedbackProps) {
'rounded-md p-1.5 transition-colors', 'rounded-md p-1.5 transition-colors',
feedback === true feedback === true
? 'text-emerald-400 bg-emerald-400/10' ? 'text-emerald-400 bg-emerald-400/10'
: 'text-muted-foreground hover:text-emerald-400 hover:bg-accent' : 'text-[#848b9b] hover:text-emerald-400 hover:bg-accent'
)} )}
title="Helpful" title="Helpful"
> >
@@ -66,7 +66,7 @@ export function StepFeedback({ stepId, sessionId }: StepFeedbackProps) {
'rounded-md p-1.5 transition-colors', 'rounded-md p-1.5 transition-colors',
feedback === false feedback === false
? 'text-red-400 bg-red-400/10' ? 'text-red-400 bg-red-400/10'
: 'text-muted-foreground hover:text-red-400 hover:bg-accent' : 'text-[#848b9b] hover:text-red-400 hover:bg-accent'
)} )}
title="Not helpful" title="Not helpful"
> >

View File

@@ -80,19 +80,19 @@ export function StepRatingModal({
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-xs p-4"> <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-xs p-4">
<div className="bg-card border border-border w-full max-w-2xl max-h-[90vh] flex flex-col rounded-2xl shadow-lg"> <div className="bg-[#14161d] border border-[#1e2130] w-full max-w-2xl max-h-[90vh] flex flex-col rounded-lg shadow-lg">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between border-b border-border px-6 py-4"> <div className="flex items-center justify-between border-b border-[#1e2130] px-6 py-4">
<div> <div>
<h2 className="text-lg font-semibold text-foreground">Rate Your Experience</h2> <h2 className="text-lg font-semibold text-[#e2e5eb]">Rate Your Experience</h2>
<p className="mt-1 text-sm text-muted-foreground"> <p className="mt-1 text-sm text-[#848b9b]">
Help others by rating the steps you used ({librarySteps.length} step{librarySteps.length !== 1 ? 's' : ''}) Help others by rating the steps you used ({librarySteps.length} step{librarySteps.length !== 1 ? 's' : ''})
</p> </p>
</div> </div>
<button <button
onClick={onClose} onClick={onClose}
disabled={isSaving} disabled={isSaving}
className="rounded-full p-1 text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-50" className="rounded-full p-1 text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb] disabled:opacity-50"
> >
<X className="h-5 w-5" /> <X className="h-5 w-5" />
</button> </button>
@@ -104,14 +104,14 @@ export function StepRatingModal({
{librarySteps.map((step) => { {librarySteps.map((step) => {
const rating = getRating(step.id) const rating = getRating(step.id)
return ( return (
<div key={step.id} className="rounded-lg border border-border bg-background p-4"> <div key={step.id} className="rounded-lg border border-[#1e2130] bg-[#0c0d10] p-4">
{/* Step Title */} {/* Step Title */}
<h3 className="font-medium text-foreground">{step.title}</h3> <h3 className="font-medium text-[#e2e5eb]">{step.title}</h3>
<p className="mt-1 text-sm text-muted-foreground capitalize">{step.step_type}</p> <p className="mt-1 text-sm text-[#848b9b] capitalize">{step.step_type}</p>
{/* Star Rating */} {/* Star Rating */}
<div className="mt-3"> <div className="mt-3">
<label className="mb-1 block text-sm font-medium text-foreground"> <label className="mb-1 block text-sm font-medium text-[#e2e5eb]">
Rating Rating
</label> </label>
<StarRating <StarRating
@@ -123,7 +123,7 @@ export function StepRatingModal({
{/* Was this helpful? */} {/* Was this helpful? */}
<div className="mt-3"> <div className="mt-3">
<label className="mb-2 block text-sm font-medium text-foreground"> <label className="mb-2 block text-sm font-medium text-[#e2e5eb]">
Was this helpful? Was this helpful?
</label> </label>
<div className="flex gap-2"> <div className="flex gap-2">
@@ -135,7 +135,7 @@ export function StepRatingModal({
'flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium transition-colors', 'flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium transition-colors',
rating?.helpful === true rating?.helpful === true
? 'border-emerald-400/20 bg-emerald-400/10 text-emerald-400' ? 'border-emerald-400/20 bg-emerald-400/10 text-emerald-400'
: 'border-border text-muted-foreground hover:bg-accent hover:text-foreground', : 'border-[#1e2130] text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]',
'disabled:opacity-50' 'disabled:opacity-50'
)} )}
> >
@@ -150,7 +150,7 @@ export function StepRatingModal({
'flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium transition-colors', 'flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium transition-colors',
rating?.helpful === false rating?.helpful === false
? 'border-red-400/20 bg-red-400/10 text-red-400' ? 'border-red-400/20 bg-red-400/10 text-red-400'
: 'border-border text-muted-foreground hover:bg-accent hover:text-foreground', : 'border-[#1e2130] text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]',
'disabled:opacity-50' 'disabled:opacity-50'
)} )}
> >
@@ -162,8 +162,8 @@ export function StepRatingModal({
{/* Optional Review */} {/* Optional Review */}
<div className="mt-3"> <div className="mt-3">
<label htmlFor={`review-${step.id}`} className="mb-1 block text-sm font-medium text-foreground"> <label htmlFor={`review-${step.id}`} className="mb-1 block text-sm font-medium text-[#e2e5eb]">
Review <span className="text-muted-foreground">(optional)</span> Review <span className="text-[#848b9b]">(optional)</span>
</label> </label>
<Textarea <Textarea
id={`review-${step.id}`} id={`review-${step.id}`}
@@ -174,7 +174,7 @@ export function StepRatingModal({
rows={2} rows={2}
placeholder="Share your experience with this step..." placeholder="Share your experience with this step..."
/> />
<p className="mt-1 text-xs text-muted-foreground text-right"> <p className="mt-1 text-xs text-[#848b9b] text-right">
{rating?.review?.length || 0}/500 {rating?.review?.length || 0}/500
</p> </p>
</div> </div>
@@ -185,7 +185,7 @@ export function StepRatingModal({
</div> </div>
{/* Footer */} {/* Footer */}
<div className="flex justify-end gap-2 border-t border-border px-6 py-4"> <div className="flex justify-end gap-2 border-t border-[#1e2130] px-6 py-4">
<Button <Button
type="button" type="button"
variant="secondary" variant="secondary"

View File

@@ -49,22 +49,22 @@ export function SupportingDataPanel({ sessionId }: SupportingDataPanelProps) {
} }
return ( return (
<div className="rounded-xl border border-border bg-card/50"> <div className="rounded-xl border border-[#1e2130] bg-card/50">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between px-4 py-3"> <div className="flex items-center justify-between px-4 py-3">
<button <button
type="button" type="button"
onClick={() => setIsExpanded(!isExpanded)} onClick={() => setIsExpanded(!isExpanded)}
className="flex items-center gap-2 text-sm font-medium text-foreground hover:text-foreground/80" className="flex items-center gap-2 text-sm font-medium text-[#e2e5eb] hover:text-[#e2e5eb]/80"
> >
{isExpanded ? ( {isExpanded ? (
<ChevronDown className="h-4 w-4 text-muted-foreground" /> <ChevronDown className="h-4 w-4 text-[#848b9b]" />
) : ( ) : (
<ChevronRight className="h-4 w-4 text-muted-foreground" /> <ChevronRight className="h-4 w-4 text-[#848b9b]" />
)} )}
Supporting Data Supporting Data
{items.length > 0 && ( {items.length > 0 && (
<span className="rounded-full bg-accent px-2 py-0.5 text-xs text-muted-foreground"> <span className="rounded-full bg-accent px-2 py-0.5 text-xs text-[#848b9b]">
{items.length} {items.length}
</span> </span>
)} )}
@@ -73,8 +73,8 @@ export function SupportingDataPanel({ sessionId }: SupportingDataPanelProps) {
type="button" type="button"
onClick={() => setShowAddModal(true)} onClick={() => setShowAddModal(true)}
className={cn( className={cn(
'flex items-center gap-1.5 rounded-[10px] px-3 py-1.5 text-xs font-medium', 'flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-medium',
'bg-gradient-brand text-[#101114] hover:opacity-90 active:scale-[0.97] transition-all' 'bg-[#22d3ee] text-white hover:brightness-110 active:scale-[0.98] transition-all'
)} )}
> >
<Plus className="h-3.5 w-3.5" /> <Plus className="h-3.5 w-3.5" />
@@ -84,11 +84,11 @@ export function SupportingDataPanel({ sessionId }: SupportingDataPanelProps) {
{/* Items list */} {/* Items list */}
{isExpanded && ( {isExpanded && (
<div className="border-t border-border px-4 py-2"> <div className="border-t border-[#1e2130] px-4 py-2">
{isLoading && items.length === 0 ? ( {isLoading && items.length === 0 ? (
<p className="py-4 text-center text-xs text-muted-foreground">Loading...</p> <p className="py-4 text-center text-xs text-[#848b9b]">Loading...</p>
) : items.length === 0 ? ( ) : items.length === 0 ? (
<p className="py-4 text-center text-xs text-muted-foreground"> <p className="py-4 text-center text-xs text-[#848b9b]">
No supporting data yet. Add text snippets or screenshots to include in exports. No supporting data yet. Add text snippets or screenshots to include in exports.
</p> </p>
) : ( ) : (
@@ -97,11 +97,11 @@ export function SupportingDataPanel({ sessionId }: SupportingDataPanelProps) {
<div <div
key={item.id} key={item.id}
className={cn( className={cn(
'flex items-start gap-3 rounded-lg border border-border bg-card/30 px-3 py-2.5', 'flex items-start gap-3 rounded-lg border border-[#1e2130] bg-card/30 px-3 py-2.5',
'group transition-colors hover:border-[rgba(255,255,255,0.12)]' 'group transition-colors hover:border-[rgba(255,255,255,0.12)]'
)} )}
> >
<span className="mt-0.5 shrink-0 text-muted-foreground"> <span className="mt-0.5 shrink-0 text-[#848b9b]">
{item.data_type === 'text_snippet' ? ( {item.data_type === 'text_snippet' ? (
<Code2 className="h-4 w-4" /> <Code2 className="h-4 w-4" />
) : ( ) : (
@@ -109,9 +109,9 @@ export function SupportingDataPanel({ sessionId }: SupportingDataPanelProps) {
)} )}
</span> </span>
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<p className="text-sm font-medium text-foreground">{item.label}</p> <p className="text-sm font-medium text-[#e2e5eb]">{item.label}</p>
{item.data_type === 'text_snippet' && item.content && ( {item.data_type === 'text_snippet' && item.content && (
<p className="mt-0.5 truncate text-xs font-mono text-muted-foreground"> <p className="mt-0.5 truncate text-xs font-mono text-[#848b9b]">
{item.content.length > 120 ? item.content.slice(0, 120) + '...' : item.content} {item.content.length > 120 ? item.content.slice(0, 120) + '...' : item.content}
</p> </p>
)} )}
@@ -119,14 +119,14 @@ export function SupportingDataPanel({ sessionId }: SupportingDataPanelProps) {
<img <img
src={`data:${item.content_type || 'image/png'};base64,${item.content}`} src={`data:${item.content_type || 'image/png'};base64,${item.content}`}
alt={item.label} alt={item.label}
className="mt-1 max-h-16 rounded border border-border object-contain" className="mt-1 max-h-16 rounded border border-[#1e2130] object-contain"
/> />
)} )}
</div> </div>
<button <button
type="button" type="button"
onClick={() => handleDelete(item.id)} onClick={() => handleDelete(item.id)}
className="shrink-0 text-muted-foreground opacity-0 transition-opacity hover:text-rose-500 group-hover:opacity-100" className="shrink-0 text-[#848b9b] opacity-0 transition-opacity hover:text-rose-500 group-hover:opacity-100"
title="Remove" title="Remove"
> >
<Trash2 className="h-4 w-4" /> <Trash2 className="h-4 w-4" />

View File

@@ -38,14 +38,14 @@ function AccordionSection({ label, icon, count, children }: AccordionSectionProp
onClick={() => setOpen(!open)} onClick={() => setOpen(!open)}
className="flex w-full items-center gap-2 px-3 py-2 text-left hover:bg-[rgba(255,255,255,0.03)] transition-colors" className="flex w-full items-center gap-2 px-3 py-2 text-left hover:bg-[rgba(255,255,255,0.03)] transition-colors"
> >
<span className="text-muted-foreground">{icon}</span> <span className="text-[#848b9b]">{icon}</span>
<span className="flex-1 text-xs font-medium text-foreground">{label}</span> <span className="flex-1 text-xs font-medium text-[#e2e5eb]">{label}</span>
{count !== undefined && count > 0 && ( {count !== undefined && count > 0 && (
<span className="rounded-full bg-primary/10 px-1.5 py-0.5 text-[0.6rem] font-label text-primary"> <span className="rounded-full bg-[rgba(34,211,238,0.10)] px-1.5 py-0.5 text-[0.6rem] font-sans text-xs text-[#22d3ee]">
{count} {count}
</span> </span>
)} )}
<span className="text-muted-foreground"> <span className="text-[#848b9b]">
{open ? <ChevronDown className="h-3.5 w-3.5" /> : <ChevronRight className="h-3.5 w-3.5" />} {open ? <ChevronDown className="h-3.5 w-3.5" /> : <ChevronRight className="h-3.5 w-3.5" />}
</span> </span>
</button> </button>
@@ -60,18 +60,18 @@ function AccordionSection({ label, icon, count, children }: AccordionSectionProp
export function TicketContextPanel({ context, loading, error, onRefresh }: TicketContextPanelProps) { export function TicketContextPanel({ context, loading, error, onRefresh }: TicketContextPanelProps) {
return ( return (
<div className="glass-card-static overflow-hidden rounded-2xl"> <div className="card-flat overflow-hidden rounded-lg">
{/* Header */} {/* Header */}
<div className="flex items-center gap-2 bg-primary/5 px-3 py-2.5"> <div className="flex items-center gap-2 bg-[rgba(34,211,238,0.05)] px-3 py-2.5">
<Ticket className="h-3.5 w-3.5 text-primary" /> <Ticket className="h-3.5 w-3.5 text-[#22d3ee]" />
<span className="flex-1 font-label text-[0.625rem] uppercase tracking-[0.1em] text-primary"> <span className="flex-1 font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#22d3ee]">
Ticket Context Ticket Context
</span> </span>
<button <button
onClick={onRefresh} onClick={onRefresh}
disabled={loading} disabled={loading}
title="Refresh ticket context" title="Refresh ticket context"
className="rounded p-0.5 text-muted-foreground hover:text-foreground disabled:cursor-not-allowed transition-colors" className="rounded p-0.5 text-[#848b9b] hover:text-[#e2e5eb] disabled:cursor-not-allowed transition-colors"
> >
<RefreshCw className={cn('h-3 w-3', loading && 'animate-spin')} /> <RefreshCw className={cn('h-3 w-3', loading && 'animate-spin')} />
</button> </button>
@@ -80,7 +80,7 @@ export function TicketContextPanel({ context, loading, error, onRefresh }: Ticke
{/* Loading */} {/* Loading */}
{loading && !context && ( {loading && !context && (
<div className="flex items-center justify-center py-6"> <div className="flex items-center justify-center py-6">
<Loader2 className="h-5 w-5 animate-spin text-muted-foreground" /> <Loader2 className="h-5 w-5 animate-spin text-[#848b9b]" />
</div> </div>
)} )}
@@ -98,43 +98,43 @@ export function TicketContextPanel({ context, loading, error, onRefresh }: Ticke
{/* Compact summary */} {/* Compact summary */}
<div className="px-3 py-2.5"> <div className="px-3 py-2.5">
<div className="flex items-baseline gap-2"> <div className="flex items-baseline gap-2">
<span className="font-label text-xs font-medium text-primary">#{context.ticket.id}</span> <span className="font-sans text-xs text-xs font-medium text-[#22d3ee]">#{context.ticket.id}</span>
<span className="flex-1 truncate text-xs text-foreground">{context.ticket.summary}</span> <span className="flex-1 truncate text-xs text-[#e2e5eb]">{context.ticket.summary}</span>
</div> </div>
<div className="mt-1.5 flex flex-wrap gap-1.5"> <div className="mt-1.5 flex flex-wrap gap-1.5">
<span className="rounded-md bg-card px-1.5 py-0.5 font-label text-[0.6rem] text-muted-foreground border border-[rgba(255,255,255,0.06)]"> <span className="rounded-md bg-[#14161d] px-1.5 py-0.5 font-sans text-xs text-[0.6rem] text-[#848b9b] border border-[rgba(255,255,255,0.06)]">
{context.ticket.status} {context.ticket.status}
</span> </span>
<span className="rounded-md bg-card px-1.5 py-0.5 font-label text-[0.6rem] text-muted-foreground border border-[rgba(255,255,255,0.06)]"> <span className="rounded-md bg-[#14161d] px-1.5 py-0.5 font-sans text-xs text-[0.6rem] text-[#848b9b] border border-[rgba(255,255,255,0.06)]">
{context.ticket.priority} {context.ticket.priority}
</span> </span>
{context.ticket.sla && ( {context.ticket.sla && (
<span className="rounded-md bg-amber-400/10 px-1.5 py-0.5 font-label text-[0.6rem] text-amber-400 border border-amber-400/20"> <span className="rounded-md bg-amber-400/10 px-1.5 py-0.5 font-sans text-xs text-[0.6rem] text-amber-400 border border-amber-400/20">
SLA: {context.ticket.sla} SLA: {context.ticket.sla}
</span> </span>
)} )}
</div> </div>
<p className="mt-1 text-[0.6875rem] text-muted-foreground">{context.company.name}</p> <p className="mt-1 text-[0.6875rem] text-[#848b9b]">{context.company.name}</p>
</div> </div>
{/* Client */} {/* Client */}
<AccordionSection label="Client" icon={<Building2 className="h-3.5 w-3.5" />}> <AccordionSection label="Client" icon={<Building2 className="h-3.5 w-3.5" />}>
<div className="space-y-1 text-xs"> <div className="space-y-1 text-xs">
<p className="font-medium text-foreground">{context.company.name}</p> <p className="font-medium text-[#e2e5eb]">{context.company.name}</p>
{context.company.type && ( {context.company.type && (
<p className="text-muted-foreground">Type: {context.company.type}</p> <p className="text-[#848b9b]">Type: {context.company.type}</p>
)} )}
{context.company.territory && ( {context.company.territory && (
<p className="text-muted-foreground">Territory: {context.company.territory}</p> <p className="text-[#848b9b]">Territory: {context.company.territory}</p>
)} )}
{context.company.site && ( {context.company.site && (
<p className="text-muted-foreground">Site: {context.company.site}</p> <p className="text-[#848b9b]">Site: {context.company.site}</p>
)} )}
{context.company.address && ( {context.company.address && (
<p className="text-muted-foreground">{context.company.address}</p> <p className="text-[#848b9b]">{context.company.address}</p>
)} )}
{context.company.phone && ( {context.company.phone && (
<p className="text-muted-foreground">{context.company.phone}</p> <p className="text-[#848b9b]">{context.company.phone}</p>
)} )}
</div> </div>
</AccordionSection> </AccordionSection>
@@ -143,15 +143,15 @@ export function TicketContextPanel({ context, loading, error, onRefresh }: Ticke
{context.contact && ( {context.contact && (
<AccordionSection label="Contact" icon={<UserCircle className="h-3.5 w-3.5" />}> <AccordionSection label="Contact" icon={<UserCircle className="h-3.5 w-3.5" />}>
<div className="space-y-1 text-xs"> <div className="space-y-1 text-xs">
<p className="font-medium text-foreground">{context.contact.name}</p> <p className="font-medium text-[#e2e5eb]">{context.contact.name}</p>
{context.contact.title && ( {context.contact.title && (
<p className="text-muted-foreground">{context.contact.title}</p> <p className="text-[#848b9b]">{context.contact.title}</p>
)} )}
{context.contact.email && ( {context.contact.email && (
<p className="text-muted-foreground">{context.contact.email}</p> <p className="text-[#848b9b]">{context.contact.email}</p>
)} )}
{context.contact.phone && ( {context.contact.phone && (
<p className="text-muted-foreground">{context.contact.phone}</p> <p className="text-[#848b9b]">{context.contact.phone}</p>
)} )}
</div> </div>
</AccordionSection> </AccordionSection>
@@ -166,9 +166,9 @@ export function TicketContextPanel({ context, loading, error, onRefresh }: Ticke
> >
<div className="space-y-2"> <div className="space-y-2">
{context.configurations.map((cfg, i) => ( {context.configurations.map((cfg, i) => (
<div key={i} className="rounded-md border border-[rgba(255,255,255,0.06)] bg-card p-2"> <div key={i} className="rounded-md border border-[rgba(255,255,255,0.06)] bg-[#14161d] p-2">
<p className="text-xs font-medium text-foreground">{cfg.device_identifier}</p> <p className="text-xs font-medium text-[#e2e5eb]">{cfg.device_identifier}</p>
<div className="mt-0.5 space-y-0.5 text-[0.6875rem] text-muted-foreground"> <div className="mt-0.5 space-y-0.5 text-[0.6875rem] text-[#848b9b]">
{cfg.type && <p>Type: {cfg.type}</p>} {cfg.type && <p>Type: {cfg.type}</p>}
{cfg.os_type && <p>OS: {cfg.os_type}</p>} {cfg.os_type && <p>OS: {cfg.os_type}</p>}
{cfg.ip_address && <p>IP: {cfg.ip_address}</p>} {cfg.ip_address && <p>IP: {cfg.ip_address}</p>}
@@ -190,16 +190,16 @@ export function TicketContextPanel({ context, loading, error, onRefresh }: Ticke
> >
<div className="space-y-2"> <div className="space-y-2">
{context.notes.map((note, i) => ( {context.notes.map((note, i) => (
<div key={i} className="rounded-md border border-[rgba(255,255,255,0.06)] bg-card p-2"> <div key={i} className="rounded-md border border-[rgba(255,255,255,0.06)] bg-[#14161d] p-2">
<div className="mb-1 flex items-center justify-between gap-2"> <div className="mb-1 flex items-center justify-between gap-2">
{note.member && ( {note.member && (
<span className="text-[0.6rem] font-label text-muted-foreground">{note.member}</span> <span className="text-[0.6rem] font-sans text-xs text-[#848b9b]">{note.member}</span>
)} )}
<span className="ml-auto text-[0.6rem] font-label text-muted-foreground"> <span className="ml-auto text-[0.6rem] font-sans text-xs text-[#848b9b]">
{new Date(note.date_created).toLocaleDateString()} {new Date(note.date_created).toLocaleDateString()}
</span> </span>
</div> </div>
<p className="whitespace-pre-wrap text-[0.6875rem] text-foreground line-clamp-4"> <p className="whitespace-pre-wrap text-[0.6875rem] text-[#e2e5eb] line-clamp-4">
{note.text} {note.text}
</p> </p>
</div> </div>
@@ -219,16 +219,16 @@ export function TicketContextPanel({ context, loading, error, onRefresh }: Ticke
{context.related_tickets.map((rt) => ( {context.related_tickets.map((rt) => (
<div <div
key={rt.id} key={rt.id}
className="rounded-md border border-[rgba(255,255,255,0.06)] bg-card px-2 py-1.5" className="rounded-md border border-[rgba(255,255,255,0.06)] bg-[#14161d] px-2 py-1.5"
> >
<div className="flex items-baseline gap-1.5"> <div className="flex items-baseline gap-1.5">
<span className="font-label text-[0.6rem] text-primary">#{rt.id}</span> <span className="font-sans text-xs text-[0.6rem] text-[#22d3ee]">#{rt.id}</span>
<span className="flex-1 truncate text-[0.6875rem] text-foreground">{rt.summary}</span> <span className="flex-1 truncate text-[0.6875rem] text-[#e2e5eb]">{rt.summary}</span>
</div> </div>
<div className="mt-0.5 flex gap-1"> <div className="mt-0.5 flex gap-1">
<span className="text-[0.6rem] text-muted-foreground">{rt.status}</span> <span className="text-[0.6rem] text-[#848b9b]">{rt.status}</span>
<span className="text-[0.6rem] text-muted-foreground">·</span> <span className="text-[0.6rem] text-[#848b9b]">·</span>
<span className="text-[0.6rem] text-muted-foreground">{rt.priority}</span> <span className="text-[0.6rem] text-[#848b9b]">{rt.priority}</span>
</div> </div>
</div> </div>
))} ))}

View File

@@ -23,8 +23,8 @@ export function TicketLinkIndicator({ session, hasConnection, onLinkClick, onUnl
type="button" type="button"
onClick={onLinkClick} onClick={onLinkClick}
className={cn( className={cn(
'inline-flex items-center gap-1.5 rounded-lg px-2 py-1 text-xs text-muted-foreground transition-colors', 'inline-flex items-center gap-1.5 rounded-lg px-2 py-1 text-xs text-[#848b9b] transition-colors',
'hover:bg-accent hover:text-foreground' 'hover:bg-accent hover:text-[#e2e5eb]'
)} )}
> >
<Link2 className="h-3.5 w-3.5" /> <Link2 className="h-3.5 w-3.5" />
@@ -35,17 +35,17 @@ export function TicketLinkIndicator({ session, hasConnection, onLinkClick, onUnl
// Ticket linked // Ticket linked
return ( return (
<div className="glass-card-static inline-flex items-start gap-2.5 rounded-lg border border-border px-3 py-2"> <div className="card-flat inline-flex items-start gap-2.5 rounded-lg border border-[#1e2130] px-3 py-2">
<Ticket className="mt-0.5 h-4 w-4 shrink-0 text-cyan-400" /> <Ticket className="mt-0.5 h-4 w-4 shrink-0 text-cyan-400" />
<div className="min-w-0"> <div className="min-w-0">
<p className="text-sm font-medium text-foreground"> <p className="text-sm font-medium text-[#e2e5eb]">
CW #{session.psa_ticket_id} CW #{session.psa_ticket_id}
{ticketInfo?.summary && ( {ticketInfo?.summary && (
<span className="text-muted-foreground"> {ticketInfo.summary}</span> <span className="text-[#848b9b]"> {ticketInfo.summary}</span>
)} )}
</p> </p>
{ticketInfo && ( {ticketInfo && (
<div className="mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-muted-foreground"> <div className="mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-[#848b9b]">
{ticketInfo.company_name && <span>{ticketInfo.company_name}</span>} {ticketInfo.company_name && <span>{ticketInfo.company_name}</span>}
{ticketInfo.board_name && ( {ticketInfo.board_name && (
<> <>
@@ -68,8 +68,8 @@ export function TicketLinkIndicator({ session, hasConnection, onLinkClick, onUnl
type="button" type="button"
onClick={onUpdateClick} onClick={onUpdateClick}
className={cn( className={cn(
'inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-xs text-muted-foreground transition-colors', 'inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-xs text-[#848b9b] transition-colors',
'hover:bg-primary/10 hover:text-foreground' 'hover:bg-[rgba(34,211,238,0.10)] hover:text-[#e2e5eb]'
)} )}
title="Update ticket" title="Update ticket"
> >
@@ -80,7 +80,7 @@ export function TicketLinkIndicator({ session, hasConnection, onLinkClick, onUnl
<button <button
type="button" type="button"
onClick={onUnlink} onClick={onUnlink}
className="shrink-0 rounded p-0.5 text-xs text-muted-foreground transition-colors hover:text-foreground" className="shrink-0 rounded p-0.5 text-xs text-[#848b9b] transition-colors hover:text-[#e2e5eb]"
title="Unlink ticket" title="Unlink ticket"
> >
<Unlink className="h-3.5 w-3.5" /> <Unlink className="h-3.5 w-3.5" />

View File

@@ -219,8 +219,8 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
className={cn( className={cn(
'flex flex-1 items-center justify-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-all', 'flex flex-1 items-center justify-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-all',
mode === 'search' mode === 'search'
? 'bg-white/[0.08] text-foreground shadow-sm' ? 'bg-white/[0.08] text-[#e2e5eb] shadow-sm'
: 'text-muted-foreground hover:text-foreground' : 'text-[#848b9b] hover:text-[#e2e5eb]'
)} )}
> >
<Search className="h-3.5 w-3.5" /> <Search className="h-3.5 w-3.5" />
@@ -232,8 +232,8 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
className={cn( className={cn(
'flex flex-1 items-center justify-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-all', 'flex flex-1 items-center justify-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-all',
mode === 'manual' mode === 'manual'
? 'bg-white/[0.08] text-foreground shadow-sm' ? 'bg-white/[0.08] text-[#e2e5eb] shadow-sm'
: 'text-muted-foreground hover:text-foreground' : 'text-[#848b9b] hover:text-[#e2e5eb]'
)} )}
> >
<Hash className="h-3.5 w-3.5" /> <Hash className="h-3.5 w-3.5" />
@@ -257,12 +257,12 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
</div> </div>
{/* Include closed toggle */} {/* Include closed toggle */}
<label className="flex cursor-pointer items-center gap-2 text-xs text-muted-foreground"> <label className="flex cursor-pointer items-center gap-2 text-xs text-[#848b9b]">
<input <input
type="checkbox" type="checkbox"
checked={includeClosed} checked={includeClosed}
onChange={(e) => setIncludeClosed(e.target.checked)} onChange={(e) => setIncludeClosed(e.target.checked)}
className="rounded border-border bg-card accent-primary" className="rounded border-[#1e2130] bg-[#14161d] accent-primary"
/> />
Include closed tickets Include closed tickets
</label> </label>
@@ -270,12 +270,12 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
{/* Search results */} {/* Search results */}
{isSearching && ( {isSearching && (
<div className="flex items-center justify-center py-6"> <div className="flex items-center justify-center py-6">
<Loader2 className="h-5 w-5 animate-spin text-muted-foreground" /> <Loader2 className="h-5 w-5 animate-spin text-[#848b9b]" />
</div> </div>
)} )}
{!isSearching && hasSearched && searchResults.length === 0 && ( {!isSearching && hasSearched && searchResults.length === 0 && (
<div className="py-6 text-center text-sm text-muted-foreground"> <div className="py-6 text-center text-sm text-[#848b9b]">
No tickets found No tickets found
</div> </div>
)} )}
@@ -290,17 +290,17 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
disabled={isLooking} disabled={isLooking}
className={cn( className={cn(
'w-full rounded-lg border border-transparent px-3 py-2.5 text-left transition-all', 'w-full rounded-lg border border-transparent px-3 py-2.5 text-left transition-all',
'hover:border-border hover:bg-white/[0.04]', 'hover:border-[#1e2130] hover:bg-white/[0.04]',
'disabled:opacity-50', 'disabled:opacity-50',
result.closed && 'opacity-60' result.closed && 'opacity-60'
)} )}
> >
<p className="truncate text-sm font-medium text-foreground"> <p className="truncate text-sm font-medium text-[#e2e5eb]">
<span className="text-muted-foreground">#{result.id}</span> <span className="text-[#848b9b]">#{result.id}</span>
{' — '} {' — '}
{result.summary} {result.summary}
</p> </p>
<div className="mt-0.5 flex flex-wrap items-center gap-x-2 text-xs text-muted-foreground"> <div className="mt-0.5 flex flex-wrap items-center gap-x-2 text-xs text-[#848b9b]">
{result.company_name && <span>{result.company_name}</span>} {result.company_name && <span>{result.company_name}</span>}
{result.board_name && ( {result.board_name && (
<> <>
@@ -324,8 +324,8 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
{isLooking && ( {isLooking && (
<div className="flex items-center justify-center py-3"> <div className="flex items-center justify-center py-3">
<Loader2 className="h-5 w-5 animate-spin text-muted-foreground" /> <Loader2 className="h-5 w-5 animate-spin text-[#848b9b]" />
<span className="ml-2 text-sm text-muted-foreground">Loading ticket details...</span> <span className="ml-2 text-sm text-[#848b9b]">Loading ticket details...</span>
</div> </div>
)} )}
</div> </div>
@@ -334,7 +334,7 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
{/* Manual mode */} {/* Manual mode */}
{mode === 'manual' && !selectedTicket && ( {mode === 'manual' && !selectedTicket && (
<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]">
Ticket Number Ticket Number
</label> </label>
<div className="flex gap-2"> <div className="flex gap-2">
@@ -376,14 +376,14 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
{/* Selected ticket confirmation card */} {/* Selected ticket confirmation card */}
{selectedTicket && selectedTicketId && ( {selectedTicket && selectedTicketId && (
<div className="glass-card-static space-y-3 rounded-xl border border-border p-4"> <div className="card-flat space-y-3 rounded-xl border border-[#1e2130] p-4">
<div className="flex items-start gap-2"> <div className="flex items-start gap-2">
<CheckCircle2 className="mt-0.5 h-4 w-4 shrink-0 text-emerald-400" /> <CheckCircle2 className="mt-0.5 h-4 w-4 shrink-0 text-emerald-400" />
<div className="min-w-0"> <div className="min-w-0">
<p className="text-sm font-semibold text-foreground"> <p className="text-sm font-semibold text-[#e2e5eb]">
CW #{selectedTicketId} {selectedTicket.summary} CW #{selectedTicketId} {selectedTicket.summary}
</p> </p>
<div className="mt-1.5 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-muted-foreground"> <div className="mt-1.5 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-[#848b9b]">
{selectedTicket.company_name && ( {selectedTicket.company_name && (
<span>{selectedTicket.company_name}</span> <span>{selectedTicket.company_name}</span>
)} )}
@@ -437,8 +437,8 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
type="button" type="button"
onClick={handleClose} onClick={handleClose}
className={cn( className={cn(
'text-sm text-muted-foreground transition-colors', 'text-sm text-[#848b9b] transition-colors',
'hover:text-foreground' 'hover:text-[#e2e5eb]'
)} )}
> >
Skip Skip

View File

@@ -134,7 +134,7 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
<button <button
type="button" type="button"
onClick={onClose} onClick={onClose}
className="text-sm text-muted-foreground hover:text-foreground transition-colors" className="text-sm text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
> >
Cancel Cancel
</button> </button>
@@ -143,9 +143,9 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
onClick={handlePost} onClick={handlePost}
disabled={isPosting || !content.trim()} disabled={isPosting || !content.trim()}
className={cn( className={cn(
'inline-flex items-center gap-2 rounded-[10px] px-5 py-2.5 text-sm font-semibold', 'inline-flex items-center gap-2 rounded-lg px-5 py-2.5 text-sm font-semibold',
'bg-gradient-brand text-[#101114] shadow-lg shadow-primary/20', 'bg-[#22d3ee] text-white',
'hover:opacity-90 active:scale-[0.97] transition-all', 'hover:brightness-110 active:scale-[0.98] transition-all',
'disabled:opacity-50 disabled:cursor-not-allowed' 'disabled:opacity-50 disabled:cursor-not-allowed'
)} )}
> >
@@ -160,7 +160,7 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
<Modal isOpen={open} onClose={onClose} title="Update Ticket" size="xl" footer={footer}> <Modal isOpen={open} onClose={onClose} title="Update Ticket" size="xl" footer={footer}>
{isLoading && ( {isLoading && (
<div className="flex items-center justify-center py-12"> <div className="flex items-center justify-center py-12">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" /> <Loader2 className="h-8 w-8 animate-spin text-[#848b9b]" />
</div> </div>
)} )}
@@ -172,7 +172,7 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
</div> </div>
<button <button
onClick={loadPreview} onClick={loadPreview}
className="text-sm text-muted-foreground hover:text-foreground transition-colors" className="text-sm text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
> >
Try again Try again
</button> </button>
@@ -184,13 +184,13 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
{/* Left panel - Content editor */} {/* Left panel - Content editor */}
<div className="space-y-3"> <div className="space-y-3">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<p className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground"> <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">
Note Content Note Content
</p> </p>
<button <button
type="button" type="button"
onClick={handleCopyContent} onClick={handleCopyContent}
className="inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-xs text-muted-foreground hover:text-foreground transition-colors" className="inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-xs text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
title="Copy content" title="Copy content"
> >
<Copy className="h-3 w-3" /> <Copy className="h-3 w-3" />
@@ -214,7 +214,7 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
) : ( ) : (
<span /> <span />
)} )}
<span className="text-muted-foreground"> <span className="text-[#848b9b]">
{content.length.toLocaleString()} characters {content.length.toLocaleString()} characters
</span> </span>
</div> </div>
@@ -223,15 +223,15 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
{/* Right panel - Controls */} {/* Right panel - Controls */}
<div className="space-y-6"> <div className="space-y-6">
{/* Ticket info summary */} {/* Ticket info summary */}
<div className="glass-card-static rounded-lg border border-border p-3"> <div className="card-flat rounded-lg border border-[#1e2130] p-3">
<p className="text-sm font-medium text-foreground"> <p className="text-sm font-medium text-[#e2e5eb]">
CW #{preview.ticket.id} CW #{preview.ticket.id}
{preview.ticket.summary && ( {preview.ticket.summary && (
<span className="text-muted-foreground"> {preview.ticket.summary}</span> <span className="text-[#848b9b]"> {preview.ticket.summary}</span>
)} )}
</p> </p>
{(preview.ticket.company_name || preview.ticket.board_name) && ( {(preview.ticket.company_name || preview.ticket.board_name) && (
<p className="mt-1 text-xs text-muted-foreground"> <p className="mt-1 text-xs text-[#848b9b]">
{[preview.ticket.company_name, preview.ticket.board_name].filter(Boolean).join(' / ')} {[preview.ticket.company_name, preview.ticket.board_name].filter(Boolean).join(' / ')}
</p> </p>
)} )}
@@ -239,7 +239,7 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
{/* Note Type */} {/* Note Type */}
<div> <div>
<p className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground mb-3"> <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b] mb-3">
Note Type Note Type
</p> </p>
<div className="space-y-2"> <div className="space-y-2">
@@ -250,7 +250,7 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
'flex cursor-pointer items-start gap-3 rounded-lg border px-3 py-2.5 transition-colors', 'flex cursor-pointer items-start gap-3 rounded-lg border px-3 py-2.5 transition-colors',
noteType === opt.value noteType === opt.value
? 'border-primary/30 bg-primary/5' ? 'border-primary/30 bg-primary/5'
: 'border-border hover:border-[rgba(255,255,255,0.12)]' : 'border-[#1e2130] hover:border-[rgba(255,255,255,0.12)]'
)} )}
> >
<input <input
@@ -262,8 +262,8 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
className="mt-0.5 accent-cyan-400" className="mt-0.5 accent-cyan-400"
/> />
<div className="min-w-0"> <div className="min-w-0">
<span className="text-sm font-medium text-foreground">{opt.label}</span> <span className="text-sm font-medium text-[#e2e5eb]">{opt.label}</span>
<p className="text-xs text-muted-foreground">{opt.description}</p> <p className="text-xs text-[#848b9b]">{opt.description}</p>
{opt.warning && noteType === opt.value && ( {opt.warning && noteType === opt.value && (
<p className="mt-1 flex items-center gap-1 text-xs text-amber-400"> <p className="mt-1 flex items-center gap-1 text-xs text-amber-400">
<AlertTriangle className="h-3 w-3 shrink-0" /> <AlertTriangle className="h-3 w-3 shrink-0" />
@@ -278,14 +278,14 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
{/* Ticket Status */} {/* Ticket Status */}
<div> <div>
<p className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground mb-2"> <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b] mb-2">
Ticket Status Ticket Status
</p> </p>
<select <select
value={selectedStatusId ?? ''} value={selectedStatusId ?? ''}
onChange={(e) => setSelectedStatusId(e.target.value ? Number(e.target.value) : null)} onChange={(e) => setSelectedStatusId(e.target.value ? Number(e.target.value) : null)}
className={cn( className={cn(
'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground', 'w-full rounded-md border border-[#1e2130] bg-[#14161d] px-3 py-2 text-sm text-[#e2e5eb]',
'focus:border-primary/30 focus:outline-hidden focus:ring-1 focus:ring-primary/20' 'focus:border-primary/30 focus:outline-hidden focus:ring-1 focus:ring-primary/20'
)} )}
> >
@@ -301,7 +301,7 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
{/* Previous posts */} {/* Previous posts */}
{preview.previous_posts > 0 && ( {preview.previous_posts > 0 && (
<p className="text-xs text-muted-foreground"> <p className="text-xs text-[#848b9b]">
This session has been posted {preview.previous_posts} time{preview.previous_posts > 1 ? 's' : ''} before. This session has been posted {preview.previous_posts} time{preview.previous_posts > 1 ? 's' : ''} before.
</p> </p>
)} )}

View File

@@ -23,14 +23,14 @@ export function VariablePromptModal({ prompt, onSubmit, onCancel }: VariableProm
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-xs"> <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-xs">
<div className="bg-card border border-border w-full max-w-md rounded-2xl p-6 shadow-lg"> <div className="bg-[#14161d] border border-[#1e2130] w-full max-w-md rounded-lg p-6 shadow-lg">
<h2 className="mb-1 text-lg font-semibold text-foreground">Input Required</h2> <h2 className="mb-1 text-lg font-semibold text-[#e2e5eb]">Input Required</h2>
<p className="mb-4 text-sm text-muted-foreground"> <p className="mb-4 text-sm text-[#848b9b]">
This step requires you to provide a value. This step requires you to provide a value.
</p> </p>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<label className="mb-2 block text-sm font-medium text-muted-foreground"> <label className="mb-2 block text-sm font-medium text-[#848b9b]">
{prompt} {prompt}
</label> </label>
<input <input
@@ -40,8 +40,8 @@ export function VariablePromptModal({ prompt, onSubmit, onCancel }: VariableProm
placeholder="Enter value..." placeholder="Enter value..."
autoFocus autoFocus
className={cn( className={cn(
'w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground', 'w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2 text-sm text-[#e2e5eb]',
'placeholder:text-muted-foreground focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20' 'placeholder:text-[#848b9b] focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20'
)} )}
/> />