Skip to content

fix/wcag-color-contrast #28771

@JoshuaViera

Description

@JoshuaViera

Found a bug? Please fill out the sections below. 👍

Disabled day cells in the booking calendar's date picker fail WCAG 2.1 AA minimum contrast ratio requirements in light mode. The current implementation uses the class text-muted opacity-50 on disabled dates (line 48 of packages/ui/components/form/date-range-picker/Calendar.tsx), which renders text color #6B7280 against the calendar's background color #EEEFF2. This produces a contrast ratio of only 4.2:1, falling below the WCAG 2.1 AA minimum of 4.5:1 for normal-sized text.
This affects all users with low vision viewing any booking page in light mode, and is also relevant for compliance with the European Accessibility Act (EAA), which begins enforcement in June 2025.
Dark mode is not affected — disabled dates there render at 7.59:1, which passes both AA and AAA.

A summary of the issue. This needs to be a clear detailed-rich summary.

Go to any Cal.com booking page (e.g. cal.com/[username])
Ensure your browser/OS is set to light mode (DevTools → Rendering → prefers-color-scheme: light)
Look at the calendar date picker — find any greyed-out disabled date (past dates or unavailable dates)
Right-click the disabled date → Inspect Element
In the DevTools console, run:
jsgetComputedStyle(document.querySelector('[aria-disabled="true"]')).color
This returns rgb(107, 114, 128) which is #6B7280
To get the background, inspect the calendar container:
jsgetComputedStyle(document.querySelector('.rdp-month')).backgroundColor
This returns #EEEFF2
Enter both values into the WebAIM Contrast Checker — result: 4.2:1 FAIL

Any other relevant information. For example, why do you consider this a bug and what did you expect to happen instead?

Disabled calendar dates have a contrast ratio of 4.2:1 in light mode
This fails WCAG 2.1 Level AA, which requires a minimum of 4.5:1 for normal text (under 18pt / 14pt bold)
Users with low vision or color sensitivity may struggle to distinguish disabled dates from the background
The issue originates from the combined effect of text-muted (which resolves to #6B7280) and opacity-50, which further reduces the already-insufficient contrast

  • What's happening right now that is different from what is expected

Disabled calendar dates should meet at least the WCAG 2.1 AA minimum of 4.5:1 contrast ratio in both light and dark mode
Proposed fix: replace text-muted opacity-50 with explicit color values:

Light mode: text-[#4A4E59] → produces 7.23:1 ratio (passes both AA and AAA)
Dark mode: dark:text-[#A3A3A3] → preserves the existing 7.59:1 ratio

Disabled dates should still look visually muted/secondary compared to active dates, but remain legible — the proposed color achieves this balance

  • This is an ideal result that the system should get after the tests are performed

File: packages/ui/components/form/date-range-picker/Calendar.tsx, line 48
Current class: day_disabled: "text-muted opacity-50"
Proposed class: day_disabled: "text-[#4A4E59] dark:text-[#A3A3A3]"
Component consumers: Calendar.tsx is imported by DatePicker.tsx and DateRangePicker.tsx — neither passes a classNames prop with a day_disabled override, so the fix propagates cleanly to both
Test impact: The test at packages/ui/components/form/datepicker/datepicker.test.tsx:51 currently finds disabled dates via classList.contains("opacity-50") — this will need to be updated to use aria-disabled="true" instead
Browser: Tested in Chrome 131, macOS Sequoia
Node.js: v20.x

  • Browser version, screen recording, console logs, network requests: You can make a recording with Bird Eats Bug.
  • Node.js version
  • Anything else that you think could be an issue.
Image Image Image Image
  • How was this tested? This is quite mandatory in terms of bugs. Providing evidence of your testing with screenshots or/and videos is an amazing way to prove the bug and a troubleshooting chance to find the solution.

Opened a live Cal.com booking page in Chrome (macOS) in light mode
Inspected a disabled date cell using Chrome DevTools
Extracted the computed text color by running in the console:
getComputedStyle(document.querySelector('[aria-disabled="true"]')).color
Result: rgb(107, 114, 128) → #6B7280
Identified the background color of the calendar container: #EEEFF2
Entered both values into the WebAIM Contrast Checker — returned 4.2:1, which fails WCAG 2.1 AA for normal text (minimum 4.5:1)
Tested the proposed replacement color #4A4E59 against the same background — returned 7.23:1, passing both AA and AAA
Also verified dark mode: disabled dates render at 7.59:1, which already passes — no issue there
Screenshots above:
Before — FAILS (4.2:1)
After — PASSES (7.23:1)

Metadata

Metadata

Assignees

No one assigned

    Labels

    🐛 bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions