@instructure/ui-calendar 11.7.3-snapshot-39 → 11.7.3-snapshot-41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -1
- package/es/Calendar/v1/Day/index.js +2 -1
- package/es/Calendar/v1/Day/props.js +1 -1
- package/es/Calendar/v1/index.js +9 -3
- package/es/Calendar/v1/props.js +1 -1
- package/es/Calendar/v2/Day/index.js +2 -1
- package/es/Calendar/v2/Day/props.js +1 -1
- package/es/Calendar/v2/index.js +20 -3
- package/es/Calendar/v2/props.js +1 -1
- package/lib/Calendar/v1/Day/index.js +2 -1
- package/lib/Calendar/v1/Day/props.js +1 -1
- package/lib/Calendar/v1/index.js +9 -3
- package/lib/Calendar/v1/props.js +1 -1
- package/lib/Calendar/v2/Day/index.js +2 -1
- package/lib/Calendar/v2/Day/props.js +1 -1
- package/lib/Calendar/v2/index.js +20 -3
- package/lib/Calendar/v2/props.js +1 -1
- package/package.json +16 -16
- package/src/Calendar/v1/Day/index.tsx +6 -1
- package/src/Calendar/v1/Day/props.ts +6 -0
- package/src/Calendar/v1/README.md +2 -0
- package/src/Calendar/v1/index.tsx +8 -3
- package/src/Calendar/v1/props.ts +6 -0
- package/src/Calendar/v2/Day/index.tsx +6 -1
- package/src/Calendar/v2/Day/props.ts +6 -0
- package/src/Calendar/v2/README.md +2 -0
- package/src/Calendar/v2/index.tsx +38 -20
- package/src/Calendar/v2/props.ts +6 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/types/Calendar/v1/Day/index.d.ts +1 -0
- package/types/Calendar/v1/Day/index.d.ts.map +1 -1
- package/types/Calendar/v1/Day/props.d.ts +5 -0
- package/types/Calendar/v1/Day/props.d.ts.map +1 -1
- package/types/Calendar/v1/index.d.ts +1 -0
- package/types/Calendar/v1/index.d.ts.map +1 -1
- package/types/Calendar/v1/props.d.ts +5 -0
- package/types/Calendar/v1/props.d.ts.map +1 -1
- package/types/Calendar/v2/Day/index.d.ts +1 -0
- package/types/Calendar/v2/Day/index.d.ts.map +1 -1
- package/types/Calendar/v2/Day/props.d.ts +5 -0
- package/types/Calendar/v2/Day/props.d.ts.map +1 -1
- package/types/Calendar/v2/index.d.ts +1 -0
- package/types/Calendar/v2/index.d.ts.map +1 -1
- package/types/Calendar/v2/props.d.ts +5 -0
- package/types/Calendar/v2/props.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
## [11.7.3-snapshot-
|
|
6
|
+
## [11.7.3-snapshot-41](https://github.com/instructure/instructure-ui/compare/v11.7.2...v11.7.3-snapshot-41) (2026-05-07)
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
### Bug Fixes
|
|
10
10
|
|
|
11
11
|
* **many:** update dependencies, remove lots of Babel plugins, remove Webpack 4 support ([f916fca](https://github.com/instructure/instructure-ui/commit/f916fcafdddcb2d7de401f93e8ff92cfdfa47bba))
|
|
12
|
+
* **ui-date-time-input,ui-date-input,ui-calendar:** set missing aria-selected on calendar days, BREAKING CHANGE: add mandatory prop selectedLabel, change datePickerDialog prop to mandatory ([08abed5](https://github.com/instructure/instructure-ui/commit/08abed5e8c8b29aecab0368e01e8e4ffd0c7fda7))
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
|
|
@@ -116,6 +116,7 @@ let Day = (_dec = withStyle(generateStyle, generateComponentTheme), _dec(_class
|
|
|
116
116
|
interaction,
|
|
117
117
|
isOutsideMonth,
|
|
118
118
|
isSelected,
|
|
119
|
+
selectedLabel,
|
|
119
120
|
isToday,
|
|
120
121
|
onClick,
|
|
121
122
|
onKeyDown,
|
|
@@ -148,7 +149,7 @@ let Day = (_dec = withStyle(generateStyle, generateComponentTheme), _dec(_class
|
|
|
148
149
|
children: _jsx("span", {
|
|
149
150
|
css: styles?.day,
|
|
150
151
|
children: _jsx(AccessibleContent, {
|
|
151
|
-
alt: label,
|
|
152
|
+
alt: selectedLabel && isSelected ? `${label}, ${selectedLabel}` : label,
|
|
152
153
|
children: callRenderProp(children)
|
|
153
154
|
})
|
|
154
155
|
})
|
|
@@ -22,5 +22,5 @@
|
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
const allowedProps = ['children', 'date', 'label', 'interaction', 'isSelected', 'isToday', 'isOutsideMonth', 'onClick', 'onKeyDown', 'elementRef', 'as'];
|
|
25
|
+
const allowedProps = ['children', 'date', 'label', 'interaction', 'isSelected', 'selectedLabel', 'isToday', 'isOutsideMonth', 'onClick', 'onKeyDown', 'elementRef', 'as'];
|
|
26
26
|
export { allowedProps };
|
package/es/Calendar/v1/index.js
CHANGED
|
@@ -328,8 +328,12 @@ let Calendar = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, g
|
|
|
328
328
|
children: row.map((day, i) => _jsx("td", {
|
|
329
329
|
role: role,
|
|
330
330
|
children: role === 'presentation' ? safeCloneElement(day, {
|
|
331
|
-
'aria-describedby': this._weekdayHeaderIds[i]
|
|
332
|
-
|
|
331
|
+
'aria-describedby': this._weekdayHeaderIds[i],
|
|
332
|
+
role: 'option'
|
|
333
|
+
}) : safeCloneElement(day, {
|
|
334
|
+
'aria-describedby': this._weekdayHeaderIds[i],
|
|
335
|
+
role: 'button'
|
|
336
|
+
})
|
|
333
337
|
}, day.props.date))
|
|
334
338
|
}, `row${row[0].props.date}`));
|
|
335
339
|
}
|
|
@@ -376,7 +380,8 @@ let Calendar = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, g
|
|
|
376
380
|
}
|
|
377
381
|
renderDefaultdays() {
|
|
378
382
|
const {
|
|
379
|
-
selectedDate
|
|
383
|
+
selectedDate,
|
|
384
|
+
selectedLabel
|
|
380
385
|
} = this.props;
|
|
381
386
|
const {
|
|
382
387
|
visibleMonth,
|
|
@@ -416,6 +421,7 @@ let Calendar = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, g
|
|
|
416
421
|
isOutsideMonth: !date.isSame(visibleMonth, 'month'),
|
|
417
422
|
label: date.format('D MMMM YYYY') // used by screen readers
|
|
418
423
|
,
|
|
424
|
+
selectedLabel: selectedLabel,
|
|
419
425
|
onClick: this.handleDayClick,
|
|
420
426
|
interaction: this.isDisabledDate(date) ? 'disabled' : 'enabled',
|
|
421
427
|
children: date.format('DD')
|
package/es/Calendar/v1/props.js
CHANGED
|
@@ -22,5 +22,5 @@
|
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
const allowedProps = ['as', 'children', 'currentDate', 'disabledDates', 'locale', 'onDateSelected', 'onRequestRenderNextMonth', 'onRequestRenderPrevMonth', 'renderNavigationLabel', 'renderNextMonthButton', 'renderPrevMonthButton', 'renderWeekdayLabels', 'role', 'selectedDate', 'timezone', 'visibleMonth'];
|
|
25
|
+
const allowedProps = ['as', 'children', 'currentDate', 'disabledDates', 'locale', 'onDateSelected', 'onRequestRenderNextMonth', 'onRequestRenderPrevMonth', 'renderNavigationLabel', 'renderNextMonthButton', 'renderPrevMonthButton', 'renderWeekdayLabels', 'role', 'selectedDate', 'selectedLabel', 'timezone', 'visibleMonth'];
|
|
26
26
|
export { allowedProps };
|
|
@@ -115,6 +115,7 @@ let Day = (_dec = withStyleNew(generateStyle), _dec(_class = class Day extends C
|
|
|
115
115
|
interaction,
|
|
116
116
|
isOutsideMonth,
|
|
117
117
|
isSelected,
|
|
118
|
+
selectedLabel,
|
|
118
119
|
isToday,
|
|
119
120
|
onClick,
|
|
120
121
|
onKeyDown,
|
|
@@ -147,7 +148,7 @@ let Day = (_dec = withStyleNew(generateStyle), _dec(_class = class Day extends C
|
|
|
147
148
|
children: _jsx("span", {
|
|
148
149
|
css: styles?.day,
|
|
149
150
|
children: _jsx(AccessibleContent, {
|
|
150
|
-
alt: label,
|
|
151
|
+
alt: selectedLabel && isSelected ? `${label}, ${selectedLabel}` : label,
|
|
151
152
|
children: callRenderProp(children)
|
|
152
153
|
})
|
|
153
154
|
})
|
|
@@ -22,5 +22,5 @@
|
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
const allowedProps = ['children', 'date', 'label', 'interaction', 'isSelected', 'isToday', 'isOutsideMonth', 'onClick', 'onKeyDown', 'elementRef', 'as'];
|
|
25
|
+
const allowedProps = ['children', 'date', 'label', 'interaction', 'isSelected', 'selectedLabel', 'isToday', 'isOutsideMonth', 'onClick', 'onKeyDown', 'elementRef', 'as'];
|
|
26
26
|
export { allowedProps };
|
package/es/Calendar/v2/index.js
CHANGED
|
@@ -322,13 +322,29 @@ let Calendar = (_dec = withDeterministicId(), _dec2 = withStyleNew(generateStyle
|
|
|
322
322
|
if (!days[index]) days.push([]);
|
|
323
323
|
days[index].push(day);
|
|
324
324
|
return days; // 7xN 2D array of `Day`s
|
|
325
|
-
}, [])
|
|
325
|
+
}, [])
|
|
326
|
+
// TODO: Implement proper WAI-ARIA grid pattern for table mode to enable aria-selected on days.
|
|
327
|
+
// Currently in table mode, days use role="button" which does not support aria-selected
|
|
328
|
+
// (axe violation), so selection is announced via selectedLabel text only.
|
|
329
|
+
//
|
|
330
|
+
// To implement properly (per https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/datepicker-dialog/):
|
|
331
|
+
// 1. Add role="grid" to the <table> in table mode (renderBody)
|
|
332
|
+
// 2. Add role="row" to each <tr>
|
|
333
|
+
// 3. Set role="gridcell" + aria-selected on each <td> (not on the Day)
|
|
334
|
+
// 4. Keep Day as role="button" inside the gridcell
|
|
335
|
+
// This allows aria-selected to live on the <td role="gridcell"> which is spec-correct,
|
|
336
|
+
// while the Day button remains the interactive element.
|
|
337
|
+
.map(row => _jsx("tr", {
|
|
326
338
|
role: role,
|
|
327
339
|
children: row.map((day, i) => _jsx("td", {
|
|
328
340
|
role: role,
|
|
329
341
|
children: role === 'presentation' ? safeCloneElement(day, {
|
|
330
|
-
'aria-describedby': this._weekdayHeaderIds[i]
|
|
331
|
-
|
|
342
|
+
'aria-describedby': this._weekdayHeaderIds[i],
|
|
343
|
+
role: 'option'
|
|
344
|
+
}) : safeCloneElement(day, {
|
|
345
|
+
'aria-describedby': this._weekdayHeaderIds[i],
|
|
346
|
+
role: 'button'
|
|
347
|
+
})
|
|
332
348
|
}, day.props.date))
|
|
333
349
|
}, `row${row[0].props.date}`));
|
|
334
350
|
}
|
|
@@ -415,6 +431,7 @@ let Calendar = (_dec = withDeterministicId(), _dec2 = withStyleNew(generateStyle
|
|
|
415
431
|
isOutsideMonth: !date.isSame(visibleMonth, 'month'),
|
|
416
432
|
label: date.format('D MMMM YYYY') // used by screen readers
|
|
417
433
|
,
|
|
434
|
+
selectedLabel: this.props.selectedLabel,
|
|
418
435
|
onClick: this.handleDayClick,
|
|
419
436
|
interaction: this.isDisabledDate(date) ? 'disabled' : 'enabled',
|
|
420
437
|
children: date.format('DD')
|
package/es/Calendar/v2/props.js
CHANGED
|
@@ -22,5 +22,5 @@
|
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
const allowedProps = ['as', 'children', 'currentDate', 'disabledDates', 'locale', 'onDateSelected', 'onRequestRenderNextMonth', 'onRequestRenderPrevMonth', 'renderNavigationLabel', 'renderNextMonthButton', 'renderPrevMonthButton', 'renderWeekdayLabels', 'role', 'selectedDate', 'timezone', 'visibleMonth'];
|
|
25
|
+
const allowedProps = ['as', 'children', 'currentDate', 'disabledDates', 'locale', 'onDateSelected', 'onRequestRenderNextMonth', 'onRequestRenderPrevMonth', 'renderNavigationLabel', 'renderNextMonthButton', 'renderPrevMonthButton', 'renderWeekdayLabels', 'role', 'selectedDate', 'selectedLabel', 'timezone', 'visibleMonth'];
|
|
26
26
|
export { allowedProps };
|
|
@@ -124,6 +124,7 @@ let Day = exports.Day = (_dec = (0, _emotion.withStyle)(_styles.default, _theme.
|
|
|
124
124
|
interaction,
|
|
125
125
|
isOutsideMonth,
|
|
126
126
|
isSelected,
|
|
127
|
+
selectedLabel,
|
|
127
128
|
isToday,
|
|
128
129
|
onClick,
|
|
129
130
|
onKeyDown,
|
|
@@ -156,7 +157,7 @@ let Day = exports.Day = (_dec = (0, _emotion.withStyle)(_styles.default, _theme.
|
|
|
156
157
|
children: (0, _jsxRuntime.jsx)("span", {
|
|
157
158
|
css: styles?.day,
|
|
158
159
|
children: (0, _jsxRuntime.jsx)(_AccessibleContent.AccessibleContent, {
|
|
159
|
-
alt: label,
|
|
160
|
+
alt: selectedLabel && isSelected ? `${label}, ${selectedLabel}` : label,
|
|
160
161
|
children: (0, _callRenderProp.callRenderProp)(children)
|
|
161
162
|
})
|
|
162
163
|
})
|
|
@@ -28,4 +28,4 @@ exports.allowedProps = void 0;
|
|
|
28
28
|
* SOFTWARE.
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
|
-
const allowedProps = exports.allowedProps = ['children', 'date', 'label', 'interaction', 'isSelected', 'isToday', 'isOutsideMonth', 'onClick', 'onKeyDown', 'elementRef', 'as'];
|
|
31
|
+
const allowedProps = exports.allowedProps = ['children', 'date', 'label', 'interaction', 'isSelected', 'selectedLabel', 'isToday', 'isOutsideMonth', 'onClick', 'onKeyDown', 'elementRef', 'as'];
|
package/lib/Calendar/v1/index.js
CHANGED
|
@@ -339,8 +339,12 @@ let Calendar = exports.Calendar = (_dec = (0, _withDeterministicId.withDetermini
|
|
|
339
339
|
children: row.map((day, i) => (0, _jsxRuntime.jsx)("td", {
|
|
340
340
|
role: role,
|
|
341
341
|
children: role === 'presentation' ? (0, _safeCloneElement.safeCloneElement)(day, {
|
|
342
|
-
'aria-describedby': this._weekdayHeaderIds[i]
|
|
343
|
-
|
|
342
|
+
'aria-describedby': this._weekdayHeaderIds[i],
|
|
343
|
+
role: 'option'
|
|
344
|
+
}) : (0, _safeCloneElement.safeCloneElement)(day, {
|
|
345
|
+
'aria-describedby': this._weekdayHeaderIds[i],
|
|
346
|
+
role: 'button'
|
|
347
|
+
})
|
|
344
348
|
}, day.props.date))
|
|
345
349
|
}, `row${row[0].props.date}`));
|
|
346
350
|
}
|
|
@@ -387,7 +391,8 @@ let Calendar = exports.Calendar = (_dec = (0, _withDeterministicId.withDetermini
|
|
|
387
391
|
}
|
|
388
392
|
renderDefaultdays() {
|
|
389
393
|
const {
|
|
390
|
-
selectedDate
|
|
394
|
+
selectedDate,
|
|
395
|
+
selectedLabel
|
|
391
396
|
} = this.props;
|
|
392
397
|
const {
|
|
393
398
|
visibleMonth,
|
|
@@ -427,6 +432,7 @@ let Calendar = exports.Calendar = (_dec = (0, _withDeterministicId.withDetermini
|
|
|
427
432
|
isOutsideMonth: !date.isSame(visibleMonth, 'month'),
|
|
428
433
|
label: date.format('D MMMM YYYY') // used by screen readers
|
|
429
434
|
,
|
|
435
|
+
selectedLabel: selectedLabel,
|
|
430
436
|
onClick: this.handleDayClick,
|
|
431
437
|
interaction: this.isDisabledDate(date) ? 'disabled' : 'enabled',
|
|
432
438
|
children: date.format('DD')
|
package/lib/Calendar/v1/props.js
CHANGED
|
@@ -28,4 +28,4 @@ exports.allowedProps = void 0;
|
|
|
28
28
|
* SOFTWARE.
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
|
-
const allowedProps = exports.allowedProps = ['as', 'children', 'currentDate', 'disabledDates', 'locale', 'onDateSelected', 'onRequestRenderNextMonth', 'onRequestRenderPrevMonth', 'renderNavigationLabel', 'renderNextMonthButton', 'renderPrevMonthButton', 'renderWeekdayLabels', 'role', 'selectedDate', 'timezone', 'visibleMonth'];
|
|
31
|
+
const allowedProps = exports.allowedProps = ['as', 'children', 'currentDate', 'disabledDates', 'locale', 'onDateSelected', 'onRequestRenderNextMonth', 'onRequestRenderPrevMonth', 'renderNavigationLabel', 'renderNextMonthButton', 'renderPrevMonthButton', 'renderWeekdayLabels', 'role', 'selectedDate', 'selectedLabel', 'timezone', 'visibleMonth'];
|
|
@@ -123,6 +123,7 @@ let Day = exports.Day = (_dec = (0, _emotion.withStyleNew)(_styles.default), _de
|
|
|
123
123
|
interaction,
|
|
124
124
|
isOutsideMonth,
|
|
125
125
|
isSelected,
|
|
126
|
+
selectedLabel,
|
|
126
127
|
isToday,
|
|
127
128
|
onClick,
|
|
128
129
|
onKeyDown,
|
|
@@ -155,7 +156,7 @@ let Day = exports.Day = (_dec = (0, _emotion.withStyleNew)(_styles.default), _de
|
|
|
155
156
|
children: (0, _jsxRuntime.jsx)("span", {
|
|
156
157
|
css: styles?.day,
|
|
157
158
|
children: (0, _jsxRuntime.jsx)(_AccessibleContent.AccessibleContent, {
|
|
158
|
-
alt: label,
|
|
159
|
+
alt: selectedLabel && isSelected ? `${label}, ${selectedLabel}` : label,
|
|
159
160
|
children: (0, _callRenderProp.callRenderProp)(children)
|
|
160
161
|
})
|
|
161
162
|
})
|
|
@@ -28,4 +28,4 @@ exports.allowedProps = void 0;
|
|
|
28
28
|
* SOFTWARE.
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
|
-
const allowedProps = exports.allowedProps = ['children', 'date', 'label', 'interaction', 'isSelected', 'isToday', 'isOutsideMonth', 'onClick', 'onKeyDown', 'elementRef', 'as'];
|
|
31
|
+
const allowedProps = exports.allowedProps = ['children', 'date', 'label', 'interaction', 'isSelected', 'selectedLabel', 'isToday', 'isOutsideMonth', 'onClick', 'onKeyDown', 'elementRef', 'as'];
|
package/lib/Calendar/v2/index.js
CHANGED
|
@@ -332,13 +332,29 @@ let Calendar = exports.Calendar = (_dec = (0, _withDeterministicId.withDetermini
|
|
|
332
332
|
if (!days[index]) days.push([]);
|
|
333
333
|
days[index].push(day);
|
|
334
334
|
return days; // 7xN 2D array of `Day`s
|
|
335
|
-
}, [])
|
|
335
|
+
}, [])
|
|
336
|
+
// TODO: Implement proper WAI-ARIA grid pattern for table mode to enable aria-selected on days.
|
|
337
|
+
// Currently in table mode, days use role="button" which does not support aria-selected
|
|
338
|
+
// (axe violation), so selection is announced via selectedLabel text only.
|
|
339
|
+
//
|
|
340
|
+
// To implement properly (per https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/datepicker-dialog/):
|
|
341
|
+
// 1. Add role="grid" to the <table> in table mode (renderBody)
|
|
342
|
+
// 2. Add role="row" to each <tr>
|
|
343
|
+
// 3. Set role="gridcell" + aria-selected on each <td> (not on the Day)
|
|
344
|
+
// 4. Keep Day as role="button" inside the gridcell
|
|
345
|
+
// This allows aria-selected to live on the <td role="gridcell"> which is spec-correct,
|
|
346
|
+
// while the Day button remains the interactive element.
|
|
347
|
+
.map(row => (0, _jsxRuntime.jsx)("tr", {
|
|
336
348
|
role: role,
|
|
337
349
|
children: row.map((day, i) => (0, _jsxRuntime.jsx)("td", {
|
|
338
350
|
role: role,
|
|
339
351
|
children: role === 'presentation' ? (0, _safeCloneElement.safeCloneElement)(day, {
|
|
340
|
-
'aria-describedby': this._weekdayHeaderIds[i]
|
|
341
|
-
|
|
352
|
+
'aria-describedby': this._weekdayHeaderIds[i],
|
|
353
|
+
role: 'option'
|
|
354
|
+
}) : (0, _safeCloneElement.safeCloneElement)(day, {
|
|
355
|
+
'aria-describedby': this._weekdayHeaderIds[i],
|
|
356
|
+
role: 'button'
|
|
357
|
+
})
|
|
342
358
|
}, day.props.date))
|
|
343
359
|
}, `row${row[0].props.date}`));
|
|
344
360
|
}
|
|
@@ -425,6 +441,7 @@ let Calendar = exports.Calendar = (_dec = (0, _withDeterministicId.withDetermini
|
|
|
425
441
|
isOutsideMonth: !date.isSame(visibleMonth, 'month'),
|
|
426
442
|
label: date.format('D MMMM YYYY') // used by screen readers
|
|
427
443
|
,
|
|
444
|
+
selectedLabel: this.props.selectedLabel,
|
|
428
445
|
onClick: this.handleDayClick,
|
|
429
446
|
interaction: this.isDisabledDate(date) ? 'disabled' : 'enabled',
|
|
430
447
|
children: date.format('DD')
|
package/lib/Calendar/v2/props.js
CHANGED
|
@@ -28,4 +28,4 @@ exports.allowedProps = void 0;
|
|
|
28
28
|
* SOFTWARE.
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
|
-
const allowedProps = exports.allowedProps = ['as', 'children', 'currentDate', 'disabledDates', 'locale', 'onDateSelected', 'onRequestRenderNextMonth', 'onRequestRenderPrevMonth', 'renderNavigationLabel', 'renderNextMonthButton', 'renderPrevMonthButton', 'renderWeekdayLabels', 'role', 'selectedDate', 'timezone', 'visibleMonth'];
|
|
31
|
+
const allowedProps = exports.allowedProps = ['as', 'children', 'currentDate', 'disabledDates', 'locale', 'onDateSelected', 'onRequestRenderNextMonth', 'onRequestRenderPrevMonth', 'renderNavigationLabel', 'renderNextMonthButton', 'renderPrevMonthButton', 'renderWeekdayLabels', 'role', 'selectedDate', 'selectedLabel', 'timezone', 'visibleMonth'];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instructure/ui-calendar",
|
|
3
|
-
"version": "11.7.3-snapshot-
|
|
3
|
+
"version": "11.7.3-snapshot-41",
|
|
4
4
|
"description": "A calendar component.",
|
|
5
5
|
"author": "Instructure, Inc. Engineering and Product Design",
|
|
6
6
|
"module": "./es/index.js",
|
|
@@ -15,27 +15,27 @@
|
|
|
15
15
|
"license": "MIT",
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@babel/runtime": "^7.29.2",
|
|
18
|
-
"@instructure/console": "11.7.3-snapshot-
|
|
19
|
-
"@instructure/
|
|
20
|
-
"@instructure/
|
|
21
|
-
"@instructure/ui-
|
|
22
|
-
"@instructure/ui-
|
|
23
|
-
"@instructure/ui-
|
|
24
|
-
"@instructure/ui-
|
|
25
|
-
"@instructure/ui-
|
|
26
|
-
"@instructure/ui-themes": "11.7.3-snapshot-
|
|
27
|
-
"@instructure/ui-utils": "11.7.3-snapshot-
|
|
28
|
-
"@instructure/ui-view": "11.7.3-snapshot-
|
|
29
|
-
"@instructure/
|
|
30
|
-
"@instructure/
|
|
18
|
+
"@instructure/console": "11.7.3-snapshot-41",
|
|
19
|
+
"@instructure/shared-types": "11.7.3-snapshot-41",
|
|
20
|
+
"@instructure/emotion": "11.7.3-snapshot-41",
|
|
21
|
+
"@instructure/ui-buttons": "11.7.3-snapshot-41",
|
|
22
|
+
"@instructure/ui-a11y-content": "11.7.3-snapshot-41",
|
|
23
|
+
"@instructure/ui-icons": "11.7.3-snapshot-41",
|
|
24
|
+
"@instructure/ui-simple-select": "11.7.3-snapshot-41",
|
|
25
|
+
"@instructure/ui-i18n": "11.7.3-snapshot-41",
|
|
26
|
+
"@instructure/ui-themes": "11.7.3-snapshot-41",
|
|
27
|
+
"@instructure/ui-react-utils": "11.7.3-snapshot-41",
|
|
28
|
+
"@instructure/ui-view": "11.7.3-snapshot-41",
|
|
29
|
+
"@instructure/ui-utils": "11.7.3-snapshot-41",
|
|
30
|
+
"@instructure/uid": "11.7.3-snapshot-41"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@testing-library/jest-dom": "^6.6.3",
|
|
34
34
|
"@testing-library/react": "15.0.7",
|
|
35
35
|
"@testing-library/user-event": "^14.6.1",
|
|
36
36
|
"vitest": "^3.2.2",
|
|
37
|
-
"@instructure/ui-
|
|
38
|
-
"@instructure/ui-
|
|
37
|
+
"@instructure/ui-babel-preset": "11.7.3-snapshot-41",
|
|
38
|
+
"@instructure/ui-color-utils": "11.7.3-snapshot-41"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"react": ">=18 <=19"
|
|
@@ -117,6 +117,7 @@ class Day extends Component<CalendarDayProps> {
|
|
|
117
117
|
interaction,
|
|
118
118
|
isOutsideMonth,
|
|
119
119
|
isSelected,
|
|
120
|
+
selectedLabel,
|
|
120
121
|
isToday,
|
|
121
122
|
onClick,
|
|
122
123
|
onKeyDown,
|
|
@@ -164,7 +165,11 @@ class Day extends Component<CalendarDayProps> {
|
|
|
164
165
|
data-cid="Calendar.Day"
|
|
165
166
|
>
|
|
166
167
|
<span css={styles?.day}>
|
|
167
|
-
<AccessibleContent
|
|
168
|
+
<AccessibleContent
|
|
169
|
+
alt={
|
|
170
|
+
selectedLabel && isSelected ? `${label}, ${selectedLabel}` : label
|
|
171
|
+
}
|
|
172
|
+
>
|
|
168
173
|
{callRenderProp(children)}
|
|
169
174
|
</AccessibleContent>
|
|
170
175
|
</span>
|
|
@@ -57,6 +57,11 @@ type CalendarDayOwnProps = {
|
|
|
57
57
|
* Is the `<Calendar.Day />` selected
|
|
58
58
|
*/
|
|
59
59
|
isSelected?: boolean
|
|
60
|
+
/**
|
|
61
|
+
* Screen reader label appended to the date label when the day is selected.
|
|
62
|
+
* Used to announce the selected state to assistive technologies.
|
|
63
|
+
*/
|
|
64
|
+
selectedLabel?: string
|
|
60
65
|
/**
|
|
61
66
|
* Is the `<Calendar.Day />` today
|
|
62
67
|
*/
|
|
@@ -114,6 +119,7 @@ const allowedProps: AllowedPropKeys = [
|
|
|
114
119
|
'label',
|
|
115
120
|
'interaction',
|
|
116
121
|
'isSelected',
|
|
122
|
+
'selectedLabel',
|
|
117
123
|
'isToday',
|
|
118
124
|
'isOutsideMonth',
|
|
119
125
|
'onClick',
|
|
@@ -33,6 +33,7 @@ type: example
|
|
|
33
33
|
currentDate="2023-12-15"
|
|
34
34
|
disabledDates={['2023-12-22', '2023-12-12', '2023-12-11']}
|
|
35
35
|
selectedDate={selectedDate}
|
|
36
|
+
selectedLabel="selected"
|
|
36
37
|
onRequestRenderNextMonth={(_e, requestedMonth) =>
|
|
37
38
|
setVisibleMonth(requestedMonth)
|
|
38
39
|
}
|
|
@@ -64,6 +65,7 @@ type: example
|
|
|
64
65
|
currentDate="2024-02-29"
|
|
65
66
|
disabledDates={['2023-12-22', '2023-12-12', '2023-12-11']}
|
|
66
67
|
selectedDate={selectedDate}
|
|
68
|
+
selectedLabel="selected"
|
|
67
69
|
onRequestRenderNextMonth={(_e, requestedMonth) =>
|
|
68
70
|
setVisibleMonth(requestedMonth)
|
|
69
71
|
}
|
|
@@ -436,9 +436,13 @@ class Calendar extends Component<CalendarProps, CalendarState> {
|
|
|
436
436
|
<td key={day.props.date} role={role}>
|
|
437
437
|
{role === 'presentation'
|
|
438
438
|
? safeCloneElement(day, {
|
|
439
|
-
'aria-describedby': this._weekdayHeaderIds[i]
|
|
439
|
+
'aria-describedby': this._weekdayHeaderIds[i],
|
|
440
|
+
role: 'option'
|
|
440
441
|
})
|
|
441
|
-
: day
|
|
442
|
+
: safeCloneElement(day, {
|
|
443
|
+
'aria-describedby': this._weekdayHeaderIds[i],
|
|
444
|
+
role: 'button'
|
|
445
|
+
})}
|
|
442
446
|
</td>
|
|
443
447
|
))}
|
|
444
448
|
</tr>
|
|
@@ -488,7 +492,7 @@ class Calendar extends Component<CalendarProps, CalendarState> {
|
|
|
488
492
|
}
|
|
489
493
|
|
|
490
494
|
renderDefaultdays() {
|
|
491
|
-
const { selectedDate } = this.props
|
|
495
|
+
const { selectedDate, selectedLabel } = this.props
|
|
492
496
|
const { visibleMonth, today } = this.state
|
|
493
497
|
// Sets it to the first local day of the week counting back from the start of the month.
|
|
494
498
|
// Note that first day depends on the locale, e.g. it's Sunday in the US and
|
|
@@ -525,6 +529,7 @@ class Calendar extends Component<CalendarProps, CalendarState> {
|
|
|
525
529
|
isToday={date.isSame(today, 'day')}
|
|
526
530
|
isOutsideMonth={!date.isSame(visibleMonth, 'month')}
|
|
527
531
|
label={date.format('D MMMM YYYY')} // used by screen readers
|
|
532
|
+
selectedLabel={selectedLabel}
|
|
528
533
|
onClick={this.handleDayClick}
|
|
529
534
|
interaction={this.isDisabledDate(date) ? 'disabled' : 'enabled'}
|
|
530
535
|
>
|
package/src/Calendar/v1/props.ts
CHANGED
|
@@ -130,6 +130,11 @@ type CalendarOwnProps = {
|
|
|
130
130
|
* ISO date string for the selected date. It needs onDateSelected to be specified too.
|
|
131
131
|
*/
|
|
132
132
|
selectedDate?: string
|
|
133
|
+
/**
|
|
134
|
+
* Screen reader label appended to the date label when the day is selected.
|
|
135
|
+
* Used to announce the selected state to assistive technologies.
|
|
136
|
+
*/
|
|
137
|
+
selectedLabel?: string
|
|
133
138
|
/**
|
|
134
139
|
* A timezone identifier in the format: *Area/Location*
|
|
135
140
|
*
|
|
@@ -194,6 +199,7 @@ const allowedProps: AllowedPropKeys = [
|
|
|
194
199
|
'renderWeekdayLabels',
|
|
195
200
|
'role',
|
|
196
201
|
'selectedDate',
|
|
202
|
+
'selectedLabel',
|
|
197
203
|
'timezone',
|
|
198
204
|
'visibleMonth'
|
|
199
205
|
]
|
|
@@ -116,6 +116,7 @@ class Day extends Component<CalendarDayProps> {
|
|
|
116
116
|
interaction,
|
|
117
117
|
isOutsideMonth,
|
|
118
118
|
isSelected,
|
|
119
|
+
selectedLabel,
|
|
119
120
|
isToday,
|
|
120
121
|
onClick,
|
|
121
122
|
onKeyDown,
|
|
@@ -163,7 +164,11 @@ class Day extends Component<CalendarDayProps> {
|
|
|
163
164
|
data-cid="Calendar.Day"
|
|
164
165
|
>
|
|
165
166
|
<span css={styles?.day}>
|
|
166
|
-
<AccessibleContent
|
|
167
|
+
<AccessibleContent
|
|
168
|
+
alt={
|
|
169
|
+
selectedLabel && isSelected ? `${label}, ${selectedLabel}` : label
|
|
170
|
+
}
|
|
171
|
+
>
|
|
167
172
|
{callRenderProp(children)}
|
|
168
173
|
</AccessibleContent>
|
|
169
174
|
</span>
|
|
@@ -57,6 +57,11 @@ type CalendarDayOwnProps = {
|
|
|
57
57
|
* Is the `<Calendar.Day />` selected
|
|
58
58
|
*/
|
|
59
59
|
isSelected?: boolean
|
|
60
|
+
/**
|
|
61
|
+
* Screen reader label appended to the date label when the day is selected.
|
|
62
|
+
* Used to announce the selected state to assistive technologies.
|
|
63
|
+
*/
|
|
64
|
+
selectedLabel: string
|
|
60
65
|
/**
|
|
61
66
|
* Is the `<Calendar.Day />` today
|
|
62
67
|
*/
|
|
@@ -117,6 +122,7 @@ const allowedProps: AllowedPropKeys = [
|
|
|
117
122
|
'label',
|
|
118
123
|
'interaction',
|
|
119
124
|
'isSelected',
|
|
125
|
+
'selectedLabel',
|
|
120
126
|
'isToday',
|
|
121
127
|
'isOutsideMonth',
|
|
122
128
|
'onClick',
|
|
@@ -33,6 +33,7 @@ type: example
|
|
|
33
33
|
currentDate="2023-12-15"
|
|
34
34
|
disabledDates={['2023-12-22', '2023-12-12', '2023-12-11']}
|
|
35
35
|
selectedDate={selectedDate}
|
|
36
|
+
selectedLabel="selected"
|
|
36
37
|
onRequestRenderNextMonth={(_e, requestedMonth) =>
|
|
37
38
|
setVisibleMonth(requestedMonth)
|
|
38
39
|
}
|
|
@@ -64,6 +65,7 @@ type: example
|
|
|
64
65
|
currentDate="2024-02-29"
|
|
65
66
|
disabledDates={['2023-12-22', '2023-12-12', '2023-12-11']}
|
|
66
67
|
selectedDate={selectedDate}
|
|
68
|
+
selectedLabel="selected"
|
|
67
69
|
onRequestRenderNextMonth={(_e, requestedMonth) =>
|
|
68
70
|
setVisibleMonth(requestedMonth)
|
|
69
71
|
}
|
|
@@ -422,26 +422,43 @@ class Calendar extends Component<CalendarProps, CalendarState> {
|
|
|
422
422
|
`[Calendar] should have exactly ${Calendar.DAY_COUNT} children. ${length} provided.`
|
|
423
423
|
)
|
|
424
424
|
|
|
425
|
-
return
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
425
|
+
return (
|
|
426
|
+
childrenArr
|
|
427
|
+
.reduce((days: ReactElement<any>[][], day, i) => {
|
|
428
|
+
const index = Math.floor(i / 7)
|
|
429
|
+
if (!days[index]) days.push([])
|
|
430
|
+
days[index].push(day)
|
|
431
|
+
return days // 7xN 2D array of `Day`s
|
|
432
|
+
}, [])
|
|
433
|
+
// TODO: Implement proper WAI-ARIA grid pattern for table mode to enable aria-selected on days.
|
|
434
|
+
// Currently in table mode, days use role="button" which does not support aria-selected
|
|
435
|
+
// (axe violation), so selection is announced via selectedLabel text only.
|
|
436
|
+
//
|
|
437
|
+
// To implement properly (per https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/datepicker-dialog/):
|
|
438
|
+
// 1. Add role="grid" to the <table> in table mode (renderBody)
|
|
439
|
+
// 2. Add role="row" to each <tr>
|
|
440
|
+
// 3. Set role="gridcell" + aria-selected on each <td> (not on the Day)
|
|
441
|
+
// 4. Keep Day as role="button" inside the gridcell
|
|
442
|
+
// This allows aria-selected to live on the <td role="gridcell"> which is spec-correct,
|
|
443
|
+
// while the Day button remains the interactive element.
|
|
444
|
+
.map((row) => (
|
|
445
|
+
<tr key={`row${row[0].props.date}`} role={role}>
|
|
446
|
+
{row.map((day, i) => (
|
|
447
|
+
<td key={day.props.date} role={role}>
|
|
448
|
+
{role === 'presentation'
|
|
449
|
+
? safeCloneElement(day, {
|
|
450
|
+
'aria-describedby': this._weekdayHeaderIds[i],
|
|
451
|
+
role: 'option'
|
|
452
|
+
})
|
|
453
|
+
: safeCloneElement(day, {
|
|
454
|
+
'aria-describedby': this._weekdayHeaderIds[i],
|
|
455
|
+
role: 'button'
|
|
456
|
+
})}
|
|
457
|
+
</td>
|
|
458
|
+
))}
|
|
459
|
+
</tr>
|
|
460
|
+
))
|
|
461
|
+
)
|
|
445
462
|
}
|
|
446
463
|
|
|
447
464
|
locale(): string {
|
|
@@ -524,6 +541,7 @@ class Calendar extends Component<CalendarProps, CalendarState> {
|
|
|
524
541
|
isToday={date.isSame(today, 'day')}
|
|
525
542
|
isOutsideMonth={!date.isSame(visibleMonth, 'month')}
|
|
526
543
|
label={date.format('D MMMM YYYY')} // used by screen readers
|
|
544
|
+
selectedLabel={this.props.selectedLabel}
|
|
527
545
|
onClick={this.handleDayClick}
|
|
528
546
|
interaction={this.isDisabledDate(date) ? 'disabled' : 'enabled'}
|
|
529
547
|
>
|
package/src/Calendar/v2/props.ts
CHANGED
|
@@ -130,6 +130,11 @@ type CalendarOwnProps = {
|
|
|
130
130
|
* ISO date string for the selected date. It needs onDateSelected to be specified too.
|
|
131
131
|
*/
|
|
132
132
|
selectedDate?: string
|
|
133
|
+
/**
|
|
134
|
+
* Screen reader label appended to the date label when the day is selected.
|
|
135
|
+
* Used to announce the selected state to assistive technologies.
|
|
136
|
+
*/
|
|
137
|
+
selectedLabel: string
|
|
133
138
|
/**
|
|
134
139
|
* A timezone identifier in the format: *Area/Location*
|
|
135
140
|
*
|
|
@@ -194,6 +199,7 @@ const allowedProps: AllowedPropKeys = [
|
|
|
194
199
|
'renderWeekdayLabels',
|
|
195
200
|
'role',
|
|
196
201
|
'selectedDate',
|
|
202
|
+
'selectedLabel',
|
|
197
203
|
'timezone',
|
|
198
204
|
'visibleMonth'
|
|
199
205
|
]
|