Open zelliott opened 3 years ago
It seems that the suggested solution in #211 also works for your use case. With a hint for input modality on the body or root element, you can use something like below:
[data-interaction-mode="keyboard"] .my-option-element.is-active {
/* focus styles */
}
Motivation
I work on an app that renders highly visible focus indicators on keyboard input modality and subtle/no focus indicators on all other input modalities. We accomplish this today with a global singleton service that listens to focus events as well as keydown/mouse/touch/pointer events, and attempts to attribute the focus events to the appropriate input modalities. The service adds a CSS class with the current modality (e.g.
.keyboard-focused
) to thebody
, which then we can reference in our CSS styles. We do this instead of using:focus-visible
because:focus-visible
didn't have the requisite cross-browser support... although it looks like this may change soon.However, one use case that
:focus-visible
(as well as this polyfill) does not support isaria-activedescendant
. Consider the following use case:Suppose I have a simple ARIA combobox where focus remains on the combobox text input and "focus/selection" is moved among the various
[role="option"]
elements within the combobox witharia-activedescendant
. Suppose the combobox moves some class.is-active
among theoption
elements in accordance with focus/selection (for styles that show whichoption
is active). I'd like to render highly visible (i.e. conforming to all WCAG contrast requirements) "focus" indicators on the activeoption
elements only on keyboard input modality. On other input modalities, I'd like to render a more subtle focus indication.This isn't really possible with
:focus-visible
today (nor this polyfill).aria-activedescendant
elements are of course not actually focused, so I can't write styles like.my-option-element.is-active:focus-visible { ... }
.aria-activedescendant
elements are also not guaranteed to be a DOM descendant of the focused element (e.g. the combobox case), so I can't write styles like.my-focused-element:focus-visible .my-option-element.is-active { ... }
.Solutions
One potential solution I've seen as a CSS proposal to to expose a user's input modality (potentially via media queries)... but it seems like it isn't seeing a lot of action these days.
Another potential solution is some kind of
:focus-visible-within
selector (mentioned in https://github.com/WICG/focus-visible/issues/151). If this selector existed, I could attach it to thebody
, and write styles like:body:focus-visible-within .my-option-element.is-active { ... }
. Basically,:focus-visible-within
would be identical to the.keyboard-focused
global class I'm currently using in my app.I'm curious what the members of this community think about this use case. Happy to spin up a demo if it helps facilitate discussion.