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:
chihlasm
2026-03-07 22:10:44 -05:00
committed by GitHub
parent 732ccba966
commit d365c38b61
137 changed files with 1922 additions and 1709 deletions

View File

@@ -45,7 +45,7 @@ export function OpenSessions({ sessions }: OpenSessionsProps) {
{session.stepNumber && session.totalSteps
? `Step ${session.stepNumber} of ${session.totalSteps}`
: 'In progress'}
<span className="mx-1.5 text-[hsl(var(--text-dimmed))]">&middot;</span>
<span className="mx-1.5 text-[var(--text-dimmed)]">&middot;</span>
<span className="font-label text-[0.625rem]">{session.timeAgo}</span>
</div>
</div>

View File

@@ -21,7 +21,7 @@ export function QuickStats({ stats }: QuickStatsProps) {
className={cn('glass-card p-4 fade-in', i === 0 && 'active-glow')}
style={{ animationDelay: `${50 + i * 30}ms` }}
>
<p className="font-label text-[0.625rem] font-medium uppercase tracking-[0.1em] text-muted-foreground">
<p className="font-label text-[0.625rem] font-medium uppercase tracking-widest text-muted-foreground">
{stat.label}
</p>
<p
@@ -35,7 +35,7 @@ export function QuickStats({ stats }: QuickStatsProps) {
{stat.value}
</p>
{stat.meta && (
<p className="mt-0.5 text-[0.6875rem] text-[hsl(var(--text-dimmed))]">{stat.meta}</p>
<p className="mt-0.5 text-[0.6875rem] text-[var(--text-dimmed)]">{stat.meta}</p>
)}
</div>
))}

View File

@@ -64,7 +64,7 @@ export function SessionsPanel({ sessions, delay = 200 }: SessionsPanelProps) {
</span>
{/* Time */}
<span className="text-right text-[0.6875rem] text-[hsl(var(--text-dimmed))]">
<span className="text-right text-[0.6875rem] text-[var(--text-dimmed)]">
{session.timeAgo}
</span>
</Link>

View File

@@ -33,7 +33,7 @@ export function TreeListItem({
return (
<div
onClick={() => navigate(getTreeNavigatePath(id, treeType))}
className="group grid cursor-pointer items-center gap-3 rounded-lg border border-transparent bg-card px-4 py-3 transition-colors hover:border-border hover:bg-[hsl(var(--sidebar-hover))]"
className="group grid cursor-pointer items-center gap-3 rounded-lg border border-transparent bg-card px-4 py-3 transition-colors hover:border-border hover:bg-[var(--sidebar-hover)]"
style={{ gridTemplateColumns: '40px 1fr 130px 80px 100px 40px' }}
>
{/* Icon box */}
@@ -75,7 +75,7 @@ export function TreeListItem({
</div>
{/* Updated */}
<div className="text-right text-[0.6875rem] text-[hsl(var(--text-dimmed))]">
<div className="text-right text-[0.6875rem] text-[var(--text-dimmed)]">
{timeAgo}
</div>

View File

@@ -56,7 +56,7 @@ export function WeeklyCalendar({ events = {} }: WeeklyCalendarProps) {
borderBottom: day.isToday ? '2px solid #06b6d4' : '1px solid var(--glass-border)',
}}
>
<span className={`font-label text-[0.625rem] uppercase tracking-[0.1em] ${day.isToday ? 'text-cyan-400' : 'text-muted-foreground'}`}>
<span className={`font-label text-[0.625rem] uppercase tracking-widest ${day.isToday ? 'text-cyan-400' : 'text-muted-foreground'}`}>
{day.label}
</span>
<div className={`text-sm font-heading font-bold ${day.isToday ? 'text-foreground' : 'text-muted-foreground'}`}>
@@ -65,7 +65,7 @@ export function WeeklyCalendar({ events = {} }: WeeklyCalendarProps) {
</div>
<div className="flex-1 overflow-y-auto p-1.5 space-y-1">
{dayEvents.length === 0 ? (
<p className="text-[0.625rem] text-[hsl(var(--text-dimmed))] text-center py-2">No events</p>
<p className="text-[0.625rem] text-[var(--text-dimmed)] text-center py-2">No events</p>
) : (
dayEvents.map(event => (
<div