vigetlabs / ca11y

A lightweight accessible dependency-free datepicker
http://code.viget.com/ca11y
26 stars 6 forks source link

ca11y Circle CI

NPM

Stories in Ready

An accessible, light-weight, vanilla date picker < 6kb gzipped. Bring your own styles, or play off the demo.

npm install ca11y --save

This is a work in progress. Accessibility testing thus far has been through basic keyboard usage and Apple VoiceOver on OS X Safari. We would love more testing and advice from the community!

Demo Gif

http://code.viget.com/ca11y

Feedback, pull requests, bug reports and ideas for improvement. Got some? Head on over to issues.

Usage

Multiple instances by css selector:
import Ca11y from 'ca11y'
Ca11y.init('.date-picker', options)
Single input element:
import Ca11y from 'ca11y'
const input = document.getElementById('date-input')
const datePicker = new Ca11y(input, options)

Pass any of the options listed below to override the defaults.

Styling:

Ca11y just provides the markup and functionality. You're on the hook to provide css. Feel free to use the styles from the demo as a starting point. At the very least, you'll need to something like this to hide the date-picker when inactive:

.ca11y__picker[aria-hidden="true"] {
  display: none;
}

Options

Basic

options.container

const datePicker = new Ca11y(input, {
  container: input.parentElement // default
})

The HTML element where you want the datepicker to render.

options.toggle

const datePicker = new Ca11y(input, {
  toggle: this.ui.datePicker.querySelector('.ca11y__toggle') // default (dynamically created)
})

The HTML element that should toggle datepicker when clicked. Defaults to a dynamically created button.

options.format

const datePicker = new Ca11y(input, {
  format: ['mm', 'dd', 'yyyy'] // default
})

A an Array of date codes to specify your desired format. Joined with options.delimiter.

Available formats:

key value
d Day of the month as digits; no leading zero for single-digit days.
dd Day of the month as digits; leading zero for single-digit days.
ddd Day of the week as a three-letter abbreviation.
dddd Day of the week as its full name.
m Month as digits; no leading zero for single-digit months.
mm Month as digits; leading zero for single-digit months.
mmm Month as a three-letter abbreviation.
mmmm Month as its full name.
yy Year as last two digits; leading zero for years less than 10.
yyyy Year represented by four digits.

fullName and label values are read by screen readers. Provide transitionDuration if you are using the css transition property on the .ca11y__picker element to allow auto-focusing of the selected day on transition end.

options.delimiter

const datePicker = new Ca11y(input, {
  delimiter: "/" // default
})

The String used to join the date segments defined in the options.format Array.

options.transitionDuration

const datePicker = new Ca11y(input, {
  transitionDuration: 200 // default
})

If you are transitioning open and closing the calendar with CSS, specify the transitionDuration in milliseconds here.

options.autofill

const datePicker = new Ca11y(input, {
  autofill: false // default
})

Set to true if you want a blank input to be auto-filled with today's date.

options.onSelect

const datePicker = new Ca11y(input, {
  onSelect: onSelect(value, input, state, date) {
    input.value = value
  }  // default
})

The function that runs whenever a date is selected. By default, it sets the input value to the selected date, formatted as defined by format and delimiter.

Language

options.months

const datePicker = new Ca11y(input, {
  months: [
    { fullName: 'January', displayName: 'Jan', shortName: 'Jan' },
    ...
})

An Array of objects containing the fullName, displayName, and shortName of each month. fullName is what gets read by screen readers. displayName gets rendered to the calendar, and shortName is for usage with output formats. Override with other languages or desired text.

options.days

const datePicker = new Ca11y(input, {
  days: [
    { fullName: 'Sunday', displayName: 'S', shortName: 'Sun' } ,
    ...
})

Same format as `months`. Override with other languages or desired text.

#### `options.dayTitles`
```js
const datePicker = new Ca11y(input, {
dayTitles: [
  'First',
  'Second',
  ...
})

Read aloud by screen readers when a date receives focus. Override with other languages or desired text.

options.dayTitles

const datePicker = new Ca11y(input, {
dayTitles: [
  'First',
  'Second',
  ...
})

Read aloud by screen readers when a date receives focus. Override with other languages or desired text.

UI

options.toggleIcon

const datePicker = new Ca11y(input, {
  toggleIcon: "<svg>...</svg>" // defaults to Google material calendar icon
})

The icon to be rendered as the toggle button label. Defaults to svg iconography from https://design.google.com/icons/.

options.toggleAriaLabel

const datePicker = new Ca11y(input, {
  toggleAriaLabel: "Toggle the Datepicker" // default
})

The aria-label that should be read by a screen reader when the (default) toggle button is focused.

options.next

const datePicker = new Ca11y(input, {
  next: {
    html: '<button>Next</button>',
    label: 'Next Month'
  }
})

The html will be rendered as the next month button. The label is screen-reader only. Defaults to svg iconography from https://design.google.com/icons/.

prev

const datePicker = new Ca11y(input, {
  prev: {
    html: '<button>Prev</button>',
    label: 'Previous Month'
  }
})

The html will be rendered as the previous month button. The label is screen-reader only. Defaults to svg iconography from https://design.google.com/icons/.

Advanced

parser

See default.

formatter

See default.

HTML5 Date Inputs and Ca11y

Ca11y upgrades standard text inputs to date-pickers. If you're interested in using the native HTML5 date-picker via <input type="date">, consider loading Ca11y based on a feature test, like this one (pulled from Modernizr):

function isDateInputSupported() {
    var input = document.createElement('input')
    input.setAttribute('type', 'date')
    var isDate = input.type !== 'text' && 'style' in input
    var testValue = '1)'
    if (isDate) {
        input.value = testValue
        input.style.cssText = 'position:absolute;visibility:hidden;'
        isDate = input.value != testValue
    }
    return isDate
}

Demo Locally

npm install
npm start

Deploy to GitHub Pages

npm run deploy

--

Check out other open source work happening at Viget on code.viget.com