chore: Tailwind CSS v3 → v4 migration (#99)
* chore: run Tailwind v4 upgrade tool (Phase 1) - Upgraded tailwindcss v3 → v4.2.1, postcss plugin to @tailwindcss/postcss - Deleted tailwind.config.js, migrated theme to CSS @theme block in index.css - Replaced @tailwind directives with @import 'tailwindcss' - Added @custom-variant dark, @utility blocks for custom utilities - Updated class names across 128 files (shadow-sm → shadow-xs, etc.) - Removed autoprefixer (built into v4) - Added migration plan doc Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: switch from @tailwindcss/postcss to @tailwindcss/vite (Phase 2) - Replaced @tailwindcss/postcss with @tailwindcss/vite plugin - Deleted postcss.config.js (no longer needed) - Tailwind now runs as a native Vite plugin for faster HMR Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: convert to OKLCH colors, move keyframes into @theme (Phase 3-4) - Replaced all HSL color indirection with direct OKLCH values in @theme - Moved all keyframes inside @theme block (v4 pattern) - Eliminated hsl(var(--x)) double-indirection across 17 component files - Replaced hsl() inline styles with var(--color-*) theme references - Cleaned up redundant rdp-* utility blocks - Fixed @custom-variant dark syntax to use :where() - Added sidebar/glass/shadow vars as OKLCH in :root Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit was merged in pull request #99.
This commit is contained in:
@@ -74,7 +74,7 @@ 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-none focus:ring-1 focus:ring-primary/20 resize-none"
|
||||
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"
|
||||
/>
|
||||
|
||||
{/* Actions */}
|
||||
|
||||
@@ -62,7 +62,7 @@ export function ContinuationModal({
|
||||
'hover:border-border hover:bg-accent'
|
||||
)}
|
||||
>
|
||||
<div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-accent">
|
||||
<div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-accent">
|
||||
{nodeTypeIcons[node.type]}
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
@@ -71,7 +71,7 @@ export function ContinuationModal({
|
||||
{nodeTypeLabels[node.type]}
|
||||
</p>
|
||||
</div>
|
||||
<ArrowRight className="h-4 w-4 flex-shrink-0 text-muted-foreground" />
|
||||
<ArrowRight className="h-4 w-4 shrink-0 text-muted-foreground" />
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
@@ -98,7 +98,7 @@ export function ContinuationModal({
|
||||
'hover:border-amber-500 hover:bg-amber-500/10'
|
||||
)}
|
||||
>
|
||||
<div className="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full bg-amber-500/10">
|
||||
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-amber-500/10">
|
||||
<GitBranch className="h-5 w-5 text-amber-500" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
@@ -111,7 +111,7 @@ export function ContinuationModal({
|
||||
|
||||
{/* Warning */}
|
||||
<div className="mt-3 flex items-start gap-2 rounded-md bg-yellow-400/10 p-3">
|
||||
<AlertTriangle className="mt-0.5 h-4 w-4 flex-shrink-0 text-yellow-400" />
|
||||
<AlertTriangle className="mt-0.5 h-4 w-4 shrink-0 text-yellow-400" />
|
||||
<p className="text-sm text-yellow-400">
|
||||
You'll need to complete this branch manually or mark the issue as resolved.
|
||||
Custom branches can be saved as a personal tree when your session ends.
|
||||
|
||||
@@ -141,7 +141,7 @@ export function ExportPreviewModal({
|
||||
className={cn(
|
||||
'h-96 w-full resize-y rounded-md border border-border bg-card p-4',
|
||||
'font-mono text-sm text-foreground',
|
||||
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20'
|
||||
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20'
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -153,7 +153,7 @@ export function ExportPreviewModal({
|
||||
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',
|
||||
'focus:outline-none focus:ring-2 focus:ring-primary/20'
|
||||
'focus:outline-hidden focus:ring-2 focus:ring-primary/20'
|
||||
)}
|
||||
>
|
||||
{copied ? (
|
||||
@@ -173,7 +173,7 @@ export function ExportPreviewModal({
|
||||
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-none focus:ring-2 focus:ring-primary/20'
|
||||
'hover:opacity-90 focus:outline-hidden focus:ring-2 focus:ring-primary/20'
|
||||
)}
|
||||
>
|
||||
<Download className="h-4 w-4" />
|
||||
|
||||
@@ -83,7 +83,7 @@ export function ForkTreeModal({
|
||||
<Modal isOpen={isOpen} onClose={onClose} title="Save Custom Tree?" footer={footer}>
|
||||
<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 flex-shrink-0 items-center justify-center rounded-full bg-accent">
|
||||
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-accent">
|
||||
<GitFork className="h-5 w-5 text-foreground" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -107,7 +107,7 @@ export function ForkTreeModal({
|
||||
placeholder="My Custom Tree"
|
||||
className={cn(
|
||||
'w-full 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'
|
||||
'focus:outline-hidden focus:border-primary focus:ring-1 focus:ring-primary/20'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
@@ -124,7 +124,7 @@ export function ForkTreeModal({
|
||||
rows={3}
|
||||
className={cn(
|
||||
'w-full 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',
|
||||
'focus:outline-hidden focus:border-primary focus:ring-1 focus:ring-primary/20',
|
||||
'resize-none'
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -33,7 +33,7 @@ export function SaveSessionAsTreeModal({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm">
|
||||
<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">
|
||||
{/* Header */}
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
@@ -70,7 +70,7 @@ export function SaveSessionAsTreeModal({
|
||||
className={cn(
|
||||
'w-full rounded-md 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',
|
||||
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20',
|
||||
'disabled:opacity-50'
|
||||
)}
|
||||
/>
|
||||
@@ -91,7 +91,7 @@ export function SaveSessionAsTreeModal({
|
||||
className={cn(
|
||||
'w-full rounded-md 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',
|
||||
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20',
|
||||
'disabled:opacity-50'
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -141,7 +141,7 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
|
||||
{/* Mobile backdrop */}
|
||||
{!isCollapsed && (
|
||||
<div
|
||||
className="fixed inset-0 z-30 bg-black/80 backdrop-blur-sm sm:hidden"
|
||||
className="fixed inset-0 z-30 bg-black/80 backdrop-blur-xs sm:hidden"
|
||||
onClick={() => setIsCollapsed(true)}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
@@ -203,7 +203,7 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
|
||||
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',
|
||||
'focus:outline-none focus:ring-0'
|
||||
'focus:outline-hidden focus:ring-0'
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -102,7 +102,7 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
|
||||
className={cn(
|
||||
'w-full rounded-md border border-border bg-card py-2 pl-9 pr-3',
|
||||
'text-foreground placeholder:text-muted-foreground',
|
||||
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20'
|
||||
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
@@ -118,7 +118,7 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
|
||||
className={cn(
|
||||
'w-full rounded-md border border-border bg-card py-2 pl-9 pr-3',
|
||||
'text-foreground placeholder:text-muted-foreground',
|
||||
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20'
|
||||
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
@@ -129,7 +129,7 @@ export function SessionFilters({ filters, onChange, onClear, trees }: SessionFil
|
||||
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-none focus:ring-1 focus:ring-primary/20',
|
||||
'text-foreground focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20',
|
||||
'sm:min-w-[200px]'
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -111,7 +111,7 @@ export function SessionOutcomeModal({
|
||||
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',
|
||||
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20'
|
||||
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
@@ -126,7 +126,7 @@ export function SessionOutcomeModal({
|
||||
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',
|
||||
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20'
|
||||
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -135,7 +135,7 @@ export function SessionTimeline({
|
||||
{decisions.map((decision, index) => (
|
||||
<div key={index} className="ml-1 border-l-2 border-border pl-6">
|
||||
<div className="relative">
|
||||
<span className="absolute -left-[1.625rem] top-1 h-2 w-2 rounded-full bg-muted-foreground" />
|
||||
<span className="absolute -left-6.5 top-1 h-2 w-2 rounded-full bg-muted-foreground" />
|
||||
<div className="bg-card border border-border rounded-xl p-4">
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
<div className="flex-1">
|
||||
|
||||
@@ -181,7 +181,7 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
||||
{/* Backdrop */}
|
||||
<div
|
||||
className="absolute inset-0 bg-black/80 backdrop-blur-sm"
|
||||
className="absolute inset-0 bg-black/80 backdrop-blur-xs"
|
||||
onClick={onClose}
|
||||
/>
|
||||
|
||||
@@ -265,7 +265,7 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
|
||||
placeholder="e.g. Training link, Customer escalation"
|
||||
className={cn(
|
||||
'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground placeholder-muted-foreground',
|
||||
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20'
|
||||
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20'
|
||||
)}
|
||||
maxLength={100}
|
||||
/>
|
||||
@@ -299,8 +299,8 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
|
||||
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',
|
||||
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20',
|
||||
'[color-scheme:dark]'
|
||||
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20',
|
||||
'scheme-dark'
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -76,7 +76,7 @@ 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">
|
||||
<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>
|
||||
<div className="max-h-[600px] overflow-y-auto py-2">
|
||||
|
||||
@@ -77,7 +77,7 @@ export function StepRatingModal({
|
||||
const getRating = (stepId: string) => ratings.get(stepId)
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm p-4">
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-xs p-4">
|
||||
<div className="bg-card border border-border w-full max-w-2xl max-h-[90vh] flex flex-col rounded-2xl shadow-lg">
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between border-b border-border px-6 py-4">
|
||||
@@ -174,7 +174,7 @@ export function StepRatingModal({
|
||||
className={cn(
|
||||
'w-full rounded-md 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',
|
||||
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20',
|
||||
'disabled:opacity-50'
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -21,7 +21,7 @@ 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-sm">
|
||||
<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">
|
||||
@@ -40,7 +40,7 @@ export function VariablePromptModal({ prompt, onSubmit, onCancel }: VariableProm
|
||||
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-none focus:ring-1 focus:ring-primary/20'
|
||||
'placeholder:text-muted-foreground focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20'
|
||||
)}
|
||||
/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user