Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Component: Button: disabled button state is very low contrast #26982

Closed
ryelle opened this issue Aug 31, 2018 · 18 comments · Fixed by #33355
Closed

Component: Button: disabled button state is very low contrast #26982

ryelle opened this issue Aug 31, 2018 · 18 comments · Fixed by #33355

Comments

@ryelle
Copy link
Member

ryelle commented Aug 31, 2018

The disabled button state is very low contrast, and can seem almost invisible. The following screenshot is from devdocs, where the disabled button text vs background color contrast is 1.2.

There is no WCAG requirement for disabled elements on a page, but I might suggest aiming for a ratio of 3.0+ anyway. We are trying to show the user something, even if it's not currently actionable.

cc-ing @drw158 @cburton4 for color/design systems work

@davewhitley
Copy link
Contributor

Ok we will look to Material for guidance and see what their disabled state looks like.

@simison
Copy link
Member

simison commented Mar 18, 2019

Similar issues with disabled text inputs and probably other form elements, too:

image

https://webaim.org/resources/contrastchecker/?fcolor=B0B5B8&bcolor=F6F6F6

image

See e.g. WordPress version input for Jetpack-connected sites at https://wordpress.com/settings/general:

image

@simison
Copy link
Member

simison commented Mar 18, 2019

Another similarly poor colour contrast element is in pagination component:

image

The text is so invisible even for healthy eye & good monitor that we might as well hide the whole button instead of disabling it. 😁

@Aurorum
Copy link
Contributor

Aurorum commented Mar 18, 2019

I looked at this yesterday, -neutral-400 is the only one that passes 3+ contrast, but I feel that seems too much like an ordinary button than a disabled one.

@flootr
Copy link
Contributor

flootr commented Mar 18, 2019

@ryelle already mentioned this in the comment above but I'm adding the relevant WCAG document for reference: https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html

1.4.3 Contrast (Minimum): The visual presentation of text and images of text has a contrast ratio of at least 4.5:1, except for the following: (Level AA)

  • Large Text: Large-scale text and images of large-scale text have a contrast ratio of at least 3:1;

  • Incidental: Text or images of text that are part of an inactive user interface component, that are pure decoration, that are not visible to anyone, or that are part of a picture that contains significant other visual content, have no contrast requirement.

  • Logotypes: Text that is part of a logo or brand name has no minimum contrast requirement.

/cc @drw158

@flootr
Copy link
Contributor

flootr commented Mar 18, 2019

For visualization and reference here's what the different shades of gray look like up to -neutral-400:

Screenshot 2019-03-18 at 10 15 21

Screenshot 2019-03-18 at 10 16 26

Screenshot 2019-03-18 at 10 17 00

Screenshot 2019-03-18 at 10 17 28

Screenshot 2019-03-18 at 10 17 54

@davewhitley
Copy link
Contributor

I've taken a look at a few design systems (including gov.uk) and the disabled text contrast is anywhere from 1.5 to 2.5.

Can we compromise and use neutral-200? That is about a 2.0 contrast ratio. I feel good about that since the systems I looked at are very a11y focused.

If there is a consensus, then I propose that we meet a 2.0 contrast ratio for a disabled elements (by using the 200 value colors), not just buttons.

@simison Some of the elements to mention should obviously not be a text input (why would the version number be a text input?). Some, like the Previous disabled button in the pagination component is ok. I wouldn't hide the button because it can cause the layout to jump and cause the user to move the mouse more or cause confusion about why elements are moving. Yes, the element already jumps around a lot, but it would jump even more :)

@ryelle
Copy link
Member Author

ryelle commented Mar 18, 2019

If there is a consensus, then I propose that we meet a 2.0 contrast ratio for a disabled elements (by using the 200 value colors), not just buttons.

👍 for setting a contrast min for disabled elements, but IMO the 300s give a clearer contrast while still looking disabled (2.8 against white). The disabled text input is probably where a better contrast is most important - you're trying to communicate info to the user, even if they can't edit it. neutral-200 only has a contrast of 1.9 against that background color, while 300 has 2.6 against the input background (note that I am just color-picking based off these screenshots).

@davewhitley
Copy link
Contributor

There are 2 issues I see here:

  1. Disabled button text should be a bit higher contrast. I still feel like the 200 value (against white) is the best balance of not looking enabled, vs looking disabled (but still somewhat readable). I feel confident that our 2.07 contrast (with neutral-200) is in line with strict a11y standards, considering usa.gov, gov.au, and gov.uk all have disabled text contrast ranging from 1.5 – 2.0 (we would be on the high end of the spectrum).

  2. Disabled inputs are being used to convey information that is meant to be read. Important info should not be placed in a disabled input because disabled elements are not meant to be legible.

I say we fix issue 1 first and then figure something out for issue 2 (probably in a separate issue/PR)

@ryelle
Copy link
Member Author

ryelle commented Mar 19, 2019

I feel confident that our 2.07 contrast (with neutral-200) is in line with strict a11y standards,

