Skip to content

fix: restore input focus ring (patch tailwindcss-react-aria-components not-* variants)#172

Merged
mehdibha merged 2 commits into
mainfrom
claude/strange-matsumoto-0465af
Jun 4, 2026
Merged

fix: restore input focus ring (patch tailwindcss-react-aria-components not-* variants)#172
mehdibha merged 2 commits into
mainfrom
claude/strange-matsumoto-0465af

Conversation

@mehdibha
Copy link
Copy Markdown
Owner

@mehdibha mehdibha commented Jun 4, 2026

The regression

Focused text inputs stopped showing the blue focus ring (and the blue focus border). This regressed when the vendored react-aria was swapped for the official packages, which brought a newer tailwindcss-react-aria-components plugin.

Root cause

The input's focus styles depend on the not-invalid: variant:

focus:not-invalid:border-border-focus   // blue focus border
focus:not-invalid:ring-border-focus-muted // blue ring color

The tailwindcss-react-aria-components plugin emits each native state variant (invalid, focus, disabled, …) as two sibling rules — one for React-Aria elements and one for the native pseudo-class:

.invalid\:… {
  &:where([data-rac])[data-invalid] { … }
  &:where(:not([data-rac])):invalid  { … }
}

Tailwind's not-* compound walker bails out on variants that produce more than one rule, so every not-invalid: utility silently emitted no CSS. Confirmed against the live stylesheet: invalid: → 10 rules, not-invalid:0 rules. With no focus:not-invalid:* rules, the focused input had no focus border and --tw-ring-color was never set → no ring.

The fix

Patch the plugin (pnpm patch) to collapse the two branches into a single :is() selector, so not-* negation works again:

return `&:is(:where([data-rac])${baseSelector}, :where(:not([data-rac]))${nativeSelector})`;

:where() keeps specificity at (0,1,0), so the cascade is unchanged. Hover keeps its @media (hover: hover) wrapper (its not-hover: stays unsupported, matching native Tailwind). This backports adobe/react-spectrum#9974.

Verification

After patching, with real keyboard focus (foreground browser, since a backgrounded tab drops react-aria focus state):

state border-color box-shadow
unfocused rgb(55,55,62) (grey field) none
focused rgb(59,122,186) (focus blue) rgb(35,74,112) 0 0 0 2px (2px blue ring)

not-invalid: rules in the compiled CSS: 0 → 6.

CI (all green locally)

  • pnpm lint:ws · ✅ pnpm check · ✅ pnpm typecheck · ✅ pnpm test · ✅ pnpm build:registry (no drift)

Notes

  • www/src/registry/ui/input/styles.ts has a second commit applying oxfmt's class ordering — pre-existing formatting drift on main that oxfmt --check flags. Reordering Tailwind classes in the source string is behavior-neutral (Tailwind decides precedence by its own internal sort). Split out so it's easy to see it's unrelated to the fix.
  • Consumers of the published registry will need the same upstream fix (or this patch) for not-invalid: to work in their own Tailwind build, until tailwindcss-react-aria-components ships the fix.

🤖 Generated with Claude Code

mehdibha and others added 2 commits June 4, 2026 01:37
…onents

The plugin emits native state variants (invalid, focus, disabled, …) as two
sibling rules — one for RAC elements ([data-rac][data-invalid]) and one for the
native pseudo-class (:not([data-rac]):invalid). Tailwind's not-* compound walker
bails out on multi-rule variants, so every not-invalid: utility silently emitted
no CSS.

The input field relies on focus:not-invalid:border-border-focus and
focus:not-invalid:ring-border-focus-muted, so focused inputs lost their blue
focus border and ring after the move to the official react-aria packages.

Patch getSelector to collapse the two branches into a single :is() selector,
keeping specificity at (0,1,0) via :where(), so not-* negation works again.
Backports adobe/react-spectrum#9974.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pre-existing formatting drift flagged by oxfmt --check; reordering Tailwind
classes in the source string is behavior-neutral (Tailwind decides precedence
by its own internal sort, not class-attribute order). Keeps CI green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 4, 2026

⚠️ No Changeset found

Latest commit: 88c689d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
dotui Ready Ready Preview, Comment Jun 4, 2026 12:39am

@mehdibha mehdibha merged commit 201aa6c into main Jun 4, 2026
10 checks passed
@mehdibha mehdibha deleted the claude/strange-matsumoto-0465af branch June 4, 2026 00:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant