Skip to content

Support the :focus-within pseudo-class - #615

Open
maurerdietmar wants to merge 2 commits into
DioxusLabs:mainfrom
maurerdietmar:focus-within
Open

Support the :focus-within pseudo-class#615
maurerdietmar wants to merge 2 commits into
DioxusLabs:mainfrom
maurerdietmar:focus-within

Conversation

@maurerdietmar

@maurerdietmar maurerdietmar commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Selector matching for :focus-within was stubbed to false and no element state was maintained for it, so styles keyed on it (a common pattern for form field focus rings, where the visible border lives on a wrapper around the input) never applied.

Track ElementState::FOCUS_WITHIN on the focused element and all of its ancestors, using the same ancestor-path diffing as hover so a focus move only restyles the non-shared parts of the two chains. Cleared on refocus, clear_focus, and removal of the focused node.

WPT results

No changes in test results compared to main.

Generated by the WPT workflow.

@nicoburns nicoburns left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to use regular ancestors (node.parent) rather than layout ancestors (node.layout_parent) as focus pertains to the DOM elements tree rather than the layout tree.

This also needs to handle updating :focus-within when an element is moved within the tree.

compare_document_order builds root-first DOM ancestor chains with a
private helper. Interaction state updates need the same walk, so give
it a public name next to node_layout_ancestors, an Option-taking
variant, and tolerance for freed slots via get_node, matching
nearest_surviving_element_ancestor.

Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
Selector matching for :focus-within was stubbed to false and no
element state was maintained for it, so styles keyed on it (a common
pattern for form field focus rings, where the visible border lives on
a wrapper around the input) never applied.

Track ElementState::FOCUS_WITHIN on the focused element and all of
its DOM ancestors, using the same ancestor-path diffing as hover so a
focus move only restyles the non-shared parts of the two chains. The
DOM chain rather than the layout chain, because focus pertains to the
DOM tree: the layout chain skips display: contents ancestors, and its
links do not exist before the first layout pass, which is when
autofocus fires.

The state follows tree changes around the focused node: it is cleared
on refocus, clear_focus and removal, and transferred from the old
ancestor chain to the new one when a subtree containing the focus is
moved to a different parent, including out of the document.

Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants