React-ADA-Keyboard-Accessible-Datepicker is an easy to implement date picker compliant with the standards set out by the Americans with Disabilities Act, including features such as full keyboard accessibility and aria labeling. The package builds upon the date picker developed by w3.org ( https://www.w3.org/TR/wai-aria-practices/examples/dialog-modal/datepicker-dialog.html ) and and adds several options for customization and easy React integrations.
React-ADA-Keyboard-Accessible-Datepicker includes several features to help make its use more accessible to all.
- When a date is chosen, the accessible name of the “Choose Date” button is updated to include the selected date. So, when the dialog closes and focus returns to the “Choose Date” button, screen reader users hear confirmation of the selected date in the button name.
- When the month or year of the calendar grid changes as users navigate the calendar or activate the buttons for next or previous month or year, a live region enables screen readers to announce the new month and year.
- The calendar grid provides hotkeys for changing the year and month as well as support for normal grid navigation keys.
- When the dialog opens and a date in the calendar grid receives focus, a live region enables screen readers to announce keyboard instructions for navigating the calendar grid. The instructions are also visible at the bottom of the dialog box.
- A numbr of customization options including auto complete dates, date ranges, and more.
Use npm to install React-ADA-Keyboard-Accessible-Datepicker
npm install react-ada-keyboard-accessible-datepicker
import React from 'react';
import Datepicker from 'react-ada-keyboard-accessible-datepicker'
const DatePickerContainer = () =>{
return(
<div>
<Datepicker />
</div>
)
}
Choose Date Button
Key | Function |
---|---|
Space, Enter |
* Open the date picker dialog. * Move focus to selected date, i.e., the date displayed in the date input text field. If no date has been selected, places focus on the current date. |
Date Picker Dialog
Key | Function |
---|---|
ESC | Closes the dialog and returns focus to the Choose Date button. |
Tab | * Moves focus to next element in the dialog Tab sequence. * Note that, as specified in the grid design pattern, only one button in the calendar grid is in the Tab sequence. * If focus is on the last button (i.e., OK), moves focus to the first button(i.e. Previous Year). |
Date Picker Dialog: Month/Year Buttons
Key | Function |
---|---|
Space, Enter |
Change the month and/or year displayed in the calendar grid. |
Date Picker Dialog: Date Grid
Key | Function |
---|---|
Space, Enter |
* Select the date, close the dialog, and move focus to the Choose Date button. * Update the value of the Date input with the selected date. * Update the accessible name of the Choose Date button to include the selected date. |
Up Arrow | Moves focus to the same day of the previous week. |
Down Arrow | Moves focus to the same day of the next week. |
Right Arrow | Moves focus to the next day. |
Left Arrow | Moves focus to the previous day. |
Home | Moves focus to the first day (e.g Sunday) of the current week. |
End | Moves focus to the last day (e.g. Saturday) of the current week. |
Page Up | *Changes the grid of dates to the previous month. *Sets focus on the same day of the same week. If that day does not exist, then moves focus to the same day of the previous or next week. |
Shift + Page Up | *Changes the grid of dates to the previous Year. *Sets focus on the same day of the same week. If that day does not exist, then moves focus to the same day of the previous or next week. |
Page Down | *Changes the grid of dates to the next month. *Sets focus on the same day of the same week. If that day does not exist, then moves focus to the same day of the previous or next week. |
Shift + Page Down | *Changes the grid of dates to the next Year. *Sets focus on the same day of the same week. If that day does not exist, then moves focus to the same day of the previous or next week. |
Date Picker Dialog: OK and Cancel Buttons
Key | Function |
---|---|
Space, Enter |
Activates the button: *"Cancel": Closes the dialog, moves focus to Choose Date button, does not update date in date input. *OK: Closes the dialog, moves focus to Choose Date button, updates date in date input. |
Chose Date Button
Role | Attribute | Element | Usage |
---|---|---|---|
aria-label="String" | button | The initial value of accessible name is "Choose Date". When users select a date, the accessible name is updated to also include the selected date. |
Date Picker Dialog
Role | Attribute | Element | Usage |
---|---|---|---|
dialog | div | Identifies the element as a dialog . | |
aria-modal="true" | div | Indicates the dialog is modal. | |
aria-labelledby="IDREF" | div | Refers to the heading containing the currently displayed month and year, which defines the accessible name for the dialog. |
|
aria-live="polite" | div | *Indicates the element that displays information about keyboard commands for navigating the grid should be automatically announced by screen readers. *The script slightly delays display of the information so screen readers are more likely to read it after information related to change of focus. |
Date Picker Dialog: Calendar Navigation Buttons
Role | Attribute | Element | Usage |
---|---|---|---|
aria-label="String" | button | Defines the accessible name of the button (e.g. Next Year). |
|
aria-live="polite" | h2 | *When the month and/or year changes the content of the h2 element is updated. *Indicates the h2 should be automatically announced by screen readers. |
Date Picker Dialog: Date Grid
Role | Attribute | Element | Usage |
---|---|---|---|
grid | table | *Identifies the table element as a grid widget. *Since the grid role is applied to a table element, the row, colheader, and gridcell roles to be specified because they are implied by th, and tdtags. |
|
aria-labelledby=IDREF | table | Defines the accessible name for the grid using the h2 that shows the month and year of the dates displayed in the grid. |
|
tabindex="0" | button | *Makes the button focusable and includes it in the dialog Tab sequence. *Set dynamically by the JavaScript when the element is to be included in the dialog Tab sequence. *At any given time, only one button within the grid is in the dialog Tab sequence. *This approach to managing focus is described in the section on roving tabindex. |
|
tabindex="-1" | button | Makes the button focusable and excludes it from the dialog Tab sequence. *Changed dynamically to 0 by the JavaScript when the button is to be included in the dialog Tab sequence. *At any given time, only one button within the grid is in the dialog Tab sequence. *This approach to managing focus is described in the section on roving tabindex. |
|
aria-selected="true" | button | *Identifies the button for the currently selected date, i.e., the date value present in the date input. *Only set on the button representing the currently selected date, no other buttons have aria-selectedspecified. |
The date picker allows several levels of customization to acccomodate developers needs. Customizations are generally passed into the component as props. Additional levels of customization will be available in future releases.
themeColor
Applies a selected color to the calendar button and calendar borders
const DatePickerContainer = () =>{
return(
<div>
< Datepicker themeColor={"#B41C1C"} />
</div>
)
}
dateFormat
Dates will be formatted to mm/dd/yyyy by default, but custom formats may be passed in as a string. The month field must be repressed by mm, the date by dd, and the year by yyyy. Fields may be separated by forward slashes, commas or spaces[/ , ]. User input will be automatically formatted unless autoFormatting={false} is passed in as a prop.
const DatePickerContainer = () =>{
return(
<div>
< Datepicker dateFormat={"yyyy,mm,dd"} />
</div>
)
}
minDate
-Sets the earliest day that the user may choose by using the datepicker. All date cells before the minDate will be disabled. Combing the minDate prop with maxDate will create a date range. Users will not be able to naviagate to the dates outside of the range. minDate must be passed in with the “yyyy-mm-dd” format. To set the min date to the current date pass in minDate={“today”}
const DatePickerContainer = () =>{
return(
<div>
< Datepicker
minDate={"2019-12-25"}
# ----- OR -------
minDate={"today"}
/>
</div>
)
}
maxDate
Sets the latest date that the user may choose by using the date picker. All date cells after the maxDate will be disabled. Combining the maxDate with mandate will create a date range. Users will not be able to naviagate to the dates outside of the range. maxDate must be passed in with the “yyyy-mm-dd” format. To set the min date to the current date pass in maxDate={“today”}
const DatePickerContainer = () =>{
return(
<div>
< Datepicker
maxDate={"2017-10-12"}
# ----- OR -------
maxDate={"today"}
/>
</div>
)
}
specifiedFocusDate
You can specifiy which date that the datepicker will open to by passing in specifiedFocusDate={"yyyy-mm-dd"}
const DatePickerContainer = () =>{
return(
<div>
< Datepicker
specifiedFocusDate={"2019-10-15"}
/>
</div>
)
}
buttonInlineStyle
Customized styling can be passed to the calendar button as a style object. Object keys follow JSX conventions. Alternatively, class names from your own stylesheet can be passed to the calendar button with the buttonClassNames prop.
const buttonInlineStyle = {"color": "orange", "marginLeft": "30px"}
const DatePickerContainer = () =>{
return(
<div>
< Datepicker
buttonInlineStyle={buttonInlineStyle}
/>
</div>
)
}
buttonClassNames
One of more classes can be passed to the calendar button through the buttonClassNames prop as a string. Seperate the classes by a space Be sure to pass in names without a prepending period.
const DatePickerContainer = () =>{
return(
<div>
< Datepicker
buttonClassNames={"cssClass1 cssClass2 cssClass3"}
/>
</div>
)
}
customInputBox
Save a custom input box as a variable and pass it in as a prob. Note, you will have ot provide your own ARIA labels.
const DatePickerContainer = () =>{
const customInputBox = <input id="Custom-Box" placeholder="this is a custom inputBox" style={{'backgroundColor': 'red'}}></input>
return(
<div>
< Datepicker
customInputBox={customInputBox}
/>
</div>
)
}
inputBoxLabel
Pass in a string for a custom input box label, or pass in false to remove the default label.
const DatePickerContainer = () =>{
const customInputBox = <input id="Custom-Box" placeholder="this is a custom inputBox" style={{'backgroundColor': 'red'}}></input>
return(
<div>
< Datepicker
inputBoxLabel={"This is a custom label"}
# OR
inputBoxLabel={false}
/>
</div>
)
}
inputBoxClassNames
One of more classes can be passed as strings to the input box through the inputBoxClassNames prop. Be sure to pass in names without a prepending period.
const DatePickerContainer = () =>{
return(
<div>
< Datepicker
inputBoxClassNames={"cssClass1 cssClass2 cssClass3"}
/>
</div>
)
}
Error Handling
The datepicker comes with default internal error handling, but it is possible to passs in custom error messages through props. all of the following must be passed in as strings
invalidFormatError - This message will be displated when a user enters the date in an invaliud format
invalidMonthErrorMessage - This message will be displayed when a user enters a mm(month) value greater than 12
invalidDateErrorMessage - This message will be displayed when a user enters a dd(day) value greater than 31
pastMaxDateErrorMessage - This message will be displayted when there is a Maximum date prop passed into the datepicker and the user enters a date past that
minDateErrorMessage - This message will be displayted when there is a minimum date prop passed into the datepicker and the user enters a date before that
const DatePickerContainer = () =>{
return(
<div>
< Datepicker
invalidDateErrorMessage={" Month invalid, please check the month"}
/>
</div>
)
}
If you would prefer to handle error on your application level rather than internally through the datepicker, and alternative can be to pass in the errorHandlingCallback. and wrapping the datepicker in its own component with its own state. Set a field on the state called errorType. Write a function that will invoke this.setState and pass it into the errorHandlingCallback. An example can be seen below. Passing in errorHandlingCallback will disable the internally generated error messages.
For Class Based Components :
import React,{useState, Fragment, Component} from 'react';
import Datepicker from 'react-ada-keyboard-accessible-datepicker';
import './testStyle.css'
class ClassBasedCalContainer extends Component {
constructor(props){
super(props);
this.state = {
errorType: null
}
this.setStateCallBack = this.setStateCallBack.bind(this);
}
setStateCallBack(messageType){
this.setState({errorType: messageType})
}
render(){
return(
<div>
<h1>CLASS BASED COMPONENT CONTAINER</h1>
<h2>{`The State message is ${this.state.errorType}`}</h2>
<Datepicker
errorHandlingCallback ={this.setStateCallBack}
minDate={"today"} //eventually make this so it follows format
maxDate={"2019-12-25"}
/>
</div>
)
}
}
}
For Functional Components:
const CalendarContainer = () =>{
const [errorType, setErrorType] = useState(null)
return(
<div>
<h1 >CALANDER CONTAINER APP</h1>
<h2>{`The errorType is ${errorType}`}</h2>
<Datepicker
specifiedFocusDate={"2019-10-15"}
dateFormat ={"mm dd, yyyy"}
minDate={"today"}
maxDate={"2019-12-25"}
errorHandlingCallback ={setErrorType}
/>
</div>
)
}
You can use the errorType const to write the logic for determining your errorType messages and errorHandling behavior.
inputBoxOnChange
Callback that will be executed on input box change (under development)
inputBoxOnBlur
Callback that will be executed on input box blur (under development)
autoFormat
Auto formatting of user input can be turned off by passing in autoFormatting={false}. (under development)
History
v1.2.12
- Improvements to autopcomplete functionality
- Formatting error message only appears entire datepicker's blur
- Errors in console for incorrect datadate format with min and max date props
v1.2.9
- Improved documentation readibility.
v1.2.3
- Removed default "Cursor keys can navigate dates" message"
- Calander height now changes to fit dates
v1.2.2
- Added leading zeros into dateBoxInput string in roder to facilitate error handling and follow project formatting
v1.2.1
- Fixes bug that causes DOM propagation on go to next year and go to previous year buttons.
v1.2.0
- input box now calculates latest day of each month and throws error if entered date is beyond that
- simplified autoformating that allows for easier revisions to input date
- updated documentation with screenshots and keyboard controls
v1.1.4
- custom iput boxs without ids are automatically assigned id of "id-textbox-1"
- error messages nor use the htmlFor attribute and point ot inputBox
- inputBox ariaDescribedby pointsx to the error message
- updates to documentation