import ChevronLeftIcon from '../../components/icons/ChevronLeftIcon';
import ChevronRightIcon from '../../components/icons/ChevronRightIcon';
import {
+ getMonthName,
getShortMonthName,
getShortWeekDayName,
getWeekDayName,
type Week = [string, string, string, string, string, string, string];
-const LAST_MONTH_INDEX = 11;
+const MONTH_IN_YEAR = 12;
export default class DateInput extends React.PureComponent<Props, State> {
input?: HTMLInputElement | null;
getPreviousMonthAriaLabel = () => {
const { currentMonth } = this.state;
- return currentMonth.getMonth() === 0
- ? translateWithParameters(
- 'show_month_x_of_year_y',
- getShortMonthName(LAST_MONTH_INDEX),
- currentMonth.getFullYear() - 1
- )
- : translateWithParameters(
- 'show_month_x_of_year_y',
- getShortMonthName(currentMonth.getMonth() - 1),
- currentMonth.getFullYear()
- );
+ const previous = (currentMonth.getMonth() + MONTH_IN_YEAR - 1) % MONTH_IN_YEAR;
+
+ return translateWithParameters(
+ 'show_month_x_of_year_y',
+ getMonthName(previous),
+ currentMonth.getFullYear() - Math.floor(previous / (MONTH_IN_YEAR - 1))
+ );
};
getNextMonthAriaLabel = () => {
const { currentMonth } = this.state;
- return currentMonth.getMonth() === LAST_MONTH_INDEX
- ? translateWithParameters(
- 'show_month_x_of_year_y',
- getShortMonthName(0),
- currentMonth.getFullYear() + 1
- )
- : translateWithParameters(
- 'show_month_x_of_year_y',
- getShortMonthName(currentMonth.getMonth() + 1),
- currentMonth.getFullYear()
- );
+
+ const next = (currentMonth.getMonth() + MONTH_IN_YEAR + 1) % MONTH_IN_YEAR;
+
+ return translateWithParameters(
+ 'show_month_x_of_year_y',
+ getMonthName(next),
+ currentMonth.getFullYear() + 1 - Math.ceil(next / (MONTH_IN_YEAR - 1))
+ );
};
render() {
const after = this.props.maxDate || new Date();
- const months = range(12);
+ const months = range(MONTH_IN_YEAR);
const years = range(new Date().getFullYear() - 10, new Date().getFullYear() + 1);
const selectedDays: Modifier[] = value ? [value] : [];
/>
)}
{open && (
- <div className={classNames('date-input-calendar', { 'align-right': alignRight })}>
- <nav className="date-input-calendar-nav">
+ <form className={classNames('date-input-calendar', { 'align-right': alignRight })}>
+ <fieldset
+ className="date-input-calendar-nav"
+ aria-label={translateWithParameters(
+ 'date.select_month_and_year_x',
+ `${getMonthName(currentMonth.getMonth())}, ${currentMonth.getFullYear()}`
+ )}
+ >
<ButtonIcon
className="button-small"
aria-label={this.getPreviousMonthAriaLabel()}
>
<ChevronRightIcon />
</ButtonIcon>
- </nav>
+ </fieldset>
<DayPicker
captionElement={<NullComponent />}
disabledDays={{ after, before: minDate }}
weekdaysLong={weekdaysLong}
weekdaysShort={weekdaysShort}
/>
- </div>
+ </form>
)}
</span>
</EscKeydownHandler>
it('should announce the proper month and year for next/previous buttons aria label', () => {
const { wrapper, instance } = shallowRender();
expect(wrapper.state().currentMonth).toEqual(dateA);
- expect(instance.getPreviousMonthAriaLabel()).toEqual('show_month_x_of_year_y.Dec.2017');
- expect(instance.getNextMonthAriaLabel()).toEqual('show_month_x_of_year_y.Feb.2018');
+ expect(instance.getPreviousMonthAriaLabel()).toEqual('show_month_x_of_year_y.December.2017');
+ expect(instance.getNextMonthAriaLabel()).toEqual('show_month_x_of_year_y.February.2018');
instance.handleCurrentMonthChange({ value: 11 });
- expect(instance.getPreviousMonthAriaLabel()).toEqual('show_month_x_of_year_y.Nov.2018');
- expect(instance.getNextMonthAriaLabel()).toEqual('show_month_x_of_year_y.Jan.2019');
+ expect(instance.getPreviousMonthAriaLabel()).toEqual('show_month_x_of_year_y.November.2018');
+ expect(instance.getNextMonthAriaLabel()).toEqual('show_month_x_of_year_y.January.2019');
});
function shallowRender(props?: Partial<DateInput['props']>) {