ui icon indicating copy to clipboard operation
ui copied to clipboard

Accessibility: Contrast issues with primary buttons for certain colors (e.g. pink, red etc.), checkbox is not accessible

Open janhesters opened this issue 1 year ago • 4 comments

Contrast needs to be 4.5 or higher: https://dequeuniversity.com/rules/axe/4.8/color-contrast

Checkbox lacks a title: https://dequeuniversity.com/rules/axe/4.8/button-name?application=playwright

Contrast

Red:

+             "data": Object {
+               "bgColor": "#dc2626",
+               "contrastRatio": 4.41,
+               "expectedContrastRatio": "4.5:1",
+               "fgColor": "#fef2f2",
+               "fontSize": "10.5pt (14px)",
+               "fontWeight": "normal",
+               "messageKey": null,
+             },

Pink:

+             "data": Object {
+               "bgColor": "#e11d48",
+               "contrastRatio": 4.27,
+               "expectedContrastRatio": "4.5:1",
+               "fgColor": "#fff1f2",
+               "fontSize": "10.5pt (14px)",
+               "fontWeight": "normal",
+               "messageKey": null,
+             },

There might be more issues with other colors.

Checkbox

+ Array [
    +   Object {
    +     "description": "Ensures buttons have discernible text",
    +     "help": "Buttons must have discernible text",
    +     "helpUrl": "https://dequeuniversity.com/rules/axe/4.8/button-name?application=playwright",
    +     "id": "button-name",
    +     "impact": "critical",
    +     "nodes": Array [
    +       Object {
    +         "all": Array [],
    +         "any": Array [
    +           Object {
    +             "data": null,
    +             "id": "button-has-visible-text",
    +             "impact": "critical",
    +             "message": "Element does not have inner text that is visible to screen readers",
    +             "relatedNodes": Array [],
    +           },
    +           Object {
    +             "data": null,
    +             "id": "aria-label",
    +             "impact": "critical",
    +             "message": "aria-label attribute does not exist or is empty",
    +             "relatedNodes": Array [],
    +           },
    +           Object {
    +             "data": null,
    +             "id": "aria-labelledby",
    +             "impact": "critical",
    +             "message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty",
    +             "relatedNodes": Array [],
    +           },
    +           Object {
    +             "data": Object {
    +               "messageKey": "noAttr",
    +             },
    +             "id": "non-empty-title",
    +             "impact": "critical",
    +             "message": "Element has no title attribute",
    +             "relatedNodes": Array [],
    +           },
    +           Object {
    +             "data": null,
    +             "id": "presentational-role",
    +             "impact": "critical",
    +             "message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\"",
    +             "relatedNodes": Array [],
    +           },
    +         ],
    +         "failureSummary": "Fix any of the following:
    +   Element does not have inner text that is visible to screen readers
    +   aria-label attribute does not exist or is empty
    +   aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty
    +   Element has no title attribute
    +   Element's default semantics were not overridden with role=\"none\" or role=\"presentation\"",
    +         "html": "<button type=\"button\" role=\"checkbox\" aria-checked=\"false\" data-state=\"unchecked\" value=\"on\" class=\"peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground\" id=\":R4sp:-form-item\" aria-describedby=\":R4sp:-form-item-description\" aria-invalid=\"false\">",
    +         "impact": "critical",
    +         "none": Array [],
    +         "target": Array [
    +           "#\\:R4sp\\:-form-item",
    +         ],
    +       },
    +     ],
    +     "tags": Array [
    +       "cat.name-role-value",
    +       "wcag2a",
    +       "wcag412",
    +       "section508",
    +       "section508.22.a",
    +       "TTv5",
    +       "TT6.a",
    +       "EN-[301](https://github.com/ten-x-dev/french-house-stack/actions/runs/7444497015/job/20250990268?pr=237#step:7:302)-549",
    +       "EN-9.4.1.2",
    +       "ACT",
    +     ],
    +   },
    + ]

Code example

<FormField
  control={form.control}
  name="acceptedTermsAndConditions"
  render={({ field }) => (
    <FormItem className="items-top flex space-x-3 space-y-0">
      <FormControl>
        <Checkbox
          checked={field.value}
          onCheckedChange={field.onChange}
        />
      </FormControl>

      <div className="grid gap-1 leading-none">
        <FormLabel>Accept our terms and conditions</FormLabel>

        <FormDescription>
          By accepting, you agree to our Terms and Conditions and Privacy Policy.
        </FormDescription>

        <FormMessage />
      </div>
    </FormItem>
  )}
/>

Flagged by the package: @axe-core/playwright

Related: #281

janhesters avatar Jan 06 '24 12:01 janhesters

There seem to be a number of these contrast issues as you call out. I suspect it's not a priority due to the fact that the theme can be changed. Concern is, for a resource as popular as this - folks will use the out of the box styles and fall foul of a number of obvious contrast issues.

A common one, that I think pretty much every component library out at the moment fails is the borders on input contrast: https://webflow.com/accessibility/checklist/task/check-the-contrast-for-all-borders

Always wonder if I'm missing something on this requirement, since it's so rare to see input borders that have 3:1 contrast. Maybe Shadcn approach gets around it by always having placeholder text - but to be honest that's generally considered bad practice accessibility wise also. https://www.nngroup.com/articles/form-design-placeholders/

andrewbarnesweb avatar Feb 05 '24 09:02 andrewbarnesweb

@shadcn You marked this as stale, but I don't think this issue is fixed, yet.

janhesters avatar Feb 05 '24 10:02 janhesters

@janhesters I'm running a GitHub actions to help surface those issues. I'll remove the label here and mark this one as to do. Thank you.

shadcn avatar Feb 05 '24 12:02 shadcn

@shadcn Thank you 🙏

janhesters avatar Feb 08 '24 16:02 janhesters

This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.

shadcn avatar Mar 02 '24 23:03 shadcn

@shadcn Probably want to keep this open again 🙏

janhesters avatar Mar 04 '24 09:03 janhesters

Agree. The contrast on the form items is really not great - just reviewing the new OTP component:

image

andrewbarnesweb avatar Mar 20 '24 16:03 andrewbarnesweb