Calendar accessibility fix#2529
Conversation
|
f821375 to
545f906
Compare
545f906 to
8d0db1b
Compare
| * prop to `small`, `withBorder` and `withBackground` to `false`, and setting | ||
| * `renderIcon` to [IconArrowOpenEnd](icons). | ||
| */ | ||
| renderNextMonthButton?: Renderable | ||
| renderNextMonthButton?: Renderable<{ targetMonthSrLabel: string }> | ||
| /** | ||
| * A button to render in the navigation header. The recommendation is to | ||
| * compose it with the [IconButton](Button) component by setting the `size` | ||
| * prop to `small`, `withBorder` and `withBackground` to `false`, and setting | ||
| * `renderIcon` to [IconArrowOpenStart](icons). | ||
| */ |
There was a problem hiding this comment.
Can you please update the prop descriptions here too like in v2?
ToMESSKa
left a comment
There was a problem hiding this comment.
Really nice job. See my comment.
8d0db1b to
2ac9f89
Compare
60c5f40 to
3d35405
Compare
…DateInput v1 with DateInput v2 in DateTimeInput BREAKING CHANGE: renderWeekdayLabels` prop removed `calendarIcon` is a new required prop INSTUI-4791
2ac9f89 to
ba92f63
Compare
Visual regression report
Baselines come from the |
| <div aria-live="polite" aria-atomic="true"> | ||
| <h2 css={styles?.navigationLabel}>{visibleMonth.format('MMMM')}</h2> | ||
| {!withYearPicker ? ( | ||
| <div>{visibleMonth.format('YYYY')}</div> | ||
| <h2 css={styles?.navigationLabel}>{visibleMonth.format('YYYY')}</h2> | ||
| ) : null} | ||
| </span> | ||
| </div> |
There was a problem hiding this comment.
Two sibling <h2>s split a single conceptual heading. Screen readers announce them as two separate headings ("December, heading level 2. 2023, heading level 2.") and both show up in heading navigation, instead of one combined "December 2023". aria-atomic doesn't merge them — the heading boundaries still apply.
Suggest collapsing into a single <h2> (which can also host the live-region attributes):
| <div aria-live="polite" aria-atomic="true"> | |
| <h2 css={styles?.navigationLabel}>{visibleMonth.format('MMMM')}</h2> | |
| {!withYearPicker ? ( | |
| <div>{visibleMonth.format('YYYY')}</div> | |
| <h2 css={styles?.navigationLabel}>{visibleMonth.format('YYYY')}</h2> | |
| ) : null} | |
| </span> | |
| </div> | |
| <h2 | |
| aria-live="polite" | |
| aria-atomic="true" | |
| css={styles?.navigationLabel} | |
| > | |
| <span>{visibleMonth.format('MMMM')}</span> | |
| {!withYearPicker ? ( | |
| <span>{visibleMonth.format('YYYY')}</span> | |
| ) : null} | |
| </h2> |
If the existing two-line visual stacking matters, give the inner <span>s display: block in navigationLabel styles. One heading, one live region, one announcement.
…eader, descriptive nav button labels with target month, aria-modal on focused dialogs
ba92f63 to
c184bc3
Compare

INSTUI-5009
INSTUI-5010
INSTUI-5014
Improve date picker calendar accessibility
Changes
Add aria-live="polite" aria-atomic="true" to the month/year header in
Calendar v1 and v2. Previously the container was a
<span>wrapping<div>children (invalid HTML), causing screen readers to lose track of the live
region subtree and skip announcements on month navigation. Changed to
<div>.Add target month name to navigation button screen reader labels in Calendar
v1 and v2. Default buttons now announce e.g. "Previous month, November 2023"
instead of the generic "Previous month".
Extend renderPrevMonthButton/renderNextMonthButton prop type from Renderable
to
Renderable<{ targetMonthSrLabel: string }>in Calendar v1 and v2. Whenpassed as a function, the render prop receives the pre-formatted target month
label so consumers can build descriptive accessible names for custom buttons.
Update DateInput v2 to use function render props for navigation buttons,
appending targetMonthSrLabel to the consumer-provided label string so the
full announcement reads e.g. "Next month, January 2024".
Add aria-modal to Dialog when role="dialog" and shouldContainFocus is true,
scoping the screen reader virtual cursor to the dialog content. Guarded by
shouldContainFocus so non-modal Dialog usages (Tray without containment,
DrawerTray during transitions, etc.) are unaffected.
Test plan
Open a DateInput date picker with VoiceOver (macOS) or NVDA (Windows): verify the popover is announced as a dialog with its label (e.g. "Date picker, dialog")
The calendar heading displaying the year and month should use an h2
The last number in the yearPicker always fully visible
With the calendar open, press Tab past the last focusable element and Shift+Tab before the first: verify focus stays inside the picker and does not escape
Open a Modal, Tray, and Popover (non–date picker usage): verify aria-modal appears only when shouldContainFocus is true and does not appear on non-modal usages
Navigate to the next/previous month using the arrow buttons: verify the screen reader announces the new month and year (e.g. "January 2024") via the aria-live region without requiring the user to move focus
Check the previous and next month button accessible names: verify they include the target month (e.g. "Previous month, November 2023" / "Next month, January 2024") and not just the generic label
Pass a function to renderPrevMonthButton / renderNextMonthButton on Calendar v2: verify targetMonthSrLabel is received
Co-Authored-By: 🤖 Claude