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 (
<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">
<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>
<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,
and all associated flows will be permanently deleted.
</p>
<form onSubmit={handleDelete} className="space-y-4">
<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
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
className={cn(
'mt-1 block w-full rounded-[10px] border border-border bg-card px-3 py-2',
'text-foreground focus:border-primary focus:outline-hidden'
'mt-1 block w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2',
'text-[#e2e5eb] focus:border-primary focus:outline-hidden'
)}
/>
</div>
@@ -68,8 +68,8 @@ export function DeleteAccountModal({ onClose }: Props) {
type="button"
onClick={onClose}
className={cn(
'rounded-[10px] px-4 py-2 text-sm font-medium',
'bg-white/[0.04] border border-brand-border text-foreground'
'rounded-lg px-4 py-2 text-sm font-medium',
'bg-white/[0.04] border border-brand-border text-[#e2e5eb]'
)}
>
Cancel
@@ -78,7 +78,7 @@ export function DeleteAccountModal({ onClose }: Props) {
type="submit"
disabled={isSubmitting || !password}
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'
)}
>

View File

@@ -31,21 +31,21 @@ export function LeaveAccountModal({ accountName, onClose }: Props) {
return (
<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">
<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>
<p className="text-sm text-muted-foreground mb-4">
Are you sure you want to leave <strong className="text-foreground">{accountName}</strong>?
<p className="text-sm text-[#848b9b] mb-4">
Are you sure you want to leave <strong className="text-[#e2e5eb]">{accountName}</strong>?
A new personal account will be created for you.
</p>
<div className="flex justify-end gap-3">
<button
onClick={onClose}
className={cn(
'rounded-[10px] px-4 py-2 text-sm font-medium',
'bg-white/[0.04] border border-brand-border text-foreground'
'rounded-lg px-4 py-2 text-sm font-medium',
'bg-white/[0.04] border border-brand-border text-[#e2e5eb]'
)}
>
Cancel
@@ -54,7 +54,7 @@ export function LeaveAccountModal({ accountName, onClose }: Props) {
onClick={handleLeave}
disabled={isSubmitting}
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'
)}
>

View File

@@ -173,16 +173,16 @@ export function NotificationSettings() {
{/* Section header */}
<div className="mb-6 flex items-center justify-between">
<div className="flex items-center gap-3">
<Bell className="h-6 w-6 text-muted-foreground" />
<h2 className="text-xl font-semibold font-heading text-foreground">Notifications</h2>
<Bell className="h-6 w-6 text-[#848b9b]" />
<h2 className="text-xl font-semibold font-heading text-[#e2e5eb]">Notifications</h2>
</div>
<div className="relative" ref={dropdownRef}>
<button
onClick={() => setShowDropdown(!showDropdown)}
className={cn(
'inline-flex items-center gap-2 rounded-[10px] 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',
'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-[#e2e5eb]',
'hover:border-[rgba(255,255,255,0.12)] transition-all'
)}
>
@@ -192,16 +192,16 @@ export function NotificationSettings() {
</button>
{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]) => {
const Icon = CHANNEL_ICONS[key]
return (
<button
key={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}
</button>
)
@@ -214,15 +214,15 @@ export function NotificationSettings() {
{/* Loading */}
{loading && (
<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>
)}
{/* Empty state */}
{!loading && configs.length === 0 && !addingChannel && (
<div className="glass-card-static p-6 text-center">
<Bell className="mx-auto h-8 w-8 text-muted-foreground/50 mb-3" />
<p className="text-sm text-muted-foreground">
<div className="card-flat p-6 text-center">
<Bell className="mx-auto h-8 w-8 text-[#848b9b]/50 mb-3" />
<p className="text-sm text-[#848b9b]">
No notification channels configured. Add a channel to receive alerts for session events.
</p>
</div>
@@ -234,11 +234,11 @@ export function NotificationSettings() {
{configs.map(config => {
const Icon = CHANNEL_ICONS[config.channel]
return (
<div key={config.id} className="glass-card-static p-5">
<div key={config.id} className="card-flat p-5">
{/* Header row */}
<div className="flex items-center gap-3 mb-4">
<Icon className="h-5 w-5 text-muted-foreground" />
<span className="text-sm font-medium text-foreground">
<Icon className="h-5 w-5 text-[#848b9b]" />
<span className="text-sm font-medium text-[#e2e5eb]">
{CHANNEL_LABELS[config.channel]}
</span>
<span
@@ -248,8 +248,8 @@ export function NotificationSettings() {
)}
/>
<span className={cn(
'text-xs font-label',
config.is_active ? 'text-emerald-400' : 'text-muted-foreground'
'text-xs font-sans text-xs',
config.is_active ? 'text-emerald-400' : 'text-[#848b9b]'
)}>
{config.is_active ? 'Active' : 'Inactive'}
</span>
@@ -259,20 +259,20 @@ export function NotificationSettings() {
<div className="mb-4">
{config.webhook_url && (
<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
</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)}
</p>
</div>
)}
{config.email_addresses && config.email_addresses.length > 0 && (
<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
</span>
<p className="mt-0.5 text-sm text-foreground">
<p className="mt-0.5 text-sm text-[#e2e5eb]">
{config.email_addresses.join(', ')}
</p>
</div>
@@ -281,7 +281,7 @@ export function NotificationSettings() {
{/* Event toggles */}
<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
</span>
<div className="mt-2 grid gap-2 sm:grid-cols-2">
@@ -294,28 +294,28 @@ export function NotificationSettings() {
type="checkbox"
checked={config.events_enabled[eventKey] ?? false}
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>
))}
</div>
</div>
{/* 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
onClick={() => handleToggleActive(config)}
className={cn(
'inline-flex items-center gap-1.5 rounded-[10px] 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',
'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-[#e2e5eb]',
'hover:border-[rgba(255,255,255,0.12)] transition-all'
)}
>
{config.is_active ? (
<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'}
</button>
@@ -324,8 +324,8 @@ export function NotificationSettings() {
onClick={() => handleTest(config.id)}
disabled={testingId === config.id}
className={cn(
'inline-flex items-center gap-1.5 rounded-[10px] 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',
'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-[#e2e5eb]',
'hover:border-[rgba(255,255,255,0.12)] transition-all',
'disabled:opacity-50 disabled:cursor-not-allowed'
)}
@@ -349,7 +349,7 @@ export function NotificationSettings() {
) : (
<button
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" />
Remove
@@ -362,20 +362,20 @@ export function NotificationSettings() {
{/* Inline add form */}
{addingChannel && (
<div className="glass-card-static p-5">
<div className="card-flat p-5">
<div className="flex items-center gap-3 mb-4">
{(() => {
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]}
</span>
</div>
{addingChannel === 'email' ? (
<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
</label>
<Input
@@ -385,13 +385,13 @@ export function NotificationSettings() {
placeholder="user@example.com, team@example.com"
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
</p>
</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
</label>
<Input
@@ -413,9 +413,9 @@ export function NotificationSettings() {
onClick={handleSaveNew}
disabled={isSaving}
className={cn(
'inline-flex items-center gap-2 rounded-[10px] px-5 py-2.5 text-sm font-semibold',
'bg-gradient-brand text-[#101114] shadow-lg shadow-primary/20',
'hover:opacity-90 active:scale-[0.97] transition-all',
'inline-flex items-center gap-2 rounded-lg px-5 py-2.5 text-sm font-semibold',
'bg-[#22d3ee] text-white',
'hover:brightness-110 active:scale-[0.98] transition-all',
'disabled:opacity-50 disabled:cursor-not-allowed'
)}
>
@@ -424,7 +424,7 @@ export function NotificationSettings() {
</button>
<button
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
</button>

View File

@@ -40,27 +40,27 @@ export function TransferOwnershipModal({ members, onClose, onTransferred }: Prop
return (
<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">
<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>
<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.
</p>
{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">
<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
value={targetUserId}
onChange={(e) => setTargetUserId(e.target.value)}
className={cn(
'mt-1 block w-full rounded-[10px] border border-border bg-card px-3 py-2',
'text-foreground focus:border-primary focus:outline-hidden'
'mt-1 block w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2',
'text-[#e2e5eb] focus:border-primary focus:outline-hidden'
)}
>
{nonOwnerMembers.map((m) => (
@@ -69,15 +69,15 @@ export function TransferOwnershipModal({ members, onClose, onTransferred }: Prop
</select>
</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
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
className={cn(
'mt-1 block w-full rounded-[10px] border border-border bg-card px-3 py-2',
'text-foreground focus:border-primary focus:outline-hidden'
'mt-1 block w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2',
'text-[#e2e5eb] focus:border-primary focus:outline-hidden'
)}
/>
</div>
@@ -89,8 +89,8 @@ export function TransferOwnershipModal({ members, onClose, onTransferred }: Prop
type="button"
onClick={onClose}
className={cn(
'rounded-[10px] px-4 py-2 text-sm font-medium',
'bg-white/[0.04] border border-brand-border text-foreground'
'rounded-lg px-4 py-2 text-sm font-medium',
'bg-white/[0.04] border border-brand-border text-[#e2e5eb]'
)}
>
Cancel
@@ -99,7 +99,7 @@ export function TransferOwnershipModal({ members, onClose, onTransferred }: Prop
type="submit"
disabled={isSubmitting || !password}
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',
'disabled:opacity-50'
)}

View File

@@ -63,16 +63,16 @@ export function SaveToLibraryDialog({
return (
<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() }}
>
<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 */}
<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
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} />
</button>
@@ -82,7 +82,7 @@ export function SaveToLibraryDialog({
<form onSubmit={handleSubmit} className="p-5 space-y-4">
{/* Name */}
<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 *
</label>
<input
@@ -91,8 +91,8 @@ export function SaveToLibraryDialog({
onChange={(e) => setName(e.target.value)}
required
className={cn(
"w-full rounded-[10px] px-3 py-2 text-sm",
"border border-border bg-card text-foreground placeholder:text-muted-foreground",
"w-full rounded-lg px-3 py-2 text-sm",
"border border-[#1e2130] bg-[#14161d] text-[#e2e5eb] placeholder:text-[#848b9b]",
"focus:outline-none focus:border-[rgba(6,182,212,0.3)] transition-colors"
)}
placeholder="Script name"
@@ -101,7 +101,7 @@ export function SaveToLibraryDialog({
{/* Description */}
<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
</label>
<textarea
@@ -109,8 +109,8 @@ export function SaveToLibraryDialog({
onChange={(e) => setDescription(e.target.value)}
rows={3}
className={cn(
"w-full rounded-[10px] px-3 py-2 text-sm resize-none",
"border border-border bg-card text-foreground placeholder:text-muted-foreground",
"w-full rounded-lg px-3 py-2 text-sm resize-none",
"border border-[#1e2130] bg-[#14161d] text-[#e2e5eb] placeholder:text-[#848b9b]",
"focus:outline-none focus:border-[rgba(6,182,212,0.3)] transition-colors"
)}
placeholder="What does this script do?"
@@ -119,15 +119,15 @@ export function SaveToLibraryDialog({
{/* Category */}
<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
</label>
<select
value={categoryId}
onChange={(e) => setCategoryId(e.target.value)}
className={cn(
"w-full rounded-[10px] px-3 py-2 text-sm",
"border border-border bg-card text-foreground",
"w-full rounded-lg px-3 py-2 text-sm",
"border border-[#1e2130] bg-[#14161d] text-[#e2e5eb]",
"focus:outline-none focus:border-[rgba(6,182,212,0.3)] transition-colors"
)}
>
@@ -144,9 +144,9 @@ export function SaveToLibraryDialog({
type="checkbox"
checked={shareWithTeam}
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>
{/* Error */}
@@ -160,8 +160,8 @@ export function SaveToLibraryDialog({
type="button"
onClick={onClose}
className={cn(
"px-4 py-2 rounded-[10px] 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)]"
"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-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)]"
)}
>
Cancel
@@ -170,8 +170,8 @@ export function SaveToLibraryDialog({
type="submit"
disabled={!name.trim() || isSaving}
className={cn(
"flex items-center gap-2 px-4 py-2 rounded-[10px] text-sm font-semibold transition-all",
"bg-gradient-brand text-[#101114] hover:opacity-90 active:scale-[0.97]",
"flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-semibold transition-all",
"bg-[#22d3ee] text-white hover:brightness-110 active:scale-[0.98]",
"disabled:opacity-50 disabled:cursor-not-allowed"
)}
>

View File

@@ -30,13 +30,13 @@ export function ScriptBuilderChat({
return (
<div className="flex-1 flex items-center justify-center p-8">
<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">
<Bot size={28} className="text-[#101114]" />
<div className="w-14 h-14 rounded-2xl bg-[#22d3ee] flex items-center justify-center mx-auto mb-4">
<Bot size={28} className="text-white" />
</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
</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,
preview it, and save it to your library.
</p>
@@ -65,8 +65,8 @@ export function ScriptBuilderChat({
className={cn(
"max-w-[85%] rounded-xl px-4 py-3 text-sm",
msg.role === 'user'
? "bg-[rgba(6,182,212,0.08)] border border-[rgba(6,182,212,0.15)] text-foreground"
: "glass-card-static"
? "bg-[rgba(6,182,212,0.08)] border border-[rgba(6,182,212,0.15)] text-[#e2e5eb]"
: "card-flat"
)}
>
{msg.role === 'assistant' ? (
@@ -90,7 +90,7 @@ export function ScriptBuilderChat({
{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">
<User size={16} className="text-muted-foreground" />
<User size={16} className="text-[#848b9b]" />
</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">
<Bot size={16} className="text-cyan-400" />
</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" />
<span className="text-muted-foreground">Generating script...</span>
<span className="text-[#848b9b]">Generating script...</span>
</div>
</div>
)}

View File

@@ -55,7 +55,7 @@ export function ScriptBuilderInput({
rows={1}
className={cn(
"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",
"disabled:opacity-50"
)}
@@ -67,7 +67,7 @@ export function ScriptBuilderInput({
className={cn(
"shrink-0 flex items-center justify-center w-10 h-10 rounded-xl transition-all",
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"
)}
>

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">
{/* Header */}
<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'}
</span>
{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
</span>
)}
@@ -85,7 +85,7 @@ export function ScriptCodeBlock({
{previewLines}
</SyntaxHighlighter>
{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' : ''}
</div>
)}
@@ -96,8 +96,8 @@ export function ScriptCodeBlock({
<button
onClick={onViewFull}
className={cn(
"flex items-center gap-1.5 px-3 py-1.5 rounded-[10px] text-xs font-semibold transition-all",
"bg-gradient-brand text-[#101114] hover:opacity-90 active:scale-[0.97]"
"flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-semibold transition-all",
"bg-[#22d3ee] text-white hover:brightness-110 active:scale-[0.98]"
)}
>
<Eye size={14} />
@@ -106,8 +106,8 @@ export function ScriptCodeBlock({
<button
onClick={handleCopy}
className={cn(
"flex items-center gap-1.5 px-3 py-1.5 rounded-[10px] 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)]"
"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-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)]"
)}
>
{copied ? <Check size={14} className="text-emerald-400" /> : <Copy size={14} />}
@@ -116,7 +116,7 @@ export function ScriptCodeBlock({
<button
onClick={(e) => { e.stopPropagation(); onSave() }}
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"
)}
>

View File

@@ -55,17 +55,17 @@ export function ScriptPreviewModal({
return (
<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() }}
>
<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 */}
<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">
<span className="font-label text-sm text-cyan-400 truncate">
<span className="font-mono text-sm text-cyan-400 truncate">
{filename || 'script'}
</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}
</span>
</div>
@@ -73,8 +73,8 @@ export function ScriptPreviewModal({
<button
onClick={handleCopy}
className={cn(
"flex items-center gap-1.5 px-3 py-1.5 rounded-[10px] 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)]"
"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-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)]"
)}
>
{copied ? <Check size={14} className="text-emerald-400" /> : <Copy size={14} />}
@@ -83,7 +83,7 @@ export function ScriptPreviewModal({
<button
onClick={onSave}
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"
)}
>
@@ -92,7 +92,7 @@ export function ScriptPreviewModal({
</button>
<button
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} />
</button>
@@ -126,14 +126,14 @@ export function ScriptPreviewModal({
{/* Footer */}
<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' : ''}
</span>
<button
onClick={onClose}
className={cn(
"px-4 py-1.5 rounded-[10px] 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)]"
"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-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)]"
)}
>
Close & Return to Chat

View File

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

View File

@@ -40,7 +40,7 @@ export function CSATModal({ isOpen, onClose, sessionId }: CSATModalProps) {
return (
<Modal isOpen={isOpen} onClose={handleSkip} title="How was this flow?" size="sm">
<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.
</p>
@@ -60,7 +60,7 @@ export function CSATModal({ isOpen, onClose, sessionId }: CSATModalProps) {
'transition-colors',
(hoveredRating || rating) >= value
? 'fill-yellow-400 text-yellow-400'
: 'fill-none text-muted-foreground'
: 'fill-none text-[#848b9b]'
)}
/>
</button>
@@ -74,21 +74,21 @@ export function CSATModal({ isOpen, onClose, sessionId }: CSATModalProps) {
placeholder="Any comments? (optional)"
maxLength={500}
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 */}
<div className="flex items-center justify-between">
<button
onClick={handleSkip}
className="text-sm text-muted-foreground hover:text-foreground transition-colors"
className="text-sm text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
>
Skip
</button>
<button
onClick={handleSubmit}
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'}
</button>

View File

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

View File

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

View File

@@ -69,11 +69,11 @@ export function ForkTreeModal({
<div className="space-y-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">
<GitFork className="h-5 w-5 text-foreground" />
<GitFork className="h-5 w-5 text-[#e2e5eb]" />
</div>
<div>
<p className="font-medium text-foreground">You've created a custom troubleshooting path!</p>
<p className="mt-1 text-sm text-muted-foreground">
<p className="font-medium text-[#e2e5eb]">You've created a custom troubleshooting path!</p>
<p className="mt-1 text-sm text-[#848b9b]">
Save it as your own personal tree to reuse this troubleshooting flow in the future.
</p>
</div>
@@ -81,7 +81,7 @@ export function ForkTreeModal({
<div className="space-y-4">
<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>
</label>
<Input
@@ -94,8 +94,8 @@ export function ForkTreeModal({
</div>
<div>
<label htmlFor="tree-description" className="mb-1.5 block text-sm font-medium text-foreground">
Description <span className="text-muted-foreground">(optional)</span>
<label htmlFor="tree-description" className="mb-1.5 block text-sm font-medium text-[#e2e5eb]">
Description <span className="text-[#848b9b]">(optional)</span>
</label>
<Textarea
id="tree-description"
@@ -112,7 +112,7 @@ export function ForkTreeModal({
<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.
</p>
</div>

View File

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

View File

@@ -36,21 +36,21 @@ export function SaveSessionAsTreeModal({
return (
<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 */}
<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
onClick={onClose}
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" />
</button>
</div>
{/* 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.
</p>
@@ -58,8 +58,8 @@ export function SaveSessionAsTreeModal({
<form onSubmit={handleSubmit} className="space-y-4">
{/* Tree Name */}
<div>
<label htmlFor="treeName" className="mb-1 block text-sm font-medium text-foreground">
Tree Name <span className="text-muted-foreground">(optional)</span>
<label htmlFor="treeName" className="mb-1 block text-sm font-medium text-[#e2e5eb]">
Tree Name <span className="text-[#848b9b]">(optional)</span>
</label>
<Input
id="treeName"
@@ -74,8 +74,8 @@ export function SaveSessionAsTreeModal({
{/* Description */}
<div>
<label htmlFor="description" className="mb-1 block text-sm font-medium text-foreground">
Description <span className="text-muted-foreground">(optional)</span>
<label htmlFor="description" className="mb-1 block text-sm font-medium text-[#e2e5eb]">
Description <span className="text-[#848b9b]">(optional)</span>
</label>
<Textarea
id="description"
@@ -89,7 +89,7 @@ export function SaveSessionAsTreeModal({
{/* Status */}
<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">
<label className="flex cursor-pointer items-center gap-2">
<input
@@ -99,9 +99,9 @@ export function SaveSessionAsTreeModal({
checked={status === 'draft'}
onChange={() => setStatus('draft')}
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 className="flex cursor-pointer items-center gap-2">
<input
@@ -111,9 +111,9 @@ export function SaveSessionAsTreeModal({
checked={status === 'published'}
onChange={() => setStatus('published')}
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>
</div>
</div>

View File

@@ -124,8 +124,8 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
onClick={() => setIsCollapsed(false)}
className={cn(
'fixed right-2 top-1/2 z-40 -translate-y-1/2 rounded-md p-2.5',
'bg-card border border-border shadow-md',
'text-muted-foreground hover:bg-accent hover:text-foreground',
'bg-[#14161d] border border-[#1e2130] shadow-md',
'text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]',
'transition-opacity duration-200',
isCollapsed ? 'opacity-100' : 'pointer-events-none opacity-0'
)}
@@ -153,29 +153,29 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
'fixed z-40',
'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]',
'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',
isCollapsed ? 'translate-x-full' : 'translate-x-0'
)}
>
{/* 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">
<StickyNote className="h-4 w-4 text-muted-foreground" />
<span className="text-sm font-medium text-foreground">Scratchpad</span>
<span className="text-xs text-muted-foreground">Ctrl+/</span>
<StickyNote className="h-4 w-4 text-[#848b9b]" />
<span className="text-sm font-medium text-[#e2e5eb]">Scratchpad</span>
<span className="text-xs text-[#848b9b]">Ctrl+/</span>
</div>
<div className="flex items-center gap-1">
<button
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'}
>
{showPreview ? <Pencil className="h-3.5 w-3.5" /> : <Eye className="h-3.5 w-3.5" />}
</button>
<button
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"
aria-label="Close scratchpad"
>
@@ -191,7 +191,7 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
{content.trim() ? (
<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>
) : (
@@ -202,7 +202,7 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
placeholder={"Capture IPs, error codes, server names, user info...\n\nSupports markdown formatting."}
className={cn(
'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'
)}
/>
@@ -210,15 +210,15 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
</div>
{/* 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">
{saveStatus === 'unsaved' && (
<span className="text-muted-foreground">Unsaved changes</span>
<span className="text-[#848b9b]">Unsaved changes</span>
)}
{saveStatus === 'saving' && (
<>
<Loader2 className="h-3 w-3 animate-spin text-muted-foreground" />
<span className="text-muted-foreground">Saving...</span>
<Loader2 className="h-3 w-3 animate-spin text-[#848b9b]" />
<span className="text-[#848b9b]">Saving...</span>
</>
)}
{saveStatus === 'saved' && (
@@ -228,7 +228,7 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
<span className="text-red-400">Save failed</span>
)}
{saveStatus === 'idle' && (
<span className="text-muted-foreground">Markdown supported</span>
<span className="text-[#848b9b]">Markdown supported</span>
)}
</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">
{/* Ticket Number Search */}
<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
type="text"
placeholder="Search by ticket number..."
value={filters.ticketNumber}
onChange={(e) => handleFilterChange('ticketNumber', e.target.value)}
className={cn(
'w-full rounded-md border border-border bg-card py-2 pl-9 pr-3',
'text-foreground placeholder:text-muted-foreground',
'w-full rounded-md border border-[#1e2130] bg-[#14161d] py-2 pl-9 pr-3',
'text-[#e2e5eb] placeholder:text-[#848b9b]',
'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 */}
<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
type="text"
placeholder="Search by client name..."
value={filters.clientName}
onChange={(e) => handleFilterChange('clientName', e.target.value)}
className={cn(
'w-full rounded-md border border-border bg-card py-2 pl-9 pr-3',
'text-foreground placeholder:text-muted-foreground',
'w-full rounded-md border border-[#1e2130] bg-[#14161d] py-2 pl-9 pr-3',
'text-[#e2e5eb] placeholder:text-[#848b9b]',
'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}
onChange={(e) => handleFilterChange('treeName', e.target.value)}
className={cn(
'rounded-md border border-border bg-card px-3 py-2',
'text-foreground focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20',
'rounded-md border border-[#1e2130] bg-[#14161d] px-3 py-2',
'text-[#e2e5eb] focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20',
'sm:min-w-[200px]'
)}
>
@@ -148,19 +148,19 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
<button
onClick={() => setShowDatePicker(!showDatePicker)}
className={cn(
'flex w-full items-center gap-2 rounded-md border border-border bg-card px-3 py-2 text-sm',
'text-foreground hover:bg-accent',
'flex w-full items-center gap-2 rounded-md border border-[#1e2130] bg-[#14161d] px-3 py-2 text-sm',
'text-[#e2e5eb] hover:bg-accent',
filters.dateRange?.from && 'border-primary/30'
)}
>
<Calendar className="h-4 w-4 text-muted-foreground" />
<span className={cn(!filters.dateRange?.from && 'text-muted-foreground')}>
<Calendar className="h-4 w-4 text-[#848b9b]" />
<span className={cn(!filters.dateRange?.from && 'text-[#848b9b]')}>
{formatDateRange(filters.dateRange)}
</span>
</button>
{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 */}
<div className="mb-3 flex gap-2">
<button
@@ -168,8 +168,8 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
className={cn(
'flex-1 rounded-md px-3 py-1.5 text-sm font-medium transition-colors',
filters.dateType === 'started'
? 'bg-gradient-brand text-white shadow-lg shadow-primary/20'
: 'border border-border text-muted-foreground hover:bg-accent hover:text-foreground'
? 'bg-[#22d3ee] text-white'
: 'border border-[#1e2130] text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]'
)}
>
Started
@@ -179,8 +179,8 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
className={cn(
'flex-1 rounded-md px-3 py-1.5 text-sm font-medium transition-colors',
filters.dateType === 'completed'
? 'bg-gradient-brand text-white shadow-lg shadow-primary/20'
: 'border border-border text-muted-foreground hover:bg-accent hover:text-foreground'
? 'bg-[#22d3ee] text-white'
: 'border border-[#1e2130] text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]'
)}
>
Completed
@@ -194,8 +194,8 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
key={preset.value}
onClick={() => applyDatePreset(preset.value)}
className={cn(
'rounded-md bg-accent px-3 py-1.5 text-sm font-medium text-muted-foreground',
'hover:bg-accent/80 hover:text-foreground'
'rounded-md bg-accent px-3 py-1.5 text-sm font-medium text-[#848b9b]',
'hover:bg-accent/80 hover:text-[#e2e5eb]'
)}
>
{preset.label}
@@ -228,7 +228,7 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
}}
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',
'hover:opacity-90'
'hover:brightness-110'
)}
>
Apply
@@ -236,8 +236,8 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
<button
onClick={() => setShowDatePicker(false)}
className={cn(
'rounded-md border border-border px-3 py-1.5 text-sm font-medium text-muted-foreground',
'hover:bg-accent hover:text-foreground'
'rounded-md border border-[#1e2130] px-3 py-1.5 text-sm font-medium text-[#848b9b]',
'hover:bg-accent hover:text-[#e2e5eb]'
)}
>
Cancel
@@ -252,8 +252,8 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
<button
onClick={onClear}
className={cn(
'flex items-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium',
'text-muted-foreground hover:bg-accent hover:text-foreground'
'flex items-center gap-2 rounded-md border border-[#1e2130] px-3 py-2 text-sm font-medium',
'text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]'
)}
>
<Filter className="h-4 w-4" />
@@ -265,9 +265,9 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
{/* Active Filter Chips */}
{hasActiveFilters && (
<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 && (
<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}
<button
onClick={() => handleFilterChange('ticketNumber', '')}
@@ -278,7 +278,7 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
</span>
)}
{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}
<button
onClick={() => handleFilterChange('clientName', '')}
@@ -289,7 +289,7 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
</span>
)}
{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}
<button
onClick={() => handleFilterChange('treeName', '')}
@@ -300,7 +300,7 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
</span>
)}
{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})
<button
onClick={clearDateRange}

View File

@@ -66,7 +66,7 @@ export function SessionOutcomeModal({
)}
>
<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.
</p>
<div className="space-y-2">
@@ -74,7 +74,7 @@ export function SessionOutcomeModal({
<label
key={option.value}
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'
)}
>
@@ -87,8 +87,8 @@ export function SessionOutcomeModal({
className="mt-1 h-4 w-4"
/>
<div>
<p className="text-sm font-medium text-foreground">{option.label}</p>
<p className="text-xs text-muted-foreground">{option.description}</p>
<p className="text-sm font-medium text-[#e2e5eb]">{option.label}</p>
<p className="text-xs text-[#848b9b]">{option.description}</p>
</div>
</div>
</label>
@@ -96,30 +96,30 @@ export function SessionOutcomeModal({
</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
name="outcome-notes"
defaultValue=""
rows={3}
placeholder="Add context for this outcome..."
className={cn(
'mt-1 block w-full rounded-md border border-border bg-card px-3 py-2',
'text-sm text-foreground placeholder:text-muted-foreground',
'mt-1 block w-full rounded-md 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'
)}
/>
</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
name="next-steps"
defaultValue=""
rows={3}
placeholder="Actions to take after this session..."
className={cn(
'mt-1 block w-full rounded-md border border-border bg-card px-3 py-2',
'text-sm text-foreground placeholder:text-muted-foreground',
'mt-1 block w-full rounded-md 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'
)}
/>

View File

@@ -53,7 +53,7 @@ export function SessionTimeline({
if (treeType === 'procedural') {
return (
<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">
{decisions.map((decision, index) => {
const isCompleted = decision.answer === 'completed'
@@ -61,31 +61,31 @@ export function SessionTimeline({
<div
key={index}
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'
)}
>
<div className="flex items-start gap-3">
<span className={cn(
'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}
</span>
<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 && (
<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}
</p>
)}
{decision.command_output && (
<p className="mt-1 text-sm text-muted-foreground">
<p className="mt-1 text-sm text-[#848b9b]">
Verification: {decision.command_output}
</p>
)}
{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)}
</p>
)}
@@ -94,7 +94,7 @@ export function SessionTimeline({
<button
onClick={() => handleCopyStep(decision, index)}
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 ? (
<Check className="h-4 w-4 text-emerald-400" />
@@ -123,52 +123,52 @@ export function SessionTimeline({
// Default: troubleshooting decision timeline
return (
<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="flex items-center gap-3 text-sm">
<span className="h-3 w-3 rounded-full bg-foreground" />
<span className="text-muted-foreground">
<span className="h-3 w-3 rounded-full bg-[#e2e5eb]" />
<span className="text-[#848b9b]">
Session started: {formatDate(startedAt)}
</span>
</div>
{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">
<span className="absolute -left-6.5 top-1 h-2 w-2 rounded-full bg-muted-foreground" />
<div className="bg-card border border-border rounded-xl p-4">
<span className="absolute -left-6.5 top-1 h-2 w-2 rounded-full bg-[#848b9b]" />
<div className="bg-[#14161d] border border-[#1e2130] rounded-xl p-4">
<div className="flex items-start justify-between gap-2">
<div className="flex-1">
{decision.question && (
<p className="font-medium text-foreground">{decision.question}</p>
<p className="font-medium text-[#e2e5eb]">{decision.question}</p>
)}
{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 && (
<p className="mt-1 text-sm text-muted-foreground">
<p className="mt-1 text-sm text-[#848b9b]">
Action: {decision.action_performed}
</p>
)}
{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}
</p>
)}
{decision.command_output && (
<div className="mt-2">
<p className="mb-1 text-xs font-medium text-muted-foreground">Command Output</p>
<pre className="overflow-x-auto rounded bg-white/5 p-2 text-xs font-mono text-muted-foreground whitespace-pre-wrap">
<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-[#848b9b] whitespace-pre-wrap">
{decision.command_output}
</pre>
</div>
)}
{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)}
</p>
)}
<p className="mt-2 text-xs text-muted-foreground">
<p className="mt-2 text-xs text-[#848b9b]">
{formatDate(decision.timestamp)}
</p>
</div>
@@ -176,7 +176,7 @@ export function SessionTimeline({
<button
onClick={() => handleCopyStep(decision, index)}
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 ? (
<Check className="h-4 w-4 text-emerald-400" />

View File

@@ -191,14 +191,14 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
}
>
{/* 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">
{/* Create Share Form */}
<div className="space-y-4">
{/* Visibility */}
<div>
<label className="mb-2 block text-sm font-medium text-foreground">
<label className="mb-2 block text-sm font-medium text-[#e2e5eb]">
Visibility
</label>
<div className="space-y-2">
@@ -207,14 +207,14 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
className={cn(
'flex w-full items-center gap-3 rounded-md border px-4 py-3 text-left transition-colors',
visibility === 'account'
? 'border-primary/30 bg-primary/10 text-foreground'
: 'border-border bg-transparent text-muted-foreground hover:border-border hover:bg-accent'
? 'border-primary/30 bg-[rgba(34,211,238,0.10)] text-[#e2e5eb]'
: 'border-[#1e2130] bg-transparent text-[#848b9b] hover:border-[#1e2130] hover:bg-accent'
)}
>
<Users className="h-4 w-4" />
<div className="flex-1">
<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>
{visibility === 'account' && (
<div className="h-2 w-2 rounded-full bg-primary" />
@@ -225,14 +225,14 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
className={cn(
'flex w-full items-center gap-3 rounded-md border px-4 py-3 text-left transition-colors',
visibility === 'public'
? 'border-primary/30 bg-primary/10 text-foreground'
: 'border-border bg-transparent text-muted-foreground hover:border-border hover:bg-accent'
? 'border-primary/30 bg-[rgba(34,211,238,0.10)] text-[#e2e5eb]'
: 'border-[#1e2130] bg-transparent text-[#848b9b] hover:border-[#1e2130] hover:bg-accent'
)}
>
<Globe className="h-4 w-4" />
<div className="flex-1">
<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>
{visibility === 'public' && (
<div className="h-2 w-2 rounded-full bg-primary" />
@@ -246,8 +246,8 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
{/* Share Name */}
<div>
<label className="mb-2 block text-sm font-medium text-foreground">
Share Name <span className="text-muted-foreground">(optional)</span>
<label className="mb-2 block text-sm font-medium text-[#e2e5eb]">
Share Name <span className="text-[#848b9b]">(optional)</span>
</label>
<Input
type="text"
@@ -260,7 +260,7 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
{/* Expiration */}
<div>
<label className="mb-2 block text-sm font-medium text-foreground">
<label className="mb-2 block text-sm font-medium text-[#e2e5eb]">
Expiration
</label>
<div className="flex flex-wrap gap-2">
@@ -271,8 +271,8 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
className={cn(
'rounded-md border px-3 py-1.5 text-sm transition-colors',
expirationPreset === preset.value
? 'border-primary/30 bg-primary/10 text-foreground'
: 'border-border text-muted-foreground hover:border-border hover:bg-accent'
? 'border-primary/30 bg-[rgba(34,211,238,0.10)] text-[#e2e5eb]'
: 'border-[#1e2130] text-[#848b9b] hover:border-[#1e2130] hover:bg-accent'
)}
>
{preset.label}
@@ -285,7 +285,7 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
value={customDatetime}
onChange={(e) => setCustomDatetime(e.target.value)}
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',
'scheme-dark'
)}
@@ -308,7 +308,7 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
{/* Existing Shares */}
{shares.length > 0 && (
<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})
</h3>
<div className="space-y-3">
@@ -318,7 +318,7 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
return (
<div
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-1 min-w-0">
@@ -326,8 +326,8 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
<span className={cn(
'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs',
share.visibility === 'public'
? 'bg-accent text-muted-foreground'
: 'bg-accent text-muted-foreground'
? 'bg-accent text-[#848b9b]'
: 'bg-accent text-[#848b9b]'
)}>
{share.visibility === 'public' ? (
<Globe className="h-3 w-3" />
@@ -336,11 +336,11 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
)}
{share.visibility === 'public' ? 'Public' : 'Account'}
</span>
<span className="truncate text-sm font-medium text-foreground">
<span className="truncate text-sm font-medium text-[#e2e5eb]">
{share.share_name || 'Untitled share'}
</span>
</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>
{share.view_count > 0
@@ -361,10 +361,10 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
onClick={() => handleCopyUrl(share)}
title="Copy share URL"
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
? '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 ? (
@@ -376,7 +376,7 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
<button
onClick={() => handleRevoke(share.id)}
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" />
</button>

View File

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

View File

@@ -80,19 +80,19 @@ export function StepRatingModal({
return (
<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 */}
<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>
<h2 className="text-lg font-semibold text-foreground">Rate Your Experience</h2>
<p className="mt-1 text-sm text-muted-foreground">
<h2 className="text-lg font-semibold text-[#e2e5eb]">Rate Your Experience</h2>
<p className="mt-1 text-sm text-[#848b9b]">
Help others by rating the steps you used ({librarySteps.length} step{librarySteps.length !== 1 ? 's' : ''})
</p>
</div>
<button
onClick={onClose}
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" />
</button>
@@ -104,14 +104,14 @@ export function StepRatingModal({
{librarySteps.map((step) => {
const rating = getRating(step.id)
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 */}
<h3 className="font-medium text-foreground">{step.title}</h3>
<p className="mt-1 text-sm text-muted-foreground capitalize">{step.step_type}</p>
<h3 className="font-medium text-[#e2e5eb]">{step.title}</h3>
<p className="mt-1 text-sm text-[#848b9b] capitalize">{step.step_type}</p>
{/* Star Rating */}
<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
</label>
<StarRating
@@ -123,7 +123,7 @@ export function StepRatingModal({
{/* Was this helpful? */}
<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?
</label>
<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',
rating?.helpful === true
? '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'
)}
>
@@ -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',
rating?.helpful === false
? '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'
)}
>
@@ -162,8 +162,8 @@ export function StepRatingModal({
{/* Optional Review */}
<div className="mt-3">
<label htmlFor={`review-${step.id}`} className="mb-1 block text-sm font-medium text-foreground">
Review <span className="text-muted-foreground">(optional)</span>
<label htmlFor={`review-${step.id}`} className="mb-1 block text-sm font-medium text-[#e2e5eb]">
Review <span className="text-[#848b9b]">(optional)</span>
</label>
<Textarea
id={`review-${step.id}`}
@@ -174,7 +174,7 @@ export function StepRatingModal({
rows={2}
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
</p>
</div>
@@ -185,7 +185,7 @@ export function StepRatingModal({
</div>
{/* 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
type="button"
variant="secondary"

View File

@@ -49,22 +49,22 @@ export function SupportingDataPanel({ sessionId }: SupportingDataPanelProps) {
}
return (
<div className="rounded-xl border border-border bg-card/50">
<div className="rounded-xl border border-[#1e2130] bg-card/50">
{/* Header */}
<div className="flex items-center justify-between px-4 py-3">
<button
type="button"
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 ? (
<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
{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}
</span>
)}
@@ -73,8 +73,8 @@ export function SupportingDataPanel({ sessionId }: SupportingDataPanelProps) {
type="button"
onClick={() => setShowAddModal(true)}
className={cn(
'flex items-center gap-1.5 rounded-[10px] px-3 py-1.5 text-xs font-medium',
'bg-gradient-brand text-[#101114] hover:opacity-90 active:scale-[0.97] transition-all'
'flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-medium',
'bg-[#22d3ee] text-white hover:brightness-110 active:scale-[0.98] transition-all'
)}
>
<Plus className="h-3.5 w-3.5" />
@@ -84,11 +84,11 @@ export function SupportingDataPanel({ sessionId }: SupportingDataPanelProps) {
{/* Items list */}
{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 ? (
<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 ? (
<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.
</p>
) : (
@@ -97,11 +97,11 @@ export function SupportingDataPanel({ sessionId }: SupportingDataPanelProps) {
<div
key={item.id}
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)]'
)}
>
<span className="mt-0.5 shrink-0 text-muted-foreground">
<span className="mt-0.5 shrink-0 text-[#848b9b]">
{item.data_type === 'text_snippet' ? (
<Code2 className="h-4 w-4" />
) : (
@@ -109,9 +109,9 @@ export function SupportingDataPanel({ sessionId }: SupportingDataPanelProps) {
)}
</span>
<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 && (
<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}
</p>
)}
@@ -119,14 +119,14 @@ export function SupportingDataPanel({ sessionId }: SupportingDataPanelProps) {
<img
src={`data:${item.content_type || 'image/png'};base64,${item.content}`}
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>
<button
type="button"
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"
>
<Trash2 className="h-4 w-4" />

View File

@@ -38,14 +38,14 @@ function AccordionSection({ label, icon, count, children }: AccordionSectionProp
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"
>
<span className="text-muted-foreground">{icon}</span>
<span className="flex-1 text-xs font-medium text-foreground">{label}</span>
<span className="text-[#848b9b]">{icon}</span>
<span className="flex-1 text-xs font-medium text-[#e2e5eb]">{label}</span>
{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}
</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" />}
</span>
</button>
@@ -60,18 +60,18 @@ function AccordionSection({ label, icon, count, children }: AccordionSectionProp
export function TicketContextPanel({ context, loading, error, onRefresh }: TicketContextPanelProps) {
return (
<div className="glass-card-static overflow-hidden rounded-2xl">
<div className="card-flat overflow-hidden rounded-lg">
{/* Header */}
<div className="flex items-center gap-2 bg-primary/5 px-3 py-2.5">
<Ticket className="h-3.5 w-3.5 text-primary" />
<span className="flex-1 font-label text-[0.625rem] uppercase tracking-[0.1em] text-primary">
<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-[#22d3ee]" />
<span className="flex-1 font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#22d3ee]">
Ticket Context
</span>
<button
onClick={onRefresh}
disabled={loading}
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')} />
</button>
@@ -80,7 +80,7 @@ export function TicketContextPanel({ context, loading, error, onRefresh }: Ticke
{/* Loading */}
{loading && !context && (
<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>
)}
@@ -98,43 +98,43 @@ export function TicketContextPanel({ context, loading, error, onRefresh }: Ticke
{/* Compact summary */}
<div className="px-3 py-2.5">
<div className="flex items-baseline gap-2">
<span className="font-label text-xs font-medium text-primary">#{context.ticket.id}</span>
<span className="flex-1 truncate text-xs text-foreground">{context.ticket.summary}</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-[#e2e5eb]">{context.ticket.summary}</span>
</div>
<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}
</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}
</span>
{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}
</span>
)}
</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>
{/* Client */}
<AccordionSection label="Client" icon={<Building2 className="h-3.5 w-3.5" />}>
<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 && (
<p className="text-muted-foreground">Type: {context.company.type}</p>
<p className="text-[#848b9b]">Type: {context.company.type}</p>
)}
{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 && (
<p className="text-muted-foreground">Site: {context.company.site}</p>
<p className="text-[#848b9b]">Site: {context.company.site}</p>
)}
{context.company.address && (
<p className="text-muted-foreground">{context.company.address}</p>
<p className="text-[#848b9b]">{context.company.address}</p>
)}
{context.company.phone && (
<p className="text-muted-foreground">{context.company.phone}</p>
<p className="text-[#848b9b]">{context.company.phone}</p>
)}
</div>
</AccordionSection>
@@ -143,15 +143,15 @@ export function TicketContextPanel({ context, loading, error, onRefresh }: Ticke
{context.contact && (
<AccordionSection label="Contact" icon={<UserCircle className="h-3.5 w-3.5" />}>
<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 && (
<p className="text-muted-foreground">{context.contact.title}</p>
<p className="text-[#848b9b]">{context.contact.title}</p>
)}
{context.contact.email && (
<p className="text-muted-foreground">{context.contact.email}</p>
<p className="text-[#848b9b]">{context.contact.email}</p>
)}
{context.contact.phone && (
<p className="text-muted-foreground">{context.contact.phone}</p>
<p className="text-[#848b9b]">{context.contact.phone}</p>
)}
</div>
</AccordionSection>
@@ -166,9 +166,9 @@ export function TicketContextPanel({ context, loading, error, onRefresh }: Ticke
>
<div className="space-y-2">
{context.configurations.map((cfg, i) => (
<div key={i} className="rounded-md border border-[rgba(255,255,255,0.06)] bg-card p-2">
<p className="text-xs font-medium text-foreground">{cfg.device_identifier}</p>
<div className="mt-0.5 space-y-0.5 text-[0.6875rem] text-muted-foreground">
<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-[#e2e5eb]">{cfg.device_identifier}</p>
<div className="mt-0.5 space-y-0.5 text-[0.6875rem] text-[#848b9b]">
{cfg.type && <p>Type: {cfg.type}</p>}
{cfg.os_type && <p>OS: {cfg.os_type}</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">
{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">
{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()}
</span>
</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}
</p>
</div>
@@ -219,16 +219,16 @@ export function TicketContextPanel({ context, loading, error, onRefresh }: Ticke
{context.related_tickets.map((rt) => (
<div
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">
<span className="font-label text-[0.6rem] text-primary">#{rt.id}</span>
<span className="flex-1 truncate text-[0.6875rem] text-foreground">{rt.summary}</span>
<span className="font-sans text-xs text-[0.6rem] text-[#22d3ee]">#{rt.id}</span>
<span className="flex-1 truncate text-[0.6875rem] text-[#e2e5eb]">{rt.summary}</span>
</div>
<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-muted-foreground">·</span>
<span className="text-[0.6rem] text-muted-foreground">{rt.priority}</span>
<span className="text-[0.6rem] text-[#848b9b]">{rt.status}</span>
<span className="text-[0.6rem] text-[#848b9b]">·</span>
<span className="text-[0.6rem] text-[#848b9b]">{rt.priority}</span>
</div>
</div>
))}

View File

@@ -23,8 +23,8 @@ export function TicketLinkIndicator({ session, hasConnection, onLinkClick, onUnl
type="button"
onClick={onLinkClick}
className={cn(
'inline-flex items-center gap-1.5 rounded-lg px-2 py-1 text-xs text-muted-foreground transition-colors',
'hover:bg-accent hover:text-foreground'
'inline-flex items-center gap-1.5 rounded-lg px-2 py-1 text-xs text-[#848b9b] transition-colors',
'hover:bg-accent hover:text-[#e2e5eb]'
)}
>
<Link2 className="h-3.5 w-3.5" />
@@ -35,17 +35,17 @@ export function TicketLinkIndicator({ session, hasConnection, onLinkClick, onUnl
// Ticket linked
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" />
<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}
{ticketInfo?.summary && (
<span className="text-muted-foreground"> {ticketInfo.summary}</span>
<span className="text-[#848b9b]"> {ticketInfo.summary}</span>
)}
</p>
{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.board_name && (
<>
@@ -68,8 +68,8 @@ export function TicketLinkIndicator({ session, hasConnection, onLinkClick, onUnl
type="button"
onClick={onUpdateClick}
className={cn(
'inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-xs text-muted-foreground transition-colors',
'hover:bg-primary/10 hover:text-foreground'
'inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-xs text-[#848b9b] transition-colors',
'hover:bg-[rgba(34,211,238,0.10)] hover:text-[#e2e5eb]'
)}
title="Update ticket"
>
@@ -80,7 +80,7 @@ export function TicketLinkIndicator({ session, hasConnection, onLinkClick, onUnl
<button
type="button"
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"
>
<Unlink className="h-3.5 w-3.5" />

View File

@@ -219,8 +219,8 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
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',
mode === 'search'
? 'bg-white/[0.08] text-foreground shadow-sm'
: 'text-muted-foreground hover:text-foreground'
? 'bg-white/[0.08] text-[#e2e5eb] shadow-sm'
: 'text-[#848b9b] hover:text-[#e2e5eb]'
)}
>
<Search className="h-3.5 w-3.5" />
@@ -232,8 +232,8 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
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',
mode === 'manual'
? 'bg-white/[0.08] text-foreground shadow-sm'
: 'text-muted-foreground hover:text-foreground'
? 'bg-white/[0.08] text-[#e2e5eb] shadow-sm'
: 'text-[#848b9b] hover:text-[#e2e5eb]'
)}
>
<Hash className="h-3.5 w-3.5" />
@@ -257,12 +257,12 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
</div>
{/* 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
type="checkbox"
checked={includeClosed}
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
</label>
@@ -270,12 +270,12 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
{/* Search results */}
{isSearching && (
<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>
)}
{!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
</div>
)}
@@ -290,17 +290,17 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
disabled={isLooking}
className={cn(
'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',
result.closed && 'opacity-60'
)}
>
<p className="truncate text-sm font-medium text-foreground">
<span className="text-muted-foreground">#{result.id}</span>
<p className="truncate text-sm font-medium text-[#e2e5eb]">
<span className="text-[#848b9b]">#{result.id}</span>
{' — '}
{result.summary}
</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.board_name && (
<>
@@ -324,8 +324,8 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
{isLooking && (
<div className="flex items-center justify-center py-3">
<Loader2 className="h-5 w-5 animate-spin text-muted-foreground" />
<span className="ml-2 text-sm text-muted-foreground">Loading ticket details...</span>
<Loader2 className="h-5 w-5 animate-spin text-[#848b9b]" />
<span className="ml-2 text-sm text-[#848b9b]">Loading ticket details...</span>
</div>
)}
</div>
@@ -334,7 +334,7 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
{/* Manual mode */}
{mode === 'manual' && !selectedTicket && (
<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
</label>
<div className="flex gap-2">
@@ -376,14 +376,14 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
{/* Selected ticket confirmation card */}
{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">
<CheckCircle2 className="mt-0.5 h-4 w-4 shrink-0 text-emerald-400" />
<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}
</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 && (
<span>{selectedTicket.company_name}</span>
)}
@@ -437,8 +437,8 @@ export function TicketPickerModal({ open, onClose, sessionId, onLinked, onSelect
type="button"
onClick={handleClose}
className={cn(
'text-sm text-muted-foreground transition-colors',
'hover:text-foreground'
'text-sm text-[#848b9b] transition-colors',
'hover:text-[#e2e5eb]'
)}
>
Skip

View File

@@ -134,7 +134,7 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
<button
type="button"
onClick={onClose}
className="text-sm text-muted-foreground hover:text-foreground transition-colors"
className="text-sm text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
>
Cancel
</button>
@@ -143,9 +143,9 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
onClick={handlePost}
disabled={isPosting || !content.trim()}
className={cn(
'inline-flex items-center gap-2 rounded-[10px] px-5 py-2.5 text-sm font-semibold',
'bg-gradient-brand text-[#101114] shadow-lg shadow-primary/20',
'hover:opacity-90 active:scale-[0.97] transition-all',
'inline-flex items-center gap-2 rounded-lg px-5 py-2.5 text-sm font-semibold',
'bg-[#22d3ee] text-white',
'hover:brightness-110 active:scale-[0.98] transition-all',
'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}>
{isLoading && (
<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>
)}
@@ -172,7 +172,7 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
</div>
<button
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
</button>
@@ -184,13 +184,13 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
{/* Left panel - Content editor */}
<div className="space-y-3">
<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
</p>
<button
type="button"
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"
>
<Copy className="h-3 w-3" />
@@ -214,7 +214,7 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
) : (
<span />
)}
<span className="text-muted-foreground">
<span className="text-[#848b9b]">
{content.length.toLocaleString()} characters
</span>
</div>
@@ -223,15 +223,15 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
{/* Right panel - Controls */}
<div className="space-y-6">
{/* Ticket info summary */}
<div className="glass-card-static rounded-lg border border-border p-3">
<p className="text-sm font-medium text-foreground">
<div className="card-flat rounded-lg border border-[#1e2130] p-3">
<p className="text-sm font-medium text-[#e2e5eb]">
CW #{preview.ticket.id}
{preview.ticket.summary && (
<span className="text-muted-foreground"> {preview.ticket.summary}</span>
<span className="text-[#848b9b]"> {preview.ticket.summary}</span>
)}
</p>
{(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(' / ')}
</p>
)}
@@ -239,7 +239,7 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
{/* Note Type */}
<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
</p>
<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',
noteType === opt.value
? '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
@@ -262,8 +262,8 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
className="mt-0.5 accent-cyan-400"
/>
<div className="min-w-0">
<span className="text-sm font-medium text-foreground">{opt.label}</span>
<p className="text-xs text-muted-foreground">{opt.description}</p>
<span className="text-sm font-medium text-[#e2e5eb]">{opt.label}</span>
<p className="text-xs text-[#848b9b]">{opt.description}</p>
{opt.warning && noteType === opt.value && (
<p className="mt-1 flex items-center gap-1 text-xs text-amber-400">
<AlertTriangle className="h-3 w-3 shrink-0" />
@@ -278,14 +278,14 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
{/* Ticket Status */}
<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
</p>
<select
value={selectedStatusId ?? ''}
onChange={(e) => setSelectedStatusId(e.target.value ? Number(e.target.value) : null)}
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'
)}
>
@@ -301,7 +301,7 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
{/* Previous posts */}
{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.
</p>
)}

View File

@@ -23,14 +23,14 @@ export function VariablePromptModal({ prompt, onSubmit, onCancel }: VariableProm
return (
<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">
<h2 className="mb-1 text-lg font-semibold text-foreground">Input Required</h2>
<p className="mb-4 text-sm text-muted-foreground">
<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-[#e2e5eb]">Input Required</h2>
<p className="mb-4 text-sm text-[#848b9b]">
This step requires you to provide a value.
</p>
<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}
</label>
<input
@@ -40,8 +40,8 @@ export function VariablePromptModal({ prompt, onSubmit, onCancel }: VariableProm
placeholder="Enter value..."
autoFocus
className={cn(
'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'
'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'
)}
/>