build(deps): migrate Tailwind CSS v3.4 → v4

Root-fixes the opacity-modifier seed bug behind R10 S0: the theme colors were
bare `var(--x)` hex with no <alpha-value>, so `bg-accent/40`, `ring-accent/40`,
`border-border/60`, `text-muted/70`, … (~99 sites across 45 files) emitted no
CSS rule at all — latent no-ops. v4 implements the opacity modifier via
`color-mix`, so the modifier now works with the existing hex vars, no per-scheme
token duplication needed.

- `npx @tailwindcss/upgrade`: `@tailwind` directives → `@import "tailwindcss"`,
  JS config → CSS `@theme` (colors, --font-sans, the z-index tokens preserved),
  classname renames (rounded/shadow/blur scale, outline-none→outline-hidden,
  ring→ring-2) across 56 files; PostCSS plugin → @tailwindcss/postcss,
  autoprefixer removed (v4 prefixes for you).
- `@theme` → `@theme inline` (load-bearing): the color vars are redefined at
  runtime under html[data-scheme]/[data-theme]; inline resolves them at the use
  site so per-scheme opacity tints track the active scheme (the shadcn v4 pattern).
- Revert one codemod false-positive: it rewrote the English word "rounded" →
  "rounded-sm" inside a releaseNotes.ts prose sentence.

Gate green: tsc(app+node) / eslint 0-err / prettier / vitest 79 / knip.
Verified in-browser: bg-accent/15 now computes a scheme-tracking color at 0.15
alpha across all 6 schemes × 2 themes; the hand-rolled glass border/shadow/
radius/backdrop-filter render unchanged under v4.
This commit is contained in:
2026-08-08 00:50:05 +02:00
parent 1199bb0eaf
commit 70bda98868
60 changed files with 822 additions and 809 deletions
+4 -4
View File
@@ -90,7 +90,7 @@ export default function Welcome() {
href={REPO_URL}
target="_blank"
rel="noopener noreferrer"
className="group mt-8 flex flex-col items-center gap-x-4 gap-y-2 rounded-2xl border border-accent/25 bg-accent/[0.06] px-5 py-4 text-center sm:flex-row sm:text-left hover:border-accent/50 transition"
className="group mt-8 flex flex-col items-center gap-x-4 gap-y-2 rounded-2xl border border-accent/25 bg-accent/6 px-5 py-4 text-center sm:flex-row sm:text-left hover:border-accent/50 transition"
>
<span className="grid place-items-center w-10 h-10 rounded-xl bg-accent/15 text-accent shrink-0">
<Code2 className="w-5 h-5" />
@@ -213,7 +213,7 @@ function Preview({
if (failed) {
return (
<div className={`glass-card rounded-2xl overflow-hidden ${className ?? ""}`}>
<div className="w-full h-full grid place-items-center bg-gradient-to-br from-accent/10 to-card text-muted text-sm p-6 text-center">
<div className="w-full h-full grid place-items-center bg-linear-to-br from-accent/10 to-card text-muted text-sm p-6 text-center">
{label}
</div>
</div>
@@ -258,7 +258,7 @@ function Lightbox({ src, label, onClose }: { src: string; label: string; onClose
}, [onClose]);
return (
<div
className="fixed inset-0 z-popover grid place-items-center bg-black/80 backdrop-blur-sm p-4 sm:p-8"
className="fixed inset-0 z-popover grid place-items-center bg-black/80 backdrop-blur-xs p-4 sm:p-8"
onClick={onClose}
role="dialog"
aria-modal="true"
@@ -431,7 +431,7 @@ function AuthCard() {
}
const inputCls =
"w-full bg-card border border-border rounded-xl px-3 py-2.5 text-sm outline-none focus:border-accent";
"w-full bg-card border border-border rounded-xl px-3 py-2.5 text-sm outline-hidden focus:border-accent";
const titleKey = TITLE_KEY[mode];
return (