Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit 6480d71

Browse files
committed
feat(datepicker): fixes for a11y
1 parent a1844f7 commit 6480d71

File tree

7 files changed

+43
-25
lines changed

7 files changed

+43
-25
lines changed

src/components/calendar/calendar-theme.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
color: '{{primary-500}}'; // blue-500
1818
}
1919

20-
.md-calendar-date:focus {
20+
.md-calendar-date.md-focus {
2121
.md-calendar-date-selection-indicator {
2222
background-color: '{{background-300}}'; // grey-300
2323
}
@@ -29,7 +29,7 @@
2929

3030
// Selected style goes after hover and focus so that it takes priority.
3131
.md-calendar-date.md-calendar-selected-date,
32-
.md-calendar-date:focus.md-calendar-selected-date {
32+
.md-calendar-date.md-focus.md-calendar-selected-date {
3333
.md-calendar-date-selection-indicator {
3434
background-color: '{{primary-500}}'; // blue-500
3535
color: '{{primary-500-contrast}}'; // white

src/components/calendar/calendar.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414

1515
// PRE RELEASE
16-
// TODO(jelbourn): Base colors on the theme
1716
// TODO(jelbourn): read-only state.
1817
// TODO(jelbourn): Date "isComplete" logic
1918
// TODO(jelbourn): Apple + up / down == PgDown and PgUp
@@ -85,7 +84,7 @@
8584
$$mdDateUtil, $$mdDateLocale, $mdInkRipple, $mdUtil) {
8685

8786
/** @type {Array<number>} Dummy array-like object for virtual-repeat to iterate over. */
88-
this.items = {length: 2000 * 12};
87+
this.items = {length: 2000};
8988

9089
/** @final {!angular.$animate} */
9190
this.$animate = $animate;
@@ -120,6 +119,9 @@
120119
/** @final {HTMLElement} */
121120
this.ariaLiveElement = $element[0].querySelector('[aria-live]');
122121

122+
this.ariaLiveElement.parentNode.removeChild(this.ariaLiveElement);
123+
document.body.appendChild(this.ariaLiveElement);
124+
123125
/** @final {HTMLElement} */
124126
this.calendarScroller = $element[0].querySelector('.md-virtual-repeat-scroller');
125127

@@ -347,11 +349,18 @@
347349
* @param {Date=} opt_date
348350
*/
349351
CalendarCtrl.prototype.focus = function(opt_date) {
352+
this.$element[0].focus();
353+
354+
var previousFocus = this.calendarElement.querySelector('.md-focus');
355+
if (previousFocus) {
356+
previousFocus.classList.remove('md-focus');
357+
}
358+
350359
var date = opt_date || this.selectedDate;
351360
var cellId = this.getDateId(date);
352361
var cell = this.calendarElement.querySelector('#' + cellId);
353362
if (cell) {
354-
cell.focus();
363+
cell.classList.add('md-focus');
355364
} else {
356365
this.focusDate = date;
357366
}

src/components/calendar/calendarMonth.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
this.$element.empty();
7676
this.$element.append(this.buildCalendarForMonth(date));
7777
if (this.focusAfterAppend) {
78-
this.focusAfterAppend.focus();
78+
this.focusAfterAppend.classList.add('md-focus');
7979
this.focusAfterAppend = null;
8080
}
8181
};

src/components/calendar/datePicker-theme.scss

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
.md-datepicker-root.md-THEME_NAME-theme {
1+
md-datepicker.md-THEME_NAME-theme {
22
background: white;
3-
&[disabled] {
4-
background: '{{background-100}}';
5-
}
63
}
74

85
.md-datepicker-input-container {

src/components/calendar/datePicker.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
// TODO(jelbourn): aria attributes tying together date input and floating calendar.
88
// TODO(jelbourn): make sure this plays well with validation and ngMessages.
99
// TODO(jelbourn): forward more attributes to the internal input (required, autofocus, etc.)
10-
// TODO(jelbourn): floating panel open animation (see animation for menu in spec).
1110
// TODO(jelbourn): auto-grow input to accomodate longer dates
1211

1312
// POST RELEASE
@@ -19,20 +18,24 @@
1918

2019

2120
angular.module('material.components.calendar')
22-
.directive('mdDatePicker', datePickerDirective);
21+
.directive('mdDatepicker', datePickerDirective);
2322

2423
function datePickerDirective() {
2524
return {
2625
template:
26+
// Buttons are not in the tab order because users can open the calendar via keyboard
27+
// interaction on the text input, and multiple tab stops for one component (picker)
28+
// may be confusing.
2729
'<md-button class="md-datepicker-button md-icon-button" type="button" ' +
30+
'tabindex="-1" aria-label="Open calendar" ' +
2831
'ng-click="ctrl.openCalendarPane()">' +
2932
'<md-icon class="md-datepicker-calendar-icon" md-svg-icon="md-calendar"></md-icon>' +
3033
'</md-button>' +
3134
'<div class="md-datepicker-input-container">' +
3235
'<input class="md-datepicker-input">' +
3336

3437
'<md-button md-no-ink class="md-datepicker-triangle-button md-icon-button" ' +
35-
'ng-click="ctrl.openCalendarPane()">' +
38+
'ng-click="ctrl.openCalendarPane()" tabindex="-1" aria-label="Open calendar">' +
3639
'<div class="md-datepicker-expand-triangle"></div>' +
3740
'</md-button>' +
3841
'</div>' +
@@ -41,10 +44,11 @@
4144
'<div class="md-datepicker-calendar-pane md-whiteframe-z1">' +
4245
'<div class="md-datepicker-input-mask"></div>' +
4346
'<div class="md-datepicker-calendar">' +
44-
'<md-calendar ng-model="ctrl.date" ng-if="ctrl.isCalendarOpen"></md-calendar>' +
47+
'<md-calendar role="dialog" aria-label="Calendar" tabindex="0" ' +
48+
'ng-model="ctrl.date" ng-if="ctrl.isCalendarOpen"></md-calendar>' +
4549
'</div>' +
4650
'</div>',
47-
require: ['ngModel', 'mdDatePicker'],
51+
require: ['ngModel', 'mdDatepicker'],
4852
scope: {
4953
placeholder: '@mdPlaceholder'
5054
},
@@ -69,7 +73,7 @@
6973
* @ngInject @constructor
7074
*/
7175
function DatePickerCtrl($scope, $element, $attrs, $compile, $timeout, $mdConstant, $mdUtil,
72-
$$mdDateLocale, $$mdDateUtil, $mdMenu, $$rAF) {
76+
$$mdDateLocale, $$mdDateUtil, $$rAF) {
7377
/** @final */
7478
this.$compile = $compile;
7579

@@ -89,8 +93,6 @@
8993
this.$mdUtil = $mdUtil;
9094

9195
/** @final */
92-
this.$mdMenu = $mdMenu;
93-
9496
this.$$rAF = $$rAF;
9597

9698
/** @type {!angular.NgModelController} */
@@ -250,7 +252,7 @@
250252
calendarPane.style.top = (elementRect.top - bodyRect.top) + 'px';
251253
document.body.appendChild(this.calendarPane);
252254

253-
// Add CSS class after one frame to trigger animation.
255+
// Add CSS class after one frame to trigger open animation.
254256
this.$$rAF(function() {
255257
calendarPane.classList.add('md-pane-open');
256258
});

src/components/calendar/datePicker.scss

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,25 @@ $md-datepicker-button-gap: 12px;
3030
// The input into which the user can type the date.
3131
.md-datepicker-input {
3232
@include md-flat-input();
33-
width: 100%;
33+
min-width: 100%;
3434
}
3535

3636
// Container for the datepicker input.
3737
.md-datepicker-input-container {
38+
// Position relative in order to absolutely position the down-triangle button within.
3839
position: relative;
3940

41+
padding-bottom: 5px;
4042
border-bottom-width: 1px;
4143
border-bottom-style: solid;
4244

4345
display: inline-block;
4446
width: 120px;
4547
margin-left: $md-datepicker-button-gap;
48+
49+
md-datepicker[disabled] & {
50+
border-bottom-color: transparent;
51+
}
4652
}
4753

4854

@@ -89,7 +95,7 @@ $md-datepicker-button-gap: 12px;
8995
// Down triangle/arrow indicating that the datepicker can be opened.
9096
// We can do this entirely with CSS without needing to load an icon.
9197
// See https://css-tricks.com/snippets/css/css-triangle/
92-
$md-date-arrow-size: 6px;
98+
$md-date-arrow-size: 5px;
9399
.md-datepicker-expand-triangle {
94100
// Center the triangle inside of the button so that the
95101
// ink ripple origin looks correct.
@@ -111,6 +117,10 @@ $md-date-arrow-size: 6px;
111117
right: 0;
112118
top: 0;
113119
transform: translateY(-25%) translateX(45%);
120+
121+
md-datepicker[disabled] & {
122+
display: none;
123+
}
114124
}
115125

116126
// Need crazy specificity to override .md-button.md-icon-button.

src/components/calendar/demoDatePicker/index.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@ <h2>Development tools</h2>
1111
</p>
1212
<hr>
1313

14-
<md-date-picker ng-model="myDate" md-placeholder="Enter date"></md-date-picker>
14+
<md-datepicker ng-model="myDate" md-placeholder="Enter date"></md-datepicker>
1515

1616
<hr>
1717
<h3>Disabled with ng-disabled</h3>
18-
<md-date-picker ng-model="myDate" md-placeholder="Enter date" ng-disabled="true">
19-
</md-date-picker>
18+
<md-datepicker ng-model="myDate" md-placeholder="Enter date" ng-disabled="true">
19+
</md-datepicker>
2020

2121
<hr>
2222

2323
<h3>Disabled with static disabled attribute</h3>
24-
<md-date-picker ng-model="myDate" placeholder="Enter date" disabled></md-date-picker>
24+
<md-datepicker ng-model="myDate" placeholder="Enter date" disabled></md-datepicker>
2525

2626
<br><br>
2727
<br><br>

0 commit comments

Comments
 (0)