Repository navigation
The focus concept emits :focus-within in Web Components and :focus-visible in React #754
Description
Problem
The same declared state concept produces a different CSS selector in React than in Web Components, and the documentation presents one of them as the contract.
A library declaring the focus concept gets:
- React —
:focus-visible, which is what the settings reference documents. - Web Components —
:focus-within, and no:focus-visibleanywhere.
Measured on one library's emitted output from a single run with one config: 41 occurrences of :focus-visible across the React stylesheets, 41 occurrences of :focus-within across the Web Components stylesheets, and zero of the other in each.
These are not equivalent. :focus-within matches while focus sits anywhere inside the element, including after a mouse click; :focus-visible matches only when the browser decides a focus ring is warranted. A library that declared focus and verified it in React gets visibly different behaviour on the Web Components side — a focus ring appearing on click where it should not — and nothing says so.
The concept table also offers focus-within as a separate concept, which is what someone would declare if they wanted that behaviour. So on the Web Components side, declaring either concept appears to produce the same result, which makes one of them unreachable.
Potential solution(s)
- Make the Web Components emitter match the documented concept, so
focusemits:focus-visiblenarrowed the way the React side narrows it, andfocus-withinstays the way to ask for:focus-within. - If the divergence is deliberate — because a shadow root changes what a focus selector can reach — document it on the states settings page as a per-platform difference, and say which concept to declare for which result on each platform. Right now the page reads as one contract for both.
Acceptance criteria
- Declaring
focusproduces the same focus semantics in both emitted trees, or the difference is documented on the states settings page with the reason. - Declaring
focusand declaringfocus-withinproduce different output on the Web Components side, so both concepts are reachable. - The states settings page's selector table is true of every platform it covers, or names the platform each row applies to.
Case data
- Fixture: Checkbox, Text field, Toggle — any component whose focus styling sits on a wrapper rather than the control
- Workspace: atlassian, during a from-scratch onboarding run; surfaced while verifying that a configured
statesblock reached the emitted CSS - Territory: react-from-specs, webcomponents-from-specs, docs
- Impacted file(s): the focus-concept selector emission in
webcomponents-from-specs,from-specs/src/states.tsif the narrowing is shared,site/src/content/docs/settings/states.md - Size: s to m
Related Docs
Notes
Found by verifying every row of a configured states block against both emitted trees rather than sampling one. Nine of eleven concepts emitted identically on both platforms; this was the only divergence.
Implementation details are tracked internally.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Projects
- StatusShow more project fieldsBacklog
Activity