web-components icon indicating copy to clipboard operation
web-components copied to clipboard

WCAG 2.2: Fields should have outline also when focused with mouse

Open knoobie opened this issue 4 years ago • 18 comments

What is the problem?

If you focus a text field or any other field component with the mouse, only the label gets highlighted. If you focus a field with the keyboard the proper "outline" is applied. This behavior has to be present or configure-able for mouse-focusing as well.

WCAG Criteria: 2.4.7 Focus Visible (Level AA)

The current state violates it explicitly, because the highlighting of the default inputs is "turned of".

See Failure of Success Criterion 2.4.7 due to styling element outlines and borders in a way that removes or renders non-visible the visual focus indicator

This describes a failure condition that occurs when the user agent's default visual indication of keyboard focus is turned off or rendered non-visible by other styling on the page without providing an author-supplied visual focus indicator. Turning off the focus indicator instructs the user agent not to present the focus indicator. Other styling may make it difficult to see the focus indicator even though it is present, such as outlines that look the same as the focus outline, or thick borders that are the same color as the focus indicator so it cannot be seen against them.

Some could argue that the "blue" label is a visual focus indicator, but I don't think it's enough.

Browsers

  • [X] Chrome
  • [X] Firefox
  • [X] Safari
  • [X] Safari on iOS
  • [X] Edge

Screen Readers

  • [ ] None
  • [ ] NVDA
  • [ ] JAWS
  • [ ] VoiceOver on MacOS
  • [ ] VoiceOver on iOS

knoobie avatar Oct 21 '21 09:10 knoobie

This is intentional: we only apply outline when focus-ring attribute is set which means field is focused using keyboard.

@jouni WDYT about this? Should we change the behavior, or just document it and mark this as "won't fix"?

web-padawan avatar Oct 21 '21 10:10 web-padawan

I've spoken with our professional accessibility tester and showed her the current https://a11y-vaadin-playground.netlify.app/pages/v22/text-field.html version, her response:

the change in contrast from gray to blue, for example, has a far too low contrast distance and may not even be perceived by the user. With the new WCAG 2.2 there was a new criteria added where focus requirements are specified. 2.4.11 Focus Appearance (Minimum) Additionally, the change in the background color of the faulty field to light red is also insufficiently noticeable

She would highly recommend to already follow the latest WCAG 2.2, It's only a matter of time until the EU updates the law from 2.1 to 2.2.

knoobie avatar Oct 21 '21 11:10 knoobie

I agree it will improve accessibility for all users if the focus outline is visible also when focused with a pointer. Although, it is not required according to WCAG 2.1:

Note that a keyboard focus indicator can take different forms. One common way is a caret within the text field to indicate that the text field has the keyboard focus.

Examples

When text fields receive focus, a vertical bar is displayed in the field, indicating that the user can insert text, OR all of the text is highlighted, indicating that the user can type over the text.

WCAG 2.2 will very likely change this (which is probably what @knoobie’s friend was referring to):

A 1px wide vertical line (such as a blinking cursor) would not pass the size requirement, a text input would need a larger or separate focus indicator.


The main motivation for not showing the outline when focused via pointer, when I made this design decision, was iOS. I haven’t seen any text input focus indicators on it, and can’t find a setting to turn them on.

From there, my rationale was that if you clicked on a field, you know where the focus went.

I realize it makes it more difficult to figure out where the focus if you leave the page/app momentarily and come back to continue where you left off, at least if it’s a large screen with many inputs.

Because of some of these reasons, I’m still considering if we could make small touch devices an exception. But I think I’m close to getting over it, and accepting the outline no matter how a text input is focused.

Note, that Select is an exception, as it does not receive keyboard input. It should only get the outline when focused with the keyboard.

Also, as I type this on a "rich text editor" in GitHub, I suppose we should apply the focus outline to our RTE as well?

jouni avatar Oct 21 '21 18:10 jouni

I suppose we should apply the focus outline to our RTE as well?

Good catch. I will create a separate issue for it.

web-padawan avatar Oct 21 '21 18:10 web-padawan

Thanks @jouni for your throughout response! Yes, I wasn't sure if this is a violation based on the 2.1 wcag (it doesn't feel right, that's why I opened the ticket)

Afterwards I got in touch with our expert and the first thing she mentioned was the newly created criteria from 2.2 wcag which in turn exactly described my "something is not right feeling". :)

From a design perspective I can totally understand why you didn't want to add it in the beginning when you redesigned valo to lumo!

The current design really matches iOS native behavior in apps. But I'm typing currently on my phone and GitHub looks like it has a clearly visible focus for my current input while typing - so yeah, looks like something that should be looked into for V22 or V23 for even better UX :)

knoobie avatar Oct 21 '21 18:10 knoobie

We are about to release beta for Vaadin 22, it's planned for next week. But we can probably consider such UX changes in one of the next majors.

web-padawan avatar Oct 21 '21 19:10 web-padawan

Ideally we would provide some kind of app-wide configuration flag for this, e.g. in the form of a Lumo css property, so that each app could be easily configured to use either the current behavior or the new one.

rolfsmeds avatar Oct 27 '21 13:10 rolfsmeds

Yeah, could be something like --lumo-text-input-pointer-focus-outline: none; to get the current behavior back.

jouni avatar Oct 28 '21 10:10 jouni

Push to hopefully get this on the plate for v24 to make sure the next major is future proof 😉

knoobie avatar Sep 04 '22 18:09 knoobie

@web-padawan for your meeting - this could also add value on the long run to stay ahead for the upcoming WCAG 2.2

