Skip to content

Commit

Permalink
Adds availability information to CalendarDay aria label
Browse files Browse the repository at this point in the history
  • Loading branch information
Maja Wichrowska committed Mar 7, 2017
1 parent 1509c25 commit 7c1e502
Show file tree
Hide file tree
Showing 13 changed files with 89 additions and 48 deletions.
2 changes: 2 additions & 0 deletions constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ module.exports = {

ANCHOR_LEFT: 'left',
ANCHOR_RIGHT: 'right',

BLOCKED_MODIFIER: 'blocked',
};
1 change: 0 additions & 1 deletion css/DayPickerNavigation.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

&:active {
background: darken($react-dates-color-white, 5%);
// outline: 0;
}
}

Expand Down
2 changes: 1 addition & 1 deletion css/variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ $react-dates-color-gray: #565a5c !default;
$react-dates-color-gray-dark: darken($react-dates-color-gray, 10.5%) !default;
$react-dates-color-gray-light: lighten($react-dates-color-gray, 17.8%) !default; // #82888a
$react-dates-color-gray-lighter: lighten($react-dates-color-gray, 45%) !default; // #cacccd
$react-dates-color-gray-lightest: #eeeeee;
$react-dates-color-gray-lightest: lighten($react-dates-color-gray, 60%) !default;
$react-dates-color-highlighted: #ffe8bc !default;

$react-dates-color-border: #dbdbdb !default;
Expand Down
42 changes: 32 additions & 10 deletions src/components/CalendarDay.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import { forbidExtraProps } from 'airbnb-prop-types';
import moment from 'moment';
import cx from 'classnames';

import { CalendarDayPhrases } from '../defaultPhrases';
import getPhrasePropTypes from '../utils/getPhrasePropTypes';

import { BLOCKED_MODIFIER } from '../../constants';