There actually aren't standards for disabled elements, which is why none of them are consistent. "Text or images of text that are part of an inactive user interface component […] have no contrast requirement." – you'd be creating a standard for a8c to use.

Disabled inputs are being used to convey information that is meant to be read. Important info should not be placed in a disabled input because disabled elements are not meant to be legible.

Yeah, this info shouldn't be in disabled inputs (I think screen readers skip over disabled inputs, so they're not reading out the values either). I'm not sure I agree with "disabled elements are not meant to be legible", but maybe people overuse disabled elements in general 🤷🏼‍♀️

@keoshi
Copy link
Contributor

keoshi commented Mar 19, 2019

Came here from @simison's comment on #31550 and using this comment to subscribe to this issue as I'm interested in collaborating and helping improving this.

Putting aside the philosophy or validity of using a disabled field over something else, I still think there's value in improving their readability in the short term. In that sense @drw158's suggestion of using the neutral-200 seems like a great improvement to disabled inputs/buttons.

Whether or not we should be using disabled inputs/buttons is a much bigger discussion, because it will depend on the context of each of them. While it might not make sense to have disabled buttons as a principle, it certainly makes sense to use them in our Jetpack flow as it exists in an interstitial/loading state and prevents people from submitting a site URL more than once. That doesn't mean there isn't a better UX pattern to make that state obvious, just contextualizing our current usage according to the existing patterns.

Also, leaving here the Material guidelines on disabled states: https://material.io/design/interaction/states.html#disabled

Please, let me know how I can help.

@davewhitley
Copy link
Contributor

davewhitley commented Mar 19, 2019

There actually aren't standards for disabled elements, which is why none of them are consistent.

"Standard" is probably the wrong word on my part. I didn't mean the WCAG standard, but the unofficial threshold of what is acceptable with regards to text contrast for disabled elements. The design systems I mentioned are required to adhere to strict standards of a11y, so I looked to them for guidance.

I agree that ppl (myself included) have misused disabled elements within Calypso and the web in general.

Here's a lively debate on the W3C github w3c/wcag21#805

@simison
Copy link
Member

simison commented Mar 20, 2019

Maybe we need a different kind of disabled button which also communicates "wait, loading something"? Here's an example from Mailchimp signup form:

image

First, the disabled state is when we don't really need to know what it says on the button and we haven't yet filled the form.

Then we've filled the form.

And finally, we're waiting for the form to send. There's a spinning animation. I think the background colour is the same as focus-state for a regular button.

This could even be componentized so that people would always use it correctly and we could easily add aria live regions to loading state so that folks wouldn't need to implement them each time again:

<FormSubmit
   validForm={ true } // false = disabled button, show `invalidLabel`. True = regular button, show `label`.
   busy={ false } // true = show `busyLabel` and loading spinner. Don't allow clicks
   label={ translate( 'Get started!') }
   invalidLabel={ translate( 'Fill the form to get started!') } // when undefined defaults to `label`
   busyLabel={ translate( 'Please wait...') }
/>

@keoshi
Copy link
Contributor

keoshi commented Mar 20, 2019

Based on @simison ideas above, I've created a quick prototype to show how we could still use the disabled param in tandem with an additional class, to have the best of both options. See it live here: https://codepen.io/keoshi/full/bZxPrP

button-disabled-states-demo-2

Highlights:

  • The button with the disabled state is not relevant until additional information has been entered. This (missing) information should be indicated by the elements that require it on a case-by-case (in this scenario: a single input).
  • Only the normal state supports pointer events and hover/focus styles.
  • The “processing” state can have different visuals indicating progress, but without being vital to the interpretation of the state or readable by screen readers. In practice, this means using a disabled button with an additional class.

@Aurorum
Copy link
Contributor

Aurorum commented Mar 20, 2019

I'm not sure I follow. Just looking at that GIF, would that be in replacement for the disabled button altogether? If so, just a few points:

  • What would be the replacement to the standard secondary button, which currently looks like the disabled button in that concept? Both of them next to each other feels odd
  • With most cases currently, most of the time the disabled state turns to a primary button, isn't that fairly similar to the concept?

Examples of both of these are the Accounts Settings page.

Maybe I'm missing something, but if that's a separate button, then the colour contrast still needs to be decided anyway.

@keoshi
Copy link
Contributor

keoshi commented Mar 21, 2019

@torres126 I used different stylings on my demo for illustrative purposes only. I wasn't trying to compare or create new styles for Calypso, but rather get my point across using a more obvious pattern.

Please don't get too hung up on the disabled styling either; those are there simply to demonstrate that an extra layer — the “processing” state — could still be achieved by using the disabled attribute in inputs/buttons along with an additional class.

We currently have a “processing” state which we call a “busy” state (see it in the devdocs), but it doesn't use the disabled attribute. This means the button state must be controlled by JS (to avoid submitting its respective form more than once, for example), rather than relying on a standard implemented in all browsers.

@Aurorum
Copy link
Contributor

Aurorum commented Mar 21, 2019

Got it, thanks! :)

@davewhitley
Copy link
Contributor

@keoshi this looks great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants