refactor: migrate procedural and step library components to new design system

Migrate 10 components from monochrome glass-card design to purple gradient
accent design system tokens.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-02-15 21:08:40 -05:00
parent e3edbc64f2
commit 4ad202c92d
10 changed files with 224 additions and 224 deletions

View File

@@ -26,49 +26,49 @@ export function IntakeFieldEditor({ field, onUpdate, onRemove }: IntakeFieldEdit
const needsOptions = field.field_type === 'select' || field.field_type === 'multi_select'
return (
<div className="glass-card rounded-xl p-3">
<div className="bg-card border border-border rounded-xl p-3">
{/* Header row */}
<div className="flex items-center gap-2">
<GripVertical className="h-4 w-4 shrink-0 cursor-grab text-white/30" />
<GripVertical className="h-4 w-4 shrink-0 cursor-grab text-muted-foreground" />
<input
type="text"
value={field.label}
onChange={(e) => onUpdate({ label: e.target.value })}
placeholder="Field label"
className="min-w-0 flex-1 rounded border border-white/10 bg-black/50 px-2 py-1.5 text-sm text-white placeholder:text-white/30 focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
className="min-w-0 flex-1 rounded border border-border bg-card px-2 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
/>
<select
value={field.field_type}
onChange={(e) => onUpdate({ field_type: e.target.value as IntakeFieldType })}
className="rounded border border-white/10 bg-black/50 px-2 py-1.5 text-sm text-white focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
className="rounded border border-border bg-card px-2 py-1.5 text-sm text-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
>
{FIELD_TYPE_OPTIONS.map((opt) => (
<option key={opt.value} value={opt.value}>{opt.label}</option>
))}
</select>
<label className="flex items-center gap-1 text-xs text-white/50">
<label className="flex items-center gap-1 text-xs text-muted-foreground">
<input
type="checkbox"
checked={field.required}
onChange={(e) => onUpdate({ required: e.target.checked })}
className="rounded border-white/20"
className="rounded border-border"
/>
Req
</label>
<button
onClick={() => setExpanded(!expanded)}
className="rounded p-1 text-white/40 hover:bg-white/10 hover:text-white"
className="rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
>
{expanded ? <ChevronUp className="h-3.5 w-3.5" /> : <ChevronDown className="h-3.5 w-3.5" />}
</button>
<button
onClick={onRemove}
className="rounded p-1 text-white/40 hover:bg-red-500/20 hover:text-red-400"
className="rounded p-1 text-muted-foreground hover:bg-red-500/20 hover:text-red-400"
>
<Trash2 className="h-3.5 w-3.5" />
</button>
@@ -76,66 +76,66 @@ export function IntakeFieldEditor({ field, onUpdate, onRemove }: IntakeFieldEdit
{/* Expanded details */}
{expanded && (
<div className="mt-3 grid grid-cols-2 gap-3 border-t border-white/[0.06] pt-3">
<div className="mt-3 grid grid-cols-2 gap-3 border-t border-border pt-3">
<div>
<label className="mb-1 block text-xs text-white/50">Variable Name</label>
<label className="mb-1 block text-xs text-muted-foreground">Variable Name</label>
<input
type="text"
value={field.variable_name}
onChange={(e) => onUpdate({ variable_name: e.target.value.toLowerCase().replace(/[^a-z0-9_]/g, '') })}
placeholder="e.g. server_name"
className="w-full rounded border border-white/10 bg-black/50 px-2 py-1.5 text-sm font-mono text-white placeholder:text-white/30 focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
className="w-full rounded border border-border bg-card px-2 py-1.5 text-sm font-mono text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
/>
<p className="mt-0.5 text-[10px] text-white/30">Used as [VAR:{field.variable_name}]</p>
<p className="mt-0.5 text-[10px] text-muted-foreground">Used as [VAR:{field.variable_name}]</p>
</div>
<div>
<label className="mb-1 block text-xs text-white/50">Placeholder</label>
<label className="mb-1 block text-xs text-muted-foreground">Placeholder</label>
<input
type="text"
value={field.placeholder || ''}
onChange={(e) => onUpdate({ placeholder: e.target.value || undefined })}
placeholder="Hint text"
className="w-full rounded border border-white/10 bg-black/50 px-2 py-1.5 text-sm text-white placeholder:text-white/30 focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
className="w-full rounded border border-border bg-card px-2 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
/>
</div>
<div className="col-span-2">
<label className="mb-1 block text-xs text-white/50">Help Text</label>
<label className="mb-1 block text-xs text-muted-foreground">Help Text</label>
<input
type="text"
value={field.help_text || ''}
onChange={(e) => onUpdate({ help_text: e.target.value || undefined })}
placeholder="Description or instructions"
className="w-full rounded border border-white/10 bg-black/50 px-2 py-1.5 text-sm text-white placeholder:text-white/30 focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
className="w-full rounded border border-border bg-card px-2 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
/>
</div>
<div>
<label className="mb-1 block text-xs text-white/50">Default Value</label>
<label className="mb-1 block text-xs text-muted-foreground">Default Value</label>
<input
type="text"
value={field.default_value || ''}
onChange={(e) => onUpdate({ default_value: e.target.value || undefined })}
placeholder="Pre-filled value"
className="w-full rounded border border-white/10 bg-black/50 px-2 py-1.5 text-sm text-white placeholder:text-white/30 focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
className="w-full rounded border border-border bg-card px-2 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
/>
</div>
<div>
<label className="mb-1 block text-xs text-white/50">Group Name</label>
<label className="mb-1 block text-xs text-muted-foreground">Group Name</label>
<input
type="text"
value={field.group_name || ''}
onChange={(e) => onUpdate({ group_name: e.target.value || undefined })}
placeholder="e.g. Network Settings"
className="w-full rounded border border-white/10 bg-black/50 px-2 py-1.5 text-sm text-white placeholder:text-white/30 focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
className="w-full rounded border border-border bg-card px-2 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
/>
</div>
{needsOptions && (
<div className="col-span-2">
<label className="mb-1 block text-xs text-white/50">Options (one per line)</label>
<label className="mb-1 block text-xs text-muted-foreground">Options (one per line)</label>
<textarea
value={(field.options || []).join('\n')}
onChange={(e) => {
@@ -144,7 +144,7 @@ export function IntakeFieldEditor({ field, onUpdate, onRemove }: IntakeFieldEdit
}}
placeholder="Option 1&#10;Option 2&#10;Option 3"
rows={3}
className="w-full rounded border border-white/10 bg-black/50 px-2 py-1.5 text-sm text-white placeholder:text-white/30 focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
className="w-full rounded border border-border bg-card px-2 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
/>
</div>
)}

View File

@@ -6,18 +6,18 @@ export function IntakeFormBuilder() {
const { intakeForm, addField, removeField, updateField } = useProceduralEditorStore()
return (
<div className="glass-card rounded-2xl p-4 sm:p-6">
<div className="bg-card border border-border rounded-2xl p-4 sm:p-6">
<div className="mb-4 flex items-center justify-between">
<div className="flex items-center gap-2">
<FileText className="h-5 w-5 text-white/50" />
<h2 className="text-lg font-semibold text-white">Intake Form</h2>
<span className="text-sm text-white/40">
<FileText className="h-5 w-5 text-muted-foreground" />
<h2 className="text-lg font-semibold text-foreground">Intake Form</h2>
<span className="text-sm text-muted-foreground">
({intakeForm.length} field{intakeForm.length !== 1 ? 's' : ''})
</span>
</div>
<button
onClick={addField}
className="flex items-center gap-1.5 rounded-md border border-white/10 px-3 py-1.5 text-sm text-white/60 hover:bg-white/10 hover:text-white"
className="flex items-center gap-1.5 rounded-md border border-border px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
>
<Plus className="h-3.5 w-3.5" />
Add Field
@@ -25,10 +25,10 @@ export function IntakeFormBuilder() {
</div>
{intakeForm.length === 0 ? (
<div className="rounded-lg border border-dashed border-white/10 bg-white/[0.02] py-8 text-center">
<FileText className="mx-auto mb-2 h-8 w-8 text-white/20" />
<p className="text-sm text-white/40">No intake form fields yet</p>
<p className="mt-1 text-xs text-white/30">
<div className="rounded-lg border border-dashed border-border bg-white/[0.02] py-8 text-center">
<FileText className="mx-auto mb-2 h-8 w-8 text-muted-foreground" />
<p className="text-sm text-muted-foreground">No intake form fields yet</p>
<p className="mt-1 text-xs text-muted-foreground">
Add fields to collect project data before the procedure starts
</p>
</div>

View File

@@ -5,7 +5,7 @@ import { cn } from '@/lib/utils'
const CONTENT_TYPE_OPTIONS: { value: StepContentType; label: string; color: string }[] = [
{ value: 'action', label: 'Action', color: 'text-blue-400' },
{ value: 'informational', label: 'Info', color: 'text-white/60' },
{ value: 'informational', label: 'Info', color: 'text-muted-foreground' },
{ value: 'verification', label: 'Verify', color: 'text-emerald-400' },
{ value: 'warning', label: 'Warning', color: 'text-yellow-400' },
]
@@ -24,24 +24,24 @@ export function StepEditor({ step, stepNumber, onUpdate, onCollapse, availableVa
// Section header steps get a minimal editor
if (step.type === 'section_header') {
return (
<div className="glass-card rounded-xl border border-white/10 p-4">
<div className="bg-card border border-border rounded-xl p-4">
<div className="mb-4 flex items-center justify-between">
<span className="text-sm font-medium text-white/50">Edit Section Header</span>
<span className="text-sm font-medium text-muted-foreground">Edit Section Header</span>
<button
onClick={onCollapse}
className="rounded p-1 text-white/40 hover:bg-white/10 hover:text-white"
className="rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
>
<ChevronUp className="h-4 w-4" />
</button>
</div>
<div>
<label className="mb-1 block text-xs font-medium text-white/50">Title</label>
<label className="mb-1 block text-xs font-medium text-muted-foreground">Title</label>
<input
type="text"
value={step.title}
onChange={(e) => onUpdate({ title: e.target.value })}
placeholder="Section title"
className="w-full rounded border border-white/10 bg-black/50 px-3 py-2 text-sm text-white placeholder:text-white/30 focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
className="w-full rounded border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
/>
</div>
</div>
@@ -49,18 +49,18 @@ export function StepEditor({ step, stepNumber, onUpdate, onCollapse, availableVa
}
return (
<div className="glass-card rounded-xl border border-white/10 p-4">
<div className="bg-card border border-border rounded-xl p-4">
{/* Header */}
<div className="mb-4 flex items-center justify-between">
<div className="flex items-center gap-2">
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-white/10 text-xs font-medium text-white">
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-accent text-xs font-medium text-foreground">
{stepNumber}
</span>
<span className="text-sm font-medium text-white">Edit Step</span>
<span className="text-sm font-medium text-foreground">Edit Step</span>
</div>
<button
onClick={onCollapse}
className="rounded p-1 text-white/40 hover:bg-white/10 hover:text-white"
className="rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
>
<ChevronUp className="h-4 w-4" />
</button>
@@ -69,18 +69,18 @@ export function StepEditor({ step, stepNumber, onUpdate, onCollapse, availableVa
<div className="space-y-4">
{/* Title */}
<div>
<label className="mb-1 block text-xs font-medium text-white/50">Title</label>
<label className="mb-1 block text-xs font-medium text-muted-foreground">Title</label>
<input
type="text"
value={step.title}
onChange={(e) => onUpdate({ title: e.target.value })}
className="w-full rounded border border-white/10 bg-black/50 px-3 py-2 text-sm text-white placeholder:text-white/30 focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
className="w-full rounded border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
/>
</div>
{/* Est. Minutes */}
<div className="w-40">
<label className="mb-1 flex items-center gap-1 text-xs font-medium text-white/50">
<label className="mb-1 flex items-center gap-1 text-xs font-medium text-muted-foreground">
<Clock className="h-3 w-3" />
Est. Minutes
</label>
@@ -90,28 +90,28 @@ export function StepEditor({ step, stepNumber, onUpdate, onCollapse, availableVa
onChange={(e) => onUpdate({ estimated_minutes: e.target.value ? parseInt(e.target.value) : undefined })}
placeholder="—"
min={1}
className="w-full rounded border border-white/10 bg-black/50 px-3 py-2 text-sm text-white placeholder:text-white/30 focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
className="w-full rounded border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
/>
</div>
{/* Description */}
<div>
<label className="mb-1 block text-xs font-medium text-white/50">Description / Instructions</label>
<label className="mb-1 block text-xs font-medium text-muted-foreground">Description / Instructions</label>
<textarea
value={step.description || ''}
onChange={(e) => onUpdate({ description: e.target.value })}
placeholder="Step instructions. Use [VAR:name] for variables."
rows={4}
className="w-full rounded border border-white/10 bg-black/50 px-3 py-2 text-sm text-white placeholder:text-white/30 focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
className="w-full rounded border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
/>
{availableVariables.length > 0 && (
<div className="mt-1 flex flex-wrap gap-1">
<span className="text-[10px] text-white/30">Variables:</span>
<span className="text-[10px] text-muted-foreground">Variables:</span>
{availableVariables.map((v) => (
<button
key={v.variable_name}
onClick={() => onUpdate({ description: (step.description || '') + `[VAR:${v.variable_name}]` })}
className="rounded bg-white/5 px-1.5 py-0.5 font-mono text-[10px] text-white/50 hover:bg-white/10 hover:text-white/70"
className="rounded bg-accent/50 px-1.5 py-0.5 font-mono text-[10px] text-muted-foreground hover:bg-accent hover:text-muted-foreground"
>
{v.variable_name}
</button>
@@ -122,7 +122,7 @@ export function StepEditor({ step, stepNumber, onUpdate, onCollapse, availableVa
{/* Commands */}
<div>
<label className="mb-1 flex items-center gap-1 text-xs font-medium text-white/50">
<label className="mb-1 flex items-center gap-1 text-xs font-medium text-muted-foreground">
<Terminal className="h-3 w-3" />
Commands (optional)
</label>
@@ -131,7 +131,7 @@ export function StepEditor({ step, stepNumber, onUpdate, onCollapse, availableVa
onChange={(e) => onUpdate({ commands: e.target.value || undefined })}
placeholder="Install-WindowsFeature AD-Domain-Services -IncludeManagementTools"
rows={3}
className="w-full rounded border border-white/10 bg-black/50 px-3 py-2 font-mono text-sm text-white placeholder:text-white/30 focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
className="w-full rounded border border-border bg-card px-3 py-2 font-mono text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
/>
</div>
@@ -139,7 +139,7 @@ export function StepEditor({ step, stepNumber, onUpdate, onCollapse, availableVa
<button
type="button"
onClick={() => setShowMore(!showMore)}
className="flex items-center gap-1.5 text-xs text-white/40 hover:text-white/60"
className="flex items-center gap-1.5 text-xs text-muted-foreground hover:text-muted-foreground"
>
<Settings2 className="h-3 w-3" />
More Options
@@ -147,10 +147,10 @@ export function StepEditor({ step, stepNumber, onUpdate, onCollapse, availableVa
</button>
{showMore && (
<div className="space-y-4 border-t border-white/[0.06] pt-4">
<div className="space-y-4 border-t border-border pt-4">
{/* Content Type */}
<div>
<label className="mb-1 block text-xs font-medium text-white/50">Content Type</label>
<label className="mb-1 block text-xs font-medium text-muted-foreground">Content Type</label>
<div className="flex gap-1">
{CONTENT_TYPE_OPTIONS.map((opt) => (
<button
@@ -160,7 +160,7 @@ export function StepEditor({ step, stepNumber, onUpdate, onCollapse, availableVa
'rounded px-2 py-1 text-xs font-medium transition-colors',
step.content_type === opt.value
? 'bg-white/15 ' + opt.color
: 'text-white/40 hover:bg-white/10 hover:text-white/60'
: 'text-muted-foreground hover:bg-accent hover:text-muted-foreground'
)}
>
{opt.label}
@@ -181,27 +181,27 @@ export function StepEditor({ step, stepNumber, onUpdate, onCollapse, availableVa
onChange={(e) => onUpdate({ warning_text: e.target.value || undefined })}
placeholder="Caution: This will restart the service..."
rows={2}
className="w-full rounded border border-yellow-400/20 bg-yellow-400/5 px-3 py-2 text-sm text-white placeholder:text-white/30 focus:border-yellow-400/30 focus:outline-none focus:ring-1 focus:ring-yellow-400/20"
className="w-full rounded border border-yellow-400/20 bg-yellow-400/5 px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-yellow-400/30 focus:outline-none focus:ring-1 focus:ring-yellow-400/20"
/>
</div>
)}
{/* Expected Outcome */}
<div>
<label className="mb-1 block text-xs font-medium text-white/50">Expected Outcome (optional)</label>
<label className="mb-1 block text-xs font-medium text-muted-foreground">Expected Outcome (optional)</label>
<input
type="text"
value={step.expected_outcome || ''}
onChange={(e) => onUpdate({ expected_outcome: e.target.value || undefined })}
placeholder="Server should respond with..."
className="w-full rounded border border-white/10 bg-black/50 px-3 py-2 text-sm text-white placeholder:text-white/30 focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
className="w-full rounded border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
/>
</div>
{/* Verification */}
<div className="grid grid-cols-2 gap-3">
<div>
<label className="mb-1 flex items-center gap-1 text-xs font-medium text-white/50">
<label className="mb-1 flex items-center gap-1 text-xs font-medium text-muted-foreground">
<CheckSquare className="h-3 w-3" />
Verification Prompt (optional)
</label>
@@ -210,15 +210,15 @@ export function StepEditor({ step, stepNumber, onUpdate, onCollapse, availableVa
value={step.verification_prompt || ''}
onChange={(e) => onUpdate({ verification_prompt: e.target.value || undefined })}
placeholder="Confirm the role was installed"
className="w-full rounded border border-white/10 bg-black/50 px-3 py-2 text-sm text-white placeholder:text-white/30 focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
className="w-full rounded border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
/>
</div>
<div>
<label className="mb-1 block text-xs font-medium text-white/50">Verification Type</label>
<label className="mb-1 block text-xs font-medium text-muted-foreground">Verification Type</label>
<select
value={step.verification_type || ''}
onChange={(e) => onUpdate({ verification_type: e.target.value as 'checkbox' | 'text_input' || undefined })}
className="w-full rounded border border-white/10 bg-black/50 px-3 py-2 text-sm text-white focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
className="w-full rounded border border-border bg-card px-3 py-2 text-sm text-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
>
<option value="">None</option>
<option value="checkbox">Checkbox (confirm done)</option>
@@ -230,7 +230,7 @@ export function StepEditor({ step, stepNumber, onUpdate, onCollapse, availableVa
{/* Reference URL + Notes toggle */}
<div className="grid grid-cols-2 gap-3">
<div>
<label className="mb-1 flex items-center gap-1 text-xs font-medium text-white/50">
<label className="mb-1 flex items-center gap-1 text-xs font-medium text-muted-foreground">
<ExternalLink className="h-3 w-3" />
Reference URL (optional)
</label>
@@ -239,16 +239,16 @@ export function StepEditor({ step, stepNumber, onUpdate, onCollapse, availableVa
value={step.reference_url || ''}
onChange={(e) => onUpdate({ reference_url: e.target.value || undefined })}
placeholder="https://learn.microsoft.com/..."
className="w-full rounded border border-white/10 bg-black/50 px-3 py-2 text-sm text-white placeholder:text-white/30 focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
className="w-full rounded border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
/>
</div>
<div className="flex items-end pb-1">
<label className="flex items-center gap-2 text-sm text-white/60">
<label className="flex items-center gap-2 text-sm text-muted-foreground">
<input
type="checkbox"
checked={step.notes_enabled !== false}
onChange={(e) => onUpdate({ notes_enabled: e.target.checked })}
className="rounded border-white/20"
className="rounded border-border"
/>
Allow tech notes
</label>

View File

@@ -6,7 +6,7 @@ import { cn } from '@/lib/utils'
const contentTypeConfig: Record<StepContentType, { icon: typeof Zap; color: string; label: string }> = {
action: { icon: Zap, color: 'text-blue-400', label: 'Action' },
informational: { icon: Info, color: 'text-white/50', label: 'Info' },
informational: { icon: Info, color: 'text-muted-foreground', label: 'Info' },
verification: { icon: CheckCircle2, color: 'text-emerald-400', label: 'Verify' },
warning: { icon: AlertTriangle, color: 'text-yellow-400', label: 'Warning' },
}
@@ -27,26 +27,26 @@ export function StepList() {
let stepCounter = 0
return (
<div className="glass-card rounded-2xl p-4 sm:p-6">
<div className="bg-card border border-border rounded-2xl p-4 sm:p-6">
<div className="mb-4 flex items-center justify-between">
<div className="flex items-center gap-2">
<Shield className="h-5 w-5 text-white/50" />
<h2 className="text-lg font-semibold text-white">Steps</h2>
<span className="text-sm text-white/40">
<Shield className="h-5 w-5 text-muted-foreground" />
<h2 className="text-lg font-semibold text-foreground">Steps</h2>
<span className="text-sm text-muted-foreground">
({procedureSteps.length} step{procedureSteps.length !== 1 ? 's' : ''})
</span>
</div>
<div className="flex items-center gap-2">
<button
onClick={() => addSectionHeader()}
className="flex items-center gap-1.5 rounded-md border border-white/10 px-3 py-1.5 text-sm text-white/60 hover:bg-white/10 hover:text-white"
className="flex items-center gap-1.5 rounded-md border border-border px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
>
<SeparatorHorizontal className="h-3.5 w-3.5" />
Add Section
</button>
<button
onClick={() => addStep()}
className="flex items-center gap-1.5 rounded-md border border-white/10 px-3 py-1.5 text-sm text-white/60 hover:bg-white/10 hover:text-white"
className="flex items-center gap-1.5 rounded-md border border-border px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
>
<Plus className="h-3.5 w-3.5" />
Add Step
@@ -60,17 +60,17 @@ export function StepList() {
return (
<div
key={step.id}
className="flex items-center gap-2 rounded-lg border border-dashed border-white/10 bg-white/[0.02] px-3 py-2"
className="flex items-center gap-2 rounded-lg border border-dashed border-border bg-white/[0.02] px-3 py-2"
>
<CheckCircle2 className="h-4 w-4 text-emerald-400/50" />
<input
type="text"
value={step.title}
onChange={(e) => updateStep(step.id, { title: e.target.value })}
className="flex-1 bg-transparent text-sm text-white/50 focus:outline-none"
className="flex-1 bg-transparent text-sm text-muted-foreground focus:outline-none"
placeholder="Procedure Complete"
/>
<span className="text-[10px] text-white/30">END</span>
<span className="text-[10px] text-muted-foreground">END</span>
</div>
)
}
@@ -96,18 +96,18 @@ export function StepList() {
return (
<div
key={step.id}
className="group flex items-center gap-2 border-b border-white/[0.06] pb-1 pt-3"
className="group flex items-center gap-2 border-b border-border pb-1 pt-3"
>
<GripVertical className="h-4 w-4 shrink-0 cursor-grab text-white/20 group-hover:text-white/40" />
<GripVertical className="h-4 w-4 shrink-0 cursor-grab text-muted-foreground group-hover:text-muted-foreground" />
<span
className="min-w-0 flex-1 cursor-pointer text-xs font-semibold uppercase tracking-wider text-white/40 hover:text-white/60"
className="min-w-0 flex-1 cursor-pointer text-xs font-semibold uppercase tracking-wider text-muted-foreground hover:text-muted-foreground"
onClick={() => setExpandedStepId(step.id)}
>
{step.title || 'Untitled Section'}
</span>
<button
onClick={() => removeStep(step.id)}
className="shrink-0 rounded p-1 text-white/30 opacity-0 hover:bg-red-500/20 hover:text-red-400 group-hover:opacity-100"
className="shrink-0 rounded p-1 text-muted-foreground opacity-0 hover:bg-red-500/20 hover:text-red-400 group-hover:opacity-100"
>
<Trash2 className="h-3.5 w-3.5" />
</button>
@@ -141,13 +141,13 @@ export function StepList() {
<div key={step.id}>
<div
className={cn(
'group flex items-center gap-2 rounded-xl border border-white/[0.06] px-3 py-2.5 transition-colors',
'hover:border-white/10 hover:bg-white/[0.03]'
'group flex items-center gap-2 rounded-xl border border-border px-3 py-2.5 transition-colors',
'hover:border-primary/30 hover:bg-white/[0.03]'
)}
>
<GripVertical className="h-4 w-4 shrink-0 cursor-grab text-white/20 group-hover:text-white/40" />
<GripVertical className="h-4 w-4 shrink-0 cursor-grab text-muted-foreground group-hover:text-muted-foreground" />
<span className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-white/10 text-xs font-medium text-white/70">
<span className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-accent text-xs font-medium text-muted-foreground">
{stepNumber}
</span>
@@ -156,28 +156,28 @@ export function StepList() {
</span>
<span
className="min-w-0 flex-1 cursor-pointer truncate text-sm text-white"
className="min-w-0 flex-1 cursor-pointer truncate text-sm text-foreground"
onClick={() => setExpandedStepId(step.id)}
>
{step.title || 'Untitled step'}
</span>
{step.estimated_minutes && (
<span className="shrink-0 text-[10px] text-white/30">
<span className="shrink-0 text-[10px] text-muted-foreground">
~{step.estimated_minutes}m
</span>
)}
<button
onClick={() => setExpandedStepId(step.id)}
className="shrink-0 rounded p-1 text-white/30 hover:bg-white/10 hover:text-white"
className="shrink-0 rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
>
<ChevronDown className="h-3.5 w-3.5" />
</button>
<button
onClick={() => removeStep(step.id)}
className="shrink-0 rounded p-1 text-white/30 opacity-0 hover:bg-red-500/20 hover:text-red-400 group-hover:opacity-100"
className="shrink-0 rounded p-1 text-muted-foreground opacity-0 hover:bg-red-500/20 hover:text-red-400 group-hover:opacity-100"
>
<Trash2 className="h-3.5 w-3.5" />
</button>
@@ -190,7 +190,7 @@ export function StepList() {
{/* Add step button at bottom */}
<button
onClick={() => addStep()}
className="mt-3 flex w-full items-center justify-center gap-1.5 rounded-lg border border-dashed border-white/10 py-2 text-sm text-white/40 transition-colors hover:border-white/20 hover:text-white/60"
className="mt-3 flex w-full items-center justify-center gap-1.5 rounded-lg border border-dashed border-border py-2 text-sm text-muted-foreground transition-colors hover:border-primary/30 hover:text-muted-foreground"
>
<Plus className="h-3.5 w-3.5" />
Add Step

View File

@@ -58,38 +58,38 @@ export function CompletionSummary({
<div className="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-emerald-400/10">
<CheckCircle2 className="h-8 w-8 text-emerald-400" />
</div>
<h1 className="text-2xl font-bold text-white">Procedure Complete</h1>
<p className="mt-1 text-white/40">{treeName}</p>
<h1 className="text-2xl font-bold text-foreground">Procedure Complete</h1>
<p className="mt-1 text-muted-foreground">{treeName}</p>
</div>
{/* Summary stats */}
<div className="grid grid-cols-3 gap-3">
<div className="glass-card rounded-xl p-3 text-center">
<div className="bg-card border border-border rounded-xl p-3 text-center">
<CheckCircle2 className="mx-auto mb-1 h-5 w-5 text-emerald-400" />
<div className="text-lg font-semibold text-white">{procedureSteps.length}</div>
<div className="text-xs text-white/40">Steps Completed</div>
<div className="text-lg font-semibold text-foreground">{procedureSteps.length}</div>
<div className="text-xs text-muted-foreground">Steps Completed</div>
</div>
<div className="glass-card rounded-xl p-3 text-center">
<Clock className="mx-auto mb-1 h-5 w-5 text-white/50" />
<div className="text-lg font-semibold text-white">{formatTime(totalMinutes)}</div>
<div className="text-xs text-white/40">Total Time</div>
<div className="bg-card border border-border rounded-xl p-3 text-center">
<Clock className="mx-auto mb-1 h-5 w-5 text-muted-foreground" />
<div className="text-lg font-semibold text-foreground">{formatTime(totalMinutes)}</div>
<div className="text-xs text-muted-foreground">Total Time</div>
</div>
<div className="glass-card rounded-xl p-3 text-center">
<FileText className="mx-auto mb-1 h-5 w-5 text-white/50" />
<div className="text-lg font-semibold text-white">{Object.keys(variables).length}</div>
<div className="text-xs text-white/40">Parameters</div>
<div className="bg-card border border-border rounded-xl p-3 text-center">
<FileText className="mx-auto mb-1 h-5 w-5 text-muted-foreground" />
<div className="text-lg font-semibold text-foreground">{Object.keys(variables).length}</div>
<div className="text-xs text-muted-foreground">Parameters</div>
</div>
</div>
{/* Project parameters */}
{Object.keys(variables).length > 0 && (
<div className="glass-card rounded-xl p-4">
<h3 className="mb-3 text-sm font-semibold text-white/60">Project Parameters</h3>
<div className="bg-card border border-border rounded-xl p-4">
<h3 className="mb-3 text-sm font-semibold text-muted-foreground">Project Parameters</h3>
<div className="space-y-1.5">
{Object.entries(variables).map(([key, value]) => (
<div key={key} className="flex items-baseline justify-between gap-4 text-sm">
<span className="font-mono text-white/40">{key}</span>
<span className="text-right text-white/70">{value}</span>
<span className="font-mono text-muted-foreground">{key}</span>
<span className="text-right text-muted-foreground">{value}</span>
</div>
))}
</div>
@@ -97,8 +97,8 @@ export function CompletionSummary({
)}
{/* Step details */}
<div className="glass-card rounded-xl p-4">
<h3 className="mb-3 text-sm font-semibold text-white/60">Step Summary</h3>
<div className="bg-card border border-border rounded-xl p-4">
<h3 className="mb-3 text-sm font-semibold text-muted-foreground">Step Summary</h3>
<div className="space-y-2">
{procedureSteps.map((step, index) => {
const completion = completions.get(step.id)
@@ -107,15 +107,15 @@ export function CompletionSummary({
<CheckCircle2 className="mt-0.5 h-4 w-4 shrink-0 text-emerald-400" />
<div className="min-w-0 flex-1">
<div className="flex items-center gap-2">
<span className="text-white/70">
<span className="text-muted-foreground">
{index + 1}. {step.title}
</span>
</div>
{completion?.notes && (
<p className="mt-0.5 text-xs text-white/30">Note: {completion.notes}</p>
<p className="mt-0.5 text-xs text-muted-foreground">Note: {completion.notes}</p>
)}
{completion?.verificationValue && (
<p className="mt-0.5 text-xs text-white/30">
<p className="mt-0.5 text-xs text-muted-foreground">
Verified: {completion.verificationValue}
</p>
)}
@@ -130,14 +130,14 @@ export function CompletionSummary({
<div className="flex items-center gap-3">
<button
onClick={onExport}
className="flex flex-1 items-center justify-center gap-2 rounded-lg border border-white/10 px-4 py-2.5 text-sm font-medium text-white/60 hover:bg-white/10 hover:text-white"
className="flex flex-1 items-center justify-center gap-2 rounded-lg border border-border px-4 py-2.5 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground"
>
<Download className="h-4 w-4" />
Export Report
</button>
<button
onClick={onClose}
className="flex flex-1 items-center justify-center gap-2 rounded-lg bg-white px-4 py-2.5 text-sm font-medium text-black hover:bg-white/90"
className="flex flex-1 items-center justify-center gap-2 rounded-lg bg-gradient-brand px-4 py-2.5 text-sm font-medium text-white shadow-lg shadow-primary/20 hover:opacity-90"
>
Done
</button>

View File

@@ -71,10 +71,10 @@ export function IntakeFormModal({ isOpen, fields, treeName, onSubmit, onCancel }
const error = errors[field.variable_name]
const baseInputClass = cn(
'w-full rounded-lg border bg-black/50 px-3 py-2 text-sm text-white placeholder:text-white/30 focus:outline-none focus:ring-1',
'w-full rounded-lg border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-1',
error
? 'border-red-400/50 focus:border-red-400 focus:ring-red-400/20'
: 'border-white/10 focus:border-white/30 focus:ring-white/20'
: 'border-border focus:border-primary focus:ring-primary/20'
)
let input: React.ReactNode
@@ -111,9 +111,9 @@ export function IntakeFormModal({ isOpen, fields, treeName, onSubmit, onCancel }
type="checkbox"
checked={value === 'true'}
onChange={(e) => setValue(field.variable_name, e.target.checked ? 'true' : 'false')}
className="rounded border-white/20"
className="rounded border-border"
/>
<span className="text-sm text-white/70">{field.placeholder || field.label}</span>
<span className="text-sm text-muted-foreground">{field.placeholder || field.label}</span>
</label>
)
break
@@ -161,9 +161,9 @@ export function IntakeFormModal({ isOpen, fields, treeName, onSubmit, onCancel }
: [...selected, opt]
setValue(field.variable_name, next.join(','))
}}
className="rounded border-white/20"
className="rounded border-border"
/>
<span className="text-sm text-white/70">{opt}</span>
<span className="text-sm text-muted-foreground">{opt}</span>
</label>
)
})}
@@ -197,12 +197,12 @@ export function IntakeFormModal({ isOpen, fields, treeName, onSubmit, onCancel }
return (
<div key={field.variable_name}>
<label className="mb-1 flex items-center gap-1 text-sm font-medium text-white/60">
<label className="mb-1 flex items-center gap-1 text-sm font-medium text-muted-foreground">
{field.label}
{field.required && <span className="text-red-400">*</span>}
</label>
{field.help_text && (
<p className="mb-1.5 text-xs text-white/30">{field.help_text}</p>
<p className="mb-1.5 text-xs text-muted-foreground">{field.help_text}</p>
)}
{input}
{error && <p className="mt-1 text-xs text-red-400">{error}</p>}
@@ -212,12 +212,12 @@ export function IntakeFormModal({ isOpen, fields, treeName, onSubmit, onCancel }
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm">
<div className="mx-4 w-full max-w-lg rounded-2xl border border-white/10 bg-[#0a0a0a] shadow-xl">
<div className="mx-4 w-full max-w-lg rounded-2xl border border-border bg-[#0a0a0a] shadow-xl">
{/* Header */}
<div className="border-b border-white/[0.06] px-6 py-4">
<h2 className="text-lg font-semibold text-white">Project Information</h2>
<p className="mt-0.5 text-sm text-white/40">
Fill in the details for <span className="text-white/60">{treeName}</span>
<div className="border-b border-border px-6 py-4">
<h2 className="text-lg font-semibold text-foreground">Project Information</h2>
<p className="mt-0.5 text-sm text-muted-foreground">
Fill in the details for <span className="text-muted-foreground">{treeName}</span>
</p>
</div>
@@ -227,7 +227,7 @@ export function IntakeFormModal({ isOpen, fields, treeName, onSubmit, onCancel }
{Array.from(groups.entries()).map(([groupName, groupFields]) => (
<div key={groupName}>
{groupName && (
<h3 className="mb-3 border-b border-white/[0.06] pb-1 text-xs font-semibold uppercase tracking-wider text-white/40">
<h3 className="mb-3 border-b border-border pb-1 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
{groupName}
</h3>
)}
@@ -239,17 +239,17 @@ export function IntakeFormModal({ isOpen, fields, treeName, onSubmit, onCancel }
</div>
{/* Footer */}
<div className="flex items-center justify-end gap-2 border-t border-white/[0.06] px-6 py-4">
<div className="flex items-center justify-end gap-2 border-t border-border px-6 py-4">
<button
type="button"
onClick={onCancel}
className="rounded-md border border-white/10 px-4 py-2 text-sm text-white/60 hover:bg-white/10 hover:text-white"
className="rounded-md border border-border px-4 py-2 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
>
Cancel
</button>
<button
type="submit"
className="rounded-md bg-white px-4 py-2 text-sm font-medium text-black hover:bg-white/90"
className="rounded-md bg-gradient-brand px-4 py-2 text-sm font-medium text-white shadow-lg shadow-primary/20 hover:opacity-90"
>
Start Procedure
</button>

View File

@@ -31,7 +31,7 @@ export function StepChecklist({ steps, currentStepIndex, completedStepIds, onSte
return (
<div key={step.id}>
{showSection && (
<div className="mb-1 mt-3 border-b border-white/[0.06] pb-1 text-[10px] font-semibold uppercase tracking-wider text-white/40 first:mt-0">
<div className="mb-1 mt-3 border-b border-border pb-1 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground first:mt-0">
{step.section_header}
</div>
)}
@@ -39,24 +39,24 @@ export function StepChecklist({ steps, currentStepIndex, completedStepIds, onSte
onClick={() => onStepClick(index)}
className={cn(
'flex w-full items-center gap-2 rounded-lg px-2 py-1.5 text-left text-sm transition-colors',
isCurrent && 'bg-white/10 text-white',
!isCurrent && isCompleted && 'text-white/40',
!isCurrent && !isCompleted && 'text-white/50 hover:bg-white/[0.04]'
isCurrent && 'bg-accent text-foreground',
!isCurrent && isCompleted && 'text-muted-foreground',
!isCurrent && !isCompleted && 'text-muted-foreground hover:bg-accent/50'
)}
>
{isCompleted ? (
<CheckCircle2 className="h-4 w-4 shrink-0 text-emerald-400" />
) : isCurrent ? (
<ArrowRight className="h-4 w-4 shrink-0 text-white" />
<ArrowRight className="h-4 w-4 shrink-0 text-foreground" />
) : (
<Circle className="h-4 w-4 shrink-0 text-white/20" />
<Circle className="h-4 w-4 shrink-0 text-muted-foreground" />
)}
<span className="flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-white/10 text-[10px] font-medium">
<span className="flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-accent text-[10px] font-medium">
{index + 1}
</span>
<span className="min-w-0 flex-1 truncate">{step.title || 'Untitled step'}</span>
{step.estimated_minutes && (
<span className="shrink-0 text-[10px] text-white/30">~{step.estimated_minutes}m</span>
<span className="shrink-0 text-[10px] text-muted-foreground">~{step.estimated_minutes}m</span>
)}
</button>
</div>

View File

@@ -6,7 +6,7 @@ import { cn } from '@/lib/utils'
const contentTypeConfig: Record<StepContentType, { icon: typeof Zap; color: string; bg: string; label: string }> = {
action: { icon: Zap, color: 'text-blue-400', bg: 'bg-blue-400/10', label: 'Action' },
informational: { icon: Info, color: 'text-white/50', bg: 'bg-white/10', label: 'Info' },
informational: { icon: Info, color: 'text-muted-foreground', bg: 'bg-accent', label: 'Info' },
verification: { icon: CheckCircle2, color: 'text-emerald-400', bg: 'bg-emerald-400/10', label: 'Verification' },
warning: { icon: AlertTriangle, color: 'text-yellow-400', bg: 'bg-yellow-400/10', label: 'Warning' },
}
@@ -81,21 +81,21 @@ export function StepDetail({
<div className="space-y-4">
{/* Step header */}
<div className="flex items-start gap-3">
<span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-white/10 text-sm font-semibold text-white">
<span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-accent text-sm font-semibold text-foreground">
{stepNumber}
</span>
<div className="min-w-0 flex-1">
<h2 className="text-lg font-semibold text-white">{step.title}</h2>
<h2 className="text-lg font-semibold text-foreground">{step.title}</h2>
<div className="mt-1 flex items-center gap-2">
<span className={cn('inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs', config.bg, config.color)}>
<Icon className="h-3 w-3" />
{config.label}
</span>
<span className="text-xs text-white/30">
<span className="text-xs text-muted-foreground">
Step {stepNumber} of {totalSteps}
</span>
{step.estimated_minutes && (
<span className="text-xs text-white/30">~{step.estimated_minutes} min</span>
<span className="text-xs text-muted-foreground">~{step.estimated_minutes} min</span>
)}
</div>
</div>
@@ -111,7 +111,7 @@ export function StepDetail({
{/* Description */}
{step.description && (
<div className="prose prose-invert prose-sm max-w-none text-white/70">
<div className="prose prose-invert prose-sm max-w-none text-muted-foreground">
<p className="whitespace-pre-wrap">{resolve(step.description)}</p>
</div>
)}
@@ -120,14 +120,14 @@ export function StepDetail({
{commandBlocks.length > 0 && (
<div className="space-y-3">
{commandBlocks.map((cmd, i) => (
<div key={i} className="rounded-lg border border-white/[0.06] bg-black/50">
<div className="flex items-center justify-between border-b border-white/[0.06] px-3 py-1.5">
<span className="text-xs font-medium text-white/40">
<div key={i} className="rounded-lg border border-border bg-card">
<div className="flex items-center justify-between border-b border-border px-3 py-1.5">
<span className="text-xs font-medium text-muted-foreground">
{cmd.label || (cmd.language ? cmd.language : 'Command')}
</span>
<button
onClick={() => handleCopyCommand(cmd.code, i)}
className="flex items-center gap-1 rounded px-2 py-0.5 text-xs text-white/40 hover:bg-white/10 hover:text-white"
className="flex items-center gap-1 rounded px-2 py-0.5 text-xs text-muted-foreground hover:bg-accent hover:text-foreground"
>
{copiedIndex === i ? <Check className="h-3 w-3 text-emerald-400" /> : <Copy className="h-3 w-3" />}
{copiedIndex === i ? 'Copied' : 'Copy'}
@@ -143,37 +143,37 @@ export function StepDetail({
{/* Expected outcome */}
{step.expected_outcome && (
<div className="rounded-lg border border-white/[0.06] bg-white/[0.02] p-3">
<h4 className="mb-1 text-xs font-medium text-white/50">Expected Outcome</h4>
<p className="text-sm text-white/70">{resolve(step.expected_outcome)}</p>
<div className="rounded-lg border border-border bg-white/[0.02] p-3">
<h4 className="mb-1 text-xs font-medium text-muted-foreground">Expected Outcome</h4>
<p className="text-sm text-muted-foreground">{resolve(step.expected_outcome)}</p>
</div>
)}
{/* Verification */}
{verificationPrompt && (
<div className="rounded-lg border border-white/[0.06] bg-white/[0.02] p-3">
<h4 className="mb-2 text-xs font-medium text-white/50">Verification</h4>
<div className="rounded-lg border border-border bg-white/[0.02] p-3">
<h4 className="mb-2 text-xs font-medium text-muted-foreground">Verification</h4>
{verificationType === 'checkbox' ? (
<label className="flex items-center gap-2 text-sm text-white/70">
<label className="flex items-center gap-2 text-sm text-muted-foreground">
<input
type="checkbox"
checked={!!verificationValue}
onChange={(e) => onVerificationChange(e.target.checked ? 'confirmed' : '')}
disabled={isCompleted}
className="rounded border-white/20"
className="rounded border-border"
/>
{resolve(verificationPrompt)}
</label>
) : (
<div>
<p className="mb-2 text-sm text-white/70">{resolve(verificationPrompt)}</p>
<p className="mb-2 text-sm text-muted-foreground">{resolve(verificationPrompt)}</p>
<input
type="text"
value={verificationValue}
onChange={(e) => onVerificationChange(e.target.value)}
disabled={isCompleted}
placeholder="Enter observed value..."
className="w-full rounded border border-white/10 bg-black/50 px-3 py-1.5 text-sm text-white placeholder:text-white/30 focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20 disabled:opacity-50"
className="w-full rounded border border-border bg-card px-3 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20 disabled:opacity-50"
/>
</div>
)}
@@ -183,13 +183,13 @@ export function StepDetail({
{/* Notes */}
{step.notes_enabled !== false && (
<div>
<label className="mb-1 block text-xs font-medium text-white/50">Notes</label>
<label className="mb-1 block text-xs font-medium text-muted-foreground">Notes</label>
<textarea
value={notes}
onChange={(e) => onNotesChange(e.target.value)}
placeholder="Add notes for this step..."
rows={2}
className="w-full rounded-lg border border-white/10 bg-black/50 px-3 py-2 text-sm text-white placeholder:text-white/30 focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20"
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-none focus:ring-1 focus:ring-primary/20"
/>
</div>
)}
@@ -200,7 +200,7 @@ export function StepDetail({
href={resolve(step.reference_url)}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1.5 text-sm text-white/40 hover:text-white"
className="inline-flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground"
>
<ExternalLink className="h-3.5 w-3.5" />
Reference Documentation
@@ -216,7 +216,7 @@ export function StepDetail({
'flex w-full items-center justify-center gap-2 rounded-lg px-4 py-2.5 text-sm font-medium transition-colors',
isCompleted
? 'bg-emerald-400/10 text-emerald-400'
: 'bg-white text-black hover:bg-white/90 disabled:opacity-40 disabled:hover:bg-white'
: 'bg-gradient-brand text-white shadow-lg shadow-primary/20 hover:opacity-90 disabled:opacity-40 disabled:hover:opacity-100'
)}
>
{isCompleted ? (

View File

@@ -70,11 +70,11 @@ export function StepDetailModal({ stepId, onClose, onInsert }: StepDetailModalPr
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm">
<div className="relative flex h-[90vh] w-full max-w-3xl flex-col glass-card rounded-2xl shadow-lg">
<div className="relative flex h-[90vh] w-full max-w-3xl flex-col bg-card border border-border rounded-2xl shadow-lg">
{/* Header */}
<div className="flex items-start justify-between border-b border-white/[0.06] p-6 pb-4">
<div className="flex items-start justify-between border-b border-border p-6 pb-4">
{isLoading ? (
<div className="h-6 w-48 animate-pulse rounded bg-white/10" />
<div className="h-6 w-48 animate-pulse rounded bg-accent" />
) : error ? (
<h2 className="text-lg font-semibold text-red-400">{error}</h2>
) : step ? (
@@ -90,7 +90,7 @@ export function StepDetailModal({ stepId, onClose, onInsert }: StepDetailModalPr
{step.step_type}
</span>
{step.category_name && (
<span className="text-xs text-white/40">📁 {step.category_name}</span>
<span className="text-xs text-muted-foreground">{step.category_name}</span>
)}
{step.is_featured && (
<span className="rounded bg-yellow-400/10 px-2 py-0.5 text-xs font-medium text-yellow-400">
@@ -99,16 +99,16 @@ export function StepDetailModal({ stepId, onClose, onInsert }: StepDetailModalPr
)}
{step.is_verified && (
<span className="rounded bg-emerald-400/10 px-2 py-0.5 text-xs font-medium text-emerald-400">
Verified
Verified
</span>
)}
</div>
<h2 className="text-xl font-semibold text-white">{step.title}</h2>
<h2 className="text-xl font-semibold text-foreground">{step.title}</h2>
</div>
) : null}
<button
onClick={onClose}
className="rounded-md p-1 text-white/40 hover:bg-white/10 hover:text-white"
className="rounded-md p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
aria-label="Close"
>
<X className="h-5 w-5" />
@@ -119,18 +119,18 @@ export function StepDetailModal({ stepId, onClose, onInsert }: StepDetailModalPr
<div className="flex-1 overflow-y-auto p-6">
{isLoading ? (
<div className="space-y-4">
<div className="h-4 w-full animate-pulse rounded bg-white/10" />
<div className="h-4 w-3/4 animate-pulse rounded bg-white/10" />
<div className="h-4 w-5/6 animate-pulse rounded bg-white/10" />
<div className="h-4 w-full animate-pulse rounded bg-accent" />
<div className="h-4 w-3/4 animate-pulse rounded bg-accent" />
<div className="h-4 w-5/6 animate-pulse rounded bg-accent" />
</div>
) : error ? (
<p className="text-sm text-white/40">{error}</p>
<p className="text-sm text-muted-foreground">{error}</p>
) : step ? (
<div className="space-y-6">
{/* Rating */}
{hasRating && (
<div>
<h3 className="mb-2 text-sm font-semibold text-white">Rating</h3>
<h3 className="mb-2 text-sm font-semibold text-foreground">Rating</h3>
<div className="flex items-center gap-2">
<div className="flex items-center gap-1">
{[1, 2, 3, 4, 5].map(i => (
@@ -140,12 +140,12 @@ export function StepDetailModal({ stepId, onClose, onInsert }: StepDetailModalPr
'h-4 w-4',
i <= Math.round(step.rating_average)
? 'fill-yellow-400 text-yellow-400'
: 'text-white/20'
: 'text-muted-foreground'
)}
/>
))}
</div>
<span className="text-sm text-white/70">
<span className="text-sm text-muted-foreground">
{step.rating_average.toFixed(1)} ({step.rating_count} {step.rating_count === 1 ? 'rating' : 'ratings'})
</span>
</div>
@@ -155,12 +155,12 @@ export function StepDetailModal({ stepId, onClose, onInsert }: StepDetailModalPr
{/* Tags */}
{step.tags.length > 0 && (
<div>
<h3 className="mb-2 text-sm font-semibold text-white">Tags</h3>
<h3 className="mb-2 text-sm font-semibold text-foreground">Tags</h3>
<div className="flex flex-wrap gap-1.5">
{step.tags.map(tag => (
<span
key={tag}
className="rounded-full bg-white/10 px-2 py-1 text-xs text-white/70"
className="rounded-full bg-accent px-2 py-1 text-xs text-muted-foreground"
>
{tag}
</span>
@@ -172,7 +172,7 @@ export function StepDetailModal({ stepId, onClose, onInsert }: StepDetailModalPr
{/* Instructions */}
<div>
<h3 className="mb-2 text-sm font-semibold">Instructions</h3>
<div className="rounded-lg border border-white/[0.06] bg-white/5 p-4">
<div className="rounded-lg border border-border bg-accent/50 p-4">
<MarkdownContent content={step.content.instructions} />
</div>
</div>
@@ -180,8 +180,8 @@ export function StepDetailModal({ stepId, onClose, onInsert }: StepDetailModalPr
{/* Help Text */}
{step.content.help_text && (
<div>
<h3 className="mb-2 text-sm font-semibold text-white">Help Text</h3>
<div className="rounded-lg border border-white/[0.06] bg-blue-400/5 p-4 text-sm">
<h3 className="mb-2 text-sm font-semibold text-foreground">Help Text</h3>
<div className="rounded-lg border border-border bg-blue-400/5 p-4 text-sm">
<MarkdownContent content={step.content.help_text} />
</div>
</div>
@@ -190,19 +190,19 @@ export function StepDetailModal({ stepId, onClose, onInsert }: StepDetailModalPr
{/* Commands */}
{step.content.commands && step.content.commands.length > 0 && (
<div>
<h3 className="mb-2 text-sm font-semibold text-white">Commands</h3>
<h3 className="mb-2 text-sm font-semibold text-foreground">Commands</h3>
<div className="space-y-2">
{step.content.commands.map((cmd, index) => (
<div key={index} className="group relative">
<div className="mb-1 flex items-center justify-between">
<span className="text-xs font-medium text-white/40">{cmd.label}</span>
<span className="text-xs font-medium text-muted-foreground">{cmd.label}</span>
<button
onClick={() => handleCopyCommand(cmd.command, index)}
className={cn(
'flex items-center gap-1 rounded px-2 py-1 text-xs transition-colors',
copiedCommandIndex === index
? 'bg-emerald-400/10 text-emerald-400'
: 'bg-white/10 text-white/40 hover:bg-white/20 hover:text-white'
: 'bg-accent text-muted-foreground hover:bg-accent hover:text-foreground'
)}
>
{copiedCommandIndex === index ? (
@@ -218,7 +218,7 @@ export function StepDetailModal({ stepId, onClose, onInsert }: StepDetailModalPr
)}
</button>
</div>
<pre className="overflow-x-auto rounded bg-black/50 p-3 text-xs text-white">
<pre className="overflow-x-auto rounded bg-card p-3 text-xs text-foreground">
<code>{cmd.command}</code>
</pre>
</div>
@@ -231,23 +231,23 @@ export function StepDetailModal({ stepId, onClose, onInsert }: StepDetailModalPr
{topReviews.length > 0 && (
<div>
<div className="mb-2 flex items-center justify-between">
<h3 className="text-sm font-semibold text-white">Reviews</h3>
<h3 className="text-sm font-semibold text-foreground">Reviews</h3>
{reviews.length > 3 && (
<button className="text-xs text-white/70 hover:text-white hover:underline">
<button className="text-xs text-muted-foreground hover:text-foreground hover:underline">
See all {reviews.length} reviews
</button>
)}
</div>
<div className="space-y-3">
{topReviews.map(review => (
<div key={review.id} className="rounded-lg border border-white/[0.06] bg-white/5 p-3">
<div key={review.id} className="rounded-lg border border-border bg-accent/50 p-3">
<div className="mb-2 flex items-center justify-between">
<div className="flex items-center gap-2 text-sm">
<User className="h-3.5 w-3.5" />
<span className="font-medium text-white">{review.user_name || 'Anonymous'}</span>
<span className="font-medium text-foreground">{review.user_name || 'Anonymous'}</span>
{review.verified_use && (
<span className="rounded bg-emerald-400/10 px-1.5 py-0.5 text-xs text-emerald-400">
Verified Use
Verified Use
</span>
)}
</div>
@@ -259,14 +259,14 @@ export function StepDetailModal({ stepId, onClose, onInsert }: StepDetailModalPr
'h-3 w-3',
i <= review.rating
? 'fill-yellow-400 text-yellow-400'
: 'text-white/20'
: 'text-muted-foreground'
)}
/>
))}
</div>
</div>
<p className="text-sm text-white/70">{review.review_text}</p>
<div className="mt-2 flex items-center gap-2 text-xs text-white/40">
<p className="text-sm text-muted-foreground">{review.review_text}</p>
<div className="mt-2 flex items-center gap-2 text-xs text-muted-foreground">
<Calendar className="h-3 w-3" />
{new Date(review.created_at).toLocaleDateString()}
</div>
@@ -277,22 +277,22 @@ export function StepDetailModal({ stepId, onClose, onInsert }: StepDetailModalPr
)}
{/* Metadata */}
<div className="rounded-lg border border-white/[0.06] bg-white/5 p-4">
<div className="rounded-lg border border-border bg-accent/50 p-4">
<div className="grid grid-cols-2 gap-3 text-sm">
<div>
<span className="text-white/40">Author:</span>
<span className="ml-2 font-medium text-white">{step.author_name || 'Unknown'}</span>
<span className="text-muted-foreground">Author:</span>
<span className="ml-2 font-medium text-foreground">{step.author_name || 'Unknown'}</span>
</div>
<div>
<span className="text-white/40">Usage Count:</span>
<span className="ml-2 font-medium text-white">{step.usage_count}</span>
<span className="text-muted-foreground">Usage Count:</span>
<span className="ml-2 font-medium text-foreground">{step.usage_count}</span>
</div>
<div>
<span className="text-white/40">Created:</span>
<span className="ml-2 font-medium text-white">{new Date(step.created_at).toLocaleDateString()}</span>
<span className="text-muted-foreground">Created:</span>
<span className="ml-2 font-medium text-foreground">{new Date(step.created_at).toLocaleDateString()}</span>
</div>
<div>
<span className="text-white/40">Visibility:</span>
<span className="text-muted-foreground">Visibility:</span>
<span className="ml-2 font-medium capitalize">{step.visibility}</span>
</div>
</div>
@@ -302,10 +302,10 @@ export function StepDetailModal({ stepId, onClose, onInsert }: StepDetailModalPr
</div>
{/* Footer - Actions */}
<div className="flex gap-2 border-t border-white/[0.06] p-4">
<div className="flex gap-2 border-t border-border p-4">
<button
onClick={onClose}
className="flex-1 rounded-md border border-white/10 px-4 py-2 text-sm font-medium text-white/60 hover:bg-white/10 hover:text-white"
className="flex-1 rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground"
>
Cancel
</button>
@@ -313,8 +313,8 @@ export function StepDetailModal({ stepId, onClose, onInsert }: StepDetailModalPr
onClick={handleInsert}
disabled={!step}
className={cn(
'flex-1 rounded-md bg-white px-4 py-2 text-sm font-medium text-black',
'hover:bg-white/90 disabled:opacity-50'
'flex-1 rounded-md bg-gradient-brand px-4 py-2 text-sm font-medium text-white shadow-lg shadow-primary/20',
'hover:opacity-90 disabled:opacity-50'
)}
>
Insert Into Session

View File

@@ -133,16 +133,16 @@ export function StepLibraryBrowser({ onInsert, onCreateNew, showCreateButton = f
return (
<div className="flex h-full flex-col">
{/* Header - Filters */}
<div className="space-y-4 border-b border-white/[0.06] p-4">
<div className="space-y-4 border-b border-border p-4">
{/* Search */}
<div className="relative">
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-white/40" />
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
<input
type="text"
placeholder="Search steps..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="w-full rounded-md border border-white/10 bg-black/50 py-2 pl-10 pr-4 text-sm text-white placeholder:text-white/40 focus:outline-none focus:border-white/30 focus:ring-1 focus:ring-white/20"
className="w-full rounded-md border border-border bg-card py-2 pl-10 pr-4 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20"
/>
</div>
@@ -153,7 +153,7 @@ export function StepLibraryBrowser({ onInsert, onCreateNew, showCreateButton = f
aria-label="Filter by category"
value={selectedCategoryId || ''}
onChange={(e) => setSelectedCategoryId(e.target.value || undefined)}
className="rounded-md border border-white/10 bg-black/50 px-3 py-2 text-sm text-white focus:outline-none focus:border-white/30 focus:ring-1 focus:ring-white/20"
className="rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20"
>
<option value="">All Categories</option>
{categories.map(cat => (
@@ -166,7 +166,7 @@ export function StepLibraryBrowser({ onInsert, onCreateNew, showCreateButton = f
aria-label="Filter by step type"
value={selectedStepType || ''}
onChange={(e) => setSelectedStepType((e.target.value as 'decision' | 'action' | 'solution') || undefined)}
className="rounded-md border border-white/10 bg-black/50 px-3 py-2 text-sm text-white focus:outline-none focus:border-white/30 focus:ring-1 focus:ring-white/20"
className="rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20"
>
<option value="">All Types</option>
<option value="decision">Decision</option>
@@ -179,7 +179,7 @@ export function StepLibraryBrowser({ onInsert, onCreateNew, showCreateButton = f
aria-label="Filter by minimum rating"
value={minRating?.toString() || ''}
onChange={(e) => setMinRating(e.target.value ? Number(e.target.value) : undefined)}
className="rounded-md border border-white/10 bg-black/50 px-3 py-2 text-sm text-white focus:outline-none focus:border-white/30 focus:ring-1 focus:ring-white/20"
className="rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20"
>
<option value="">Any Rating</option>
<option value="4">4+ Stars</option>
@@ -192,7 +192,7 @@ export function StepLibraryBrowser({ onInsert, onCreateNew, showCreateButton = f
aria-label="Sort steps by"
value={sortBy}
onChange={(e) => setSortBy(e.target.value as 'recent' | 'popular' | 'highest_rated' | 'most_used')}
className="rounded-md border border-white/10 bg-black/50 px-3 py-2 text-sm text-white focus:outline-none focus:border-white/30 focus:ring-1 focus:ring-white/20"
className="rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20"
>
<option value="recent">Most Recent</option>
<option value="popular">Most Popular</option>
@@ -204,7 +204,7 @@ export function StepLibraryBrowser({ onInsert, onCreateNew, showCreateButton = f
{/* Popular Tags */}
{popularTags.length > 0 && (
<div>
<div className="mb-2 text-xs font-medium text-white/40">Popular Tags:</div>
<div className="mb-2 text-xs font-medium text-muted-foreground">Popular Tags:</div>
<div className="flex flex-wrap gap-1.5">
{popularTags.map(tag => (
<button
@@ -213,8 +213,8 @@ export function StepLibraryBrowser({ onInsert, onCreateNew, showCreateButton = f
className={cn(
'rounded-full px-2.5 py-1 text-xs transition-colors',
selectedTag === tag.tag
? 'bg-white text-black'
: 'bg-white/10 text-white/70 hover:bg-white/20'
? 'bg-gradient-brand text-white shadow-lg shadow-primary/20'
: 'bg-accent text-muted-foreground hover:bg-accent'
)}
>
{tag.tag} ({tag.count})
@@ -228,7 +228,7 @@ export function StepLibraryBrowser({ onInsert, onCreateNew, showCreateButton = f
{hasActiveFilters && (
<button
onClick={clearFilters}
className="text-sm text-white/70 hover:text-white hover:underline"
className="text-sm text-muted-foreground hover:text-foreground hover:underline"
>
Clear all filters
</button>
@@ -239,16 +239,16 @@ export function StepLibraryBrowser({ onInsert, onCreateNew, showCreateButton = f
<div className="flex-1 overflow-y-auto p-4">
{isLoading ? (
<div className="flex items-center justify-center py-12">
<Loader2 className="h-8 w-8 animate-spin text-white/40" />
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
</div>
) : error ? (
<div className="rounded-lg border border-red-400/20 bg-red-400/10 p-4 text-center text-sm text-red-400">
{error}
</div>
) : steps.length === 0 ? (
<div className="rounded-lg border border-white/[0.06] bg-white/5 p-12 text-center">
<p className="mb-2 text-lg font-medium text-white">No steps found</p>
<p className="text-sm text-white/40">
<div className="rounded-lg border border-border bg-accent/50 p-12 text-center">
<p className="mb-2 text-lg font-medium text-foreground">No steps found</p>
<p className="text-sm text-muted-foreground">
{hasActiveFilters ? 'Try adjusting your filters' : 'Create your first step to get started!'}
</p>
</div>
@@ -261,7 +261,7 @@ export function StepLibraryBrowser({ onInsert, onCreateNew, showCreateButton = f
onClick={() => toggleSection('private')}
className="mb-3 flex w-full items-center justify-between"
>
<h3 className="text-sm font-semibold text-white">My Steps ({groupedSteps.private.length})</h3>
<h3 className="text-sm font-semibold text-foreground">My Steps ({groupedSteps.private.length})</h3>
{collapsedSections.private ? (
<ChevronDown className="h-4 w-4" />
) : (
@@ -290,7 +290,7 @@ export function StepLibraryBrowser({ onInsert, onCreateNew, showCreateButton = f
onClick={() => toggleSection('team')}
className="mb-3 flex w-full items-center justify-between"
>
<h3 className="text-sm font-semibold text-white">Team Steps ({groupedSteps.team.length})</h3>
<h3 className="text-sm font-semibold text-foreground">Team Steps ({groupedSteps.team.length})</h3>
{collapsedSections.team ? (
<ChevronDown className="h-4 w-4" />
) : (
@@ -319,7 +319,7 @@ export function StepLibraryBrowser({ onInsert, onCreateNew, showCreateButton = f
onClick={() => toggleSection('public')}
className="mb-3 flex w-full items-center justify-between"
>
<h3 className="text-sm font-semibold text-white">Community ({groupedSteps.public.length})</h3>
<h3 className="text-sm font-semibold text-foreground">Community ({groupedSteps.public.length})</h3>
{collapsedSections.public ? (
<ChevronDown className="h-4 w-4" />
) : (
@@ -346,10 +346,10 @@ export function StepLibraryBrowser({ onInsert, onCreateNew, showCreateButton = f
{/* Footer - Optional Create Button */}
{showCreateButton && onCreateNew && (
<div className="border-t border-white/[0.06] p-4">
<div className="border-t border-border p-4">
<button
onClick={onCreateNew}
className="w-full rounded-md bg-white px-4 py-2 text-sm font-medium text-black hover:bg-white/90"
className="w-full rounded-md bg-gradient-brand px-4 py-2 text-sm font-medium text-white shadow-lg shadow-primary/20 hover:opacity-90"
>
+ Create New Step
</button>