const propTypes = forbidExtraProps({
day: momentPropTypes.momentObj,
isOutsideDay: PropTypes.bool,
Expand All @@ -14,6 +19,9 @@ const propTypes = forbidExtraProps({
onDayMouseEnter: PropTypes.func,
onDayMouseLeave: PropTypes.func,
renderDay: PropTypes.func,

// internationalization
phrases: PropTypes.shape(getPhrasePropTypes(CalendarDayPhrases)),
});

const defaultProps = {
Expand All @@ -25,6 +33,9 @@ const defaultProps = {
onDayMouseEnter() {},
onDayMouseLeave() {},
renderDay: null,

// internationalization
phrases: CalendarDayPhrases,
};

export function getModifiersForDay(modifiers, day) {
Expand Down Expand Up @@ -65,30 +76,41 @@ export default class CalendarDay extends React.Component {
modifiers,
renderDay,
isFocused,
phrases: { unavailable, available },
} = this.props;

if (!day) return <td />;

const modifiersForDay = getModifiersForDay(modifiers, day);

const className = cx('CalendarDay', {
'CalendarDay--outside': !day || isOutsideDay,
}, getModifiersForDay(modifiers, day).map(mod => `CalendarDay--${mod}`));
'CalendarDay--outside': isOutsideDay,
}, modifiersForDay.map(mod => `CalendarDay--${mod}`));


let availabilityText = '';
if (BLOCKED_MODIFIER in modifiers) {
availabilityText = modifiers[BLOCKED_MODIFIER](day) ? unavailable : available;
}

const ariaLabel = `${availabilityText} ${day.format('dddd')}. ${day.format('LL')}`;

return (day ?
return (
<td className={className}>
<button
type="button"
ref={(ref) => { this.buttonRef = ref; }}
className="CalendarDay__button"
aria-label={`${day.format('dddd')}. ${day.format('LL')}`}
onMouseEnter={e => this.onDayMouseEnter(day, e)}
onMouseLeave={e => this.onDayMouseLeave(day, e)}
onMouseUp={e => e.currentTarget.blur()}
onClick={e => this.onDayClick(day, e)}
aria-label={ariaLabel}
onMouseEnter={(e) => { this.onDayMouseEnter(day, e); }}
onMouseLeave={(e) => { this.onDayMouseLeave(day, e); }}
onMouseUp={(e) => { e.currentTarget.blur(); }}
onClick={(e) => { this.onDayClick(day, e); }}
tabIndex={isFocused ? 0 : -1}
>
{renderDay ? renderDay(day) : day.format('D')}
</button>
</td>
:
<td />
);
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/components/CalendarMonth.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import { forbidExtraProps } from 'airbnb-prop-types';
import moment from 'moment';
import cx from 'classnames';

import { CalendarDayPhrases } from '../defaultPhrases';
import getPhrasePropTypes from '../utils/getPhrasePropTypes';

import CalendarDay from './CalendarDay';

import getCalendarMonthWeeks from '../utils/getCalendarMonthWeeks';
Expand Down Expand Up @@ -35,6 +38,7 @@ const propTypes = forbidExtraProps({

// i18n
monthFormat: PropTypes.string,
phrases: PropTypes.shape(getPhrasePropTypes(CalendarDayPhrases)),
});

const defaultProps = {
Expand All @@ -52,6 +56,7 @@ const defaultProps = {

// i18n
monthFormat: 'MMMM YYYY', // english locale
phrases: CalendarDayPhrases,
};

export default class CalendarMonth extends React.Component {
Expand Down Expand Up @@ -87,6 +92,7 @@ export default class CalendarMonth extends React.Component {
onDayMouseLeave,
renderDay,
focusedDate,
phrases,
} = this.props;

const { weeks } = this.state;
Expand Down Expand Up @@ -119,6 +125,7 @@ export default class CalendarMonth extends React.Component {
onDayMouseLeave={onDayMouseLeave}
onDayClick={onDayClick}
renderDay={renderDay}
phrases={phrases}
/>
))}
</tr>
Expand Down
12 changes: 10 additions & 2 deletions src/components/CalendarMonthGrid.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import moment from 'moment';
import cx from 'classnames';
import { addEventListener, removeEventListener } from 'consolidated-events';

import { CalendarDayPhrases } from '../defaultPhrases';
import getPhrasePropTypes from '../utils/getPhrasePropTypes';

import CalendarMonth from './CalendarMonth';

import isTransitionEndSupported from '../utils/isTransitionEndSupported';
Expand Down Expand Up @@ -38,6 +41,7 @@ const propTypes = forbidExtraProps({

// i18n
monthFormat: PropTypes.string,
phrases: PropTypes.shape(getPhrasePropTypes(CalendarDayPhrases)),
});

const defaultProps = {
Expand All @@ -59,6 +63,7 @@ const defaultProps = {

// i18n
monthFormat: 'MMMM YYYY', // english locale
phrases: CalendarDayPhrases,
};

function getMonths(initialMonth, numberOfMonths) {
Expand Down Expand Up @@ -158,6 +163,7 @@ export default class CalendarMonthGrid extends React.Component {
onMonthTransitionEnd,
focusedDate,
calendarMonthWidth,
phrases,
} = this.props;


Expand All @@ -172,9 +178,10 @@ export default class CalendarMonthGrid extends React.Component {
'CalendarMonthGrid--animating': isAnimating,
});

const style = Object.assign({
const style = {
width: isHorizontal ? (numberOfMonths + 1) * calendarMonthWidth : calendarMonthWidth,
}, getTransformStyles(transformValue));
...getTransformStyles(transformValue),
};

return (
<div
Expand All @@ -200,6 +207,7 @@ export default class CalendarMonthGrid extends React.Component {
onDayClick={onDayClick}
renderDay={renderDay}
focusedDate={isVisible ? focusedDate : null}
phrases={phrases}
/>
);
})}
Expand Down
31 changes: 13 additions & 18 deletions src/components/DateInput.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ const defaultProps = {
displayValue: '',
inputValue: '',
screenReaderMessage: '',
focused: false, // handles actual DOM focus
selected: false, // stylizes the input to indicate that it will be filled
focused: false,
selected: false,
disabled: false,
required: false,
showCaret: false,
Expand Down Expand Up @@ -94,22 +94,17 @@ export default class DateInput extends React.Component {
onKeyDownQuestionMark,
} = this.props;

switch (e.key) {
case 'Tab':
if (e.shiftKey) {
onKeyDownShiftTab(e);
} else {
onKeyDownTab(e);
}
break;
case 'ArrowDown':
onKeyDownArrowDown(e);
break;
case '?':
onKeyDownQuestionMark(e);
break;
default:
// do nothing
const { key } = e;
if (key === 'Tab') {
if (e.shiftKey) {
onKeyDownShiftTab(e);
} else {
onKeyDownTab(e);
}
} else if (key === 'ArrowDown') {
onKeyDownArrowDown(e);
} else if (key === '?') {
onKeyDownQuestionMark(e);
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/components/DayPicker.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -511,12 +511,12 @@ export default class DayPicker extends React.Component {
if (orientation === VERTICAL_SCROLLABLE) {
onNextMonthClick = this.multiplyScrollableMonths;
} else {
onNextMonthClick = e => this.onNextMonthClick(null, e);
onNextMonthClick = (e) => { this.onNextMonthClick(null, e); };
}

return (
<DayPickerNavigation
onPrevMonthClick={e => this.onPrevMonthClick(null, e)}
onPrevMonthClick={(e) => { this.onPrevMonthClick(null, e); }}
onNextMonthClick={onNextMonthClick}
navPrev={navPrev}
navNext={navNext}
Expand Down Expand Up @@ -675,6 +675,7 @@ export default class DayPicker extends React.Component {
onMonthTransitionEnd={this.updateStateAfterMonthTransition}
monthFormat={monthFormat}
focusedDate={shouldFocusDate ? focusedDate : null}
phrases={phrases}
/>

{verticalScrollable && this.renderNavigation()}
Expand Down
12 changes: 6 additions & 6 deletions src/components/DayPickerKeyboardShortcuts.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,6 @@ export default function DayPickerKeyboardShortcuts({
{phrases.keyboardShortcuts}
</div>

<ul className="DayPickerKeyboardShortcuts__list">
{keyboardShortcuts.map(({ unicode, label, action }) => (
<KeyboardShortcutRow key={label} unicode={unicode} label={label} action={action} />
))}
</ul>

<button
className="DayPickerKeyboardShortcuts__close"
type="button"
Expand All @@ -131,6 +125,12 @@ export default function DayPickerKeyboardShortcuts({
>
<CloseButton />
</button>

<ul className="DayPickerKeyboardShortcuts__list">
{keyboardShortcuts.map(({ unicode, label, action }) => (
<KeyboardShortcutRow key={label} unicode={unicode} label={label} action={action} />
))}
</ul>
</div>
}
</div>
Expand Down
2 changes: 0 additions & 2 deletions src/components/SingleDatePicker.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import Portal from 'react-portal';
import { forbidExtraProps } from 'airbnb-prop-types';
import { addEventListener, removeEventListener } from 'consolidated-events';

import { SingleDatePickerPhrases } from '../defaultPhrases';

import OutsideClickHandler from './OutsideClickHandler';
import toMomentObject from '../utils/toMomentObject';
import toLocalizedDateString from '../utils/toLocalizedDateString';
Expand Down
15 changes: 15 additions & 0 deletions src/defaultPhrases.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const moveFocustoStartAndEndOfWeek = 'Navigate to the beginning or end of the cu
const returnFocusToInput = 'Return focus to the input field';
const keyboardNavigationInstructions = `Press the down arrow to select a date using the calendar
interface. Press ? to explore a list of all possible keyboard shortcuts.`;
const available = 'Available.';
const unavailable = 'Unavailable.';

export default {
closeDatePicker,
Expand All @@ -49,6 +51,8 @@ export default {
moveFocustoStartAndEndOfWeek,
returnFocusToInput,
keyboardNavigationInstructions,
available,
unavailable,
};

export const DateRangePickerPhrases = {
Expand All @@ -75,6 +79,8 @@ export const DateRangePickerPhrases = {
moveFocustoStartAndEndOfWeek,
returnFocusToInput,
keyboardNavigationInstructions,
available,
unavailable,
};

export const DateRangePickerInputPhrases = {
Expand Down Expand Up @@ -106,6 +112,8 @@ export const SingleDatePickerPhrases = {
moveFocustoStartAndEndOfWeek,
returnFocusToInput,
keyboardNavigationInstructions,
available,
unavailable,
};

export const SingleDatePickerInputPhrases = {
Expand Down Expand Up @@ -133,6 +141,8 @@ export const DayPickerPhrases = {
moveFocusByOneMonth,
moveFocustoStartAndEndOfWeek,
returnFocusToInput,
available,
unavailable,
};

export const DayPickerKeyboardShortcutsPhrases = {
Expand All @@ -159,3 +169,8 @@ export const DayPickerNavigationPhrases = {
jumpToPrevMonth,
jumpToNextMonth,
};

export const CalendarDayPhrases = {
available,
unavailable,
};
3 changes: 0 additions & 3 deletions src/shapes/DateRangePickerShape.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ import FocusedInputShape from '../shapes/FocusedInputShape';
import OrientationShape from '../shapes/OrientationShape';
import anchorDirectionShape from '../shapes/AnchorDirectionShape';

import { DateRangePickerPhrases } from '../defaultPhrases';
import getPhrasePropTypes from '../utils/getPhrasePropTypes';

export default {
// required props for a functional interactive DateRangePicker
startDate: momentPropTypes.momentObj,
Expand Down
3 changes: 0 additions & 3 deletions src/shapes/SingleDatePickerShape.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ import getPhrasePropTypes from '../utils/getPhrasePropTypes';
import OrientationShape from '../shapes/OrientationShape';
import anchorDirectionShape from '../shapes/AnchorDirectionShape';

import { SingleDatePickerPhrases } from '../defaultPhrases';
import getPhrasePropTypes from '../utils/getPhrasePropTypes';

export default {
// required props for a functional interactive SingleDatePicker
date: momentPropTypes.momentObj,
Expand Down

0 comments on commit 7c1e502

Please sign in to comment.