knoobie avatar Feb 17 '23 19:02 knoobie

Thanks. I'll add v24.1 label to this issue as well. However, this doesn't necessarily mean it will be included in the project. There's already some kind of a backlog and the top priority is adding HasAriaLabel support to Flow components.

web-padawan avatar Feb 17 '23 20:02 web-padawan

As we are currently making a separation between more abstract --lumo- prefixed style properties for things like general colors, dimensions, typography etc, and more feature-specific --vaadin- prefixed properties, I'd be inclined to include this in the latter category. Thus, a property like --vaadin-focus-ring-always or --vaadin-focus-ring-keyboard-only, depending on which way we want to pose it, would seem appropriate.

And I think this should not be limited to inputs, but to all components consistently.

The value could be a "boolean" set to 0 or 1, and used to enable/disable the focus ring on the plain [focus] state (cf the [focus-ring] state where it's currently applied).

Implementation within components could be something like:

// Existing keyboard-only focus:
:host([focus-ring]) {
    box-shadow: 0 0 0 var(--_focus-ring-width) var(--_focus-ring-color);
}

// Separate block for _any_ focus:
:host([focus]) {
    --_conditional-focus-ring-width: calc(var(--vaadin-focus-ring-always) * var(--_focus-ring-width));
    box-shadow: 0 0 0 var(--_conditional-focus-ring-width) var(--_focus-ring-color);
}

That way, the [focus-ring] state triggered by keyboard focus would always apply a ring, while the generic [focus] state would only render a ring if --vaadin-focus-ring-always is set to 1.

Then we just need to debate whether on or off should be the default.

(We've also discussed whether to entirely replace the current two focus state implementations with native :focus, :focus-within and :focus-visible pseudoclasses, but that would probably require support for :has in some components, which we can't do until V25.)

rolfsmeds avatar Nov 02 '23 15:11 rolfsmeds

I really like this, especially since WCAG 2.2 was published / released last month (https://www.w3.org/TR/WCAG22/)

knoobie avatar Nov 02 '23 15:11 knoobie

The border style variant of input fields adds complexity. Currently in Lumo focus-ring simply overrides the field border. The input field border depends on box-shadow and a desired style might be to add the focus-ring in addition to border. image

I tried to follow the example above by @rolfsmeds and had challenges with making the focus-ring configurable while not affecting the field border.

juuso-vaadin avatar Feb 22 '24 11:02 juuso-vaadin

In our Vaadin Webapp we made all controls (inputs, select, checkbox, etc.) having a black border for a11y reasons. Sadly, the webapp is not yet Vaadin 24.1, so we didn't made use of --vaadin-input-field-border-width and --vaadin-input-field-border-color.

Currently we are thinking about a colored border on focus, regardless of how focus got there. I fear, this might interfere with whatever this issues solution gonna be. Any estimation in which Vaadin version this feature might get published?

AndreasSamjeske avatar Feb 27 '24 12:02 AndreasSamjeske

There are two implementation options mentioned in my comment above. Although the second option would allow us to reduce the amount of code used to manage the focus ring, it would probably be a breaking change that we'd rather avoid, so the first option (in the code snippet) seems the more likely approach to be taken.

Which means that if you implement it along the lines of

:host([focus]) {
    box-shadow: 0 0 0 var(--_focus-ring-width) var(--_focus-ring-color);
}

Or, with light-dom css

[focus]::part(input-field) {
    box-shadow: 0 0 0 var(--_focus-ring-width) var(--_focus-ring-color);
}

That should just happily override the built-in solution once it ships.

Currently no plans on which version to ship it in, however.

rolfsmeds avatar Feb 27 '24 13:02 rolfsmeds

... Which means that if you implement it along the lines of

:host([focus]) {
    box-shadow: 0 0 0 var(--_focus-ring-width) var(--_focus-ring-color);
}

Or, with light-dom css

[focus]::part(input-field) {
    box-shadow: 0 0 0 var(--_focus-ring-width) var(--_focus-ring-color);
}

That should just happily override the built-in solution once it ships.

Currently no plans on which version to ship it in, however.

Two small corrections:

  1. I think it is [focused] not [focus].
  2. the first example sets the focus on vaadin-text-field (including label, helpertext, etc.) So, this might be more suitable: :host([focused]) [part="input-field"]{ box-shadow: 0 0 0 var(--_focus-ring-width) var(--_focus-ring-color); }

Since I wanted this for checkbox, too, I ended up with

[focused]::part(input-field), [focused]::part(checkbox)
{
    box-shadow: 0 0 0 var(--_focus-ring-width) var(--_focus-ring-color);
}

AndreasSamjeske avatar Mar 06 '24 16:03 AndreasSamjeske

After diving a bit deeper into this my understanding is that WCAG 2.2 doesn't really change the principles on when focus-ring should be displayed. WCAG 2.2 does better define SC 2.4.13 Focus appearance (AAA) while guidelines on when focus should be displayed remain unchanged SC 2.4.7 Focus visible.

@knoobie had a valid point when opening this ticket. Hiding the original focus outline without providing an equivalent replacement violates SC 2.4.7 due to F78. This is the case already in WCAG 2.1.

The adjustments would be required for native HTML input elements that originally show focus-ring on click. These include text-based inputs such as <input type=“text”>, <input type=“number”> and also <select>. But not <input type=“checkbox”>, <input type=“radio”> or <button>.

juuso-vaadin avatar Mar 07 '24 13:03 juuso-vaadin