ui
ui copied to clipboard
Accessibility: Contrast issues with primary buttons for certain colors (e.g. pink, red etc.), checkbox is not accessible
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
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/
@shadcn You marked this as stale, but I don't think this issue is fixed, yet.
@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 Thank you 🙏
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 Probably want to keep this open again 🙏
Agree. The contrast on the form items is really not great - just reviewing the new OTP component: