feat(deps): Tailwind 3 → 4 + swap tailwindcss-animate for tw-animate-css
Ran the official @tailwindcss/upgrade tool: - tailwind.config.ts → @theme directive in globals.css - @tailwind base/components/utilities → @import 'tailwindcss' - postcss.config switched from tailwindcss + autoprefixer to @tailwindcss/postcss (autoprefixer baked in) - focus-visible:outline-none → focus-visible:outline-hidden (the v3 utility was a footgun — outline still showed in forced-colors mode) Reverted the migration tool's over-zealous variant="outline" → variant="outline-solid" rename on CVA prop values; that rename was meant for the Tailwind `outline:` utility, not our Button/Badge component variants. Swapped tailwindcss-animate (v3-style JS plugin) for tw-animate-css (v4-native @import). Same utility surface (animate-spin, animate-in, etc.), one fewer JS plugin in the bundle. Fixed the upgrade tool's malformed dark variant (@custom-variant dark (&:is(class *)) — `class` was being parsed as a tag) to canonical &:where(.dark, .dark *). Verified: tsc 0 errors, eslint 0 errors (16 pre-existing warnings), vitest 1315/1315, next build clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -291,7 +291,7 @@ export function CommandSearch() {
|
||||
// Wrapper border swap is the focus indicator; suppress the
|
||||
// global *:focus-visible ring that would otherwise paint a
|
||||
// rectangular box clashing with the rounded wrapper.
|
||||
className="h-9 flex-1 min-w-0 bg-transparent text-sm outline-none ring-0 focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 placeholder:text-muted-foreground"
|
||||
className="h-9 flex-1 min-w-0 bg-transparent text-sm outline-hidden ring-0 focus:outline-hidden focus:ring-0 focus-visible:outline-hidden focus-visible:ring-0 focus-visible:ring-offset-0 placeholder:text-muted-foreground"
|
||||
/>
|
||||
{isFetching && query.length >= 2 && (
|
||||
<span
|
||||
|
||||
@@ -35,10 +35,7 @@ export function HighlightMatch({
|
||||
if (i % 2 === 1) {
|
||||
// The capture group lands on odd indices.
|
||||
return (
|
||||
<mark
|
||||
key={i}
|
||||
className="bg-brand/15 text-foreground rounded-[2px] px-[1px] font-medium"
|
||||
>
|
||||
<mark key={i} className="bg-brand/15 text-foreground rounded-[2px] px-px font-medium">
|
||||
{part}
|
||||
</mark>
|
||||
);
|
||||
|
||||
@@ -198,7 +198,7 @@ export function MobileSearchOverlay({ open, onOpenChange }: MobileSearchOverlayP
|
||||
repositionInputs={false}
|
||||
>
|
||||
<VaulDrawer.Portal>
|
||||
<VaulDrawer.Overlay className="fixed inset-0 z-50 bg-black/30 backdrop-blur-sm" />
|
||||
<VaulDrawer.Overlay className="fixed inset-0 z-50 bg-black/30 backdrop-blur-xs" />
|
||||
<VaulDrawer.Content
|
||||
// Anchor by top + explicit height (not bottom: 0). iOS treats
|
||||
// `bottom: 0` on position:fixed inconsistently when the
|
||||
@@ -252,7 +252,7 @@ export function MobileSearchOverlay({ open, onOpenChange }: MobileSearchOverlayP
|
||||
autoCorrect="off"
|
||||
spellCheck={false}
|
||||
className={cn(
|
||||
'ml-2 h-full w-full min-w-0 bg-transparent text-base outline-none',
|
||||
'ml-2 h-full w-full min-w-0 bg-transparent text-base outline-hidden',
|
||||
'placeholder:text-muted-foreground',
|
||||
)}
|
||||
/>
|
||||
@@ -283,7 +283,7 @@ export function MobileSearchOverlay({ open, onOpenChange }: MobileSearchOverlayP
|
||||
matter the phone width. "All" is sticky-left so it's always
|
||||
one tap away when the user is deep in a bucket. */}
|
||||
<div className="border-b pb-3">
|
||||
<div className="flex gap-1.5 overflow-x-auto px-4 [-webkit-overflow-scrolling:touch] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden">
|
||||
<div className="flex gap-1.5 overflow-x-auto px-4 [-webkit-overflow-scrolling:touch] scrollbar-none [&::-webkit-scrollbar]:hidden">
|
||||
<BucketChip
|
||||
label="All"
|
||||
active={activeBucket === 'all'}
|
||||
|
||||
Reference in New Issue
Block a user