Rytm WCAG helpers, include:
- Toggle contrast version and store user cookie
- Handle keyboard events for focus visibility:
<html class="wcag-using-keyboard">
- Set a focus trap on dialog modals, eg. menus or dropdowns
- Handle a jump to event (for first focusable link on page)
- Handle focus update on ajax requests for any SPA like webapp
Install using NPM:
$ npm install rytm-wcag --save
import { WCAG } from 'rytm-wcag';
// init WCAG
WCAG.init()
Toggle high contrast version
<!--
this by default will toggle the cookie "r_wcag_contrast"
value 1 and 0 as well as toggle the document class "wcag-contrast"
-->
<a href="#" class="wcag-contrast-toggle">...</a>
Show focus on keyboard input (SCSS)
a, button, .btn, input, select, textarea, h2 {
&:focus {
box-shadow: none;
outline: none;
}
}
html.wcag-using-tab {
a, button, .btn, input, select, textarea, h2 {
&:focus {
outline: 4px solid $gray-500 !important;
}
}
}
Set a focus trap on dialogs
<a href="#" data-dialog-toggle="menu-open" data-target="#hambruger-menu">...</a>
<div id="hambruger-menu">
<button data-dialog-close="menu-open" type="button">
×
</button>
<!-- ... -->
</div>
Add a jump to link on page's header (first focus)
<!--
this will by default:
a) scroll to #main-content
b) set focus to the first <h2> or any other
focusable element under #main-content
-->
<a href="#" data-focus-to="#main-content">
...
</a>
Handle focus update on SPA ajax page loads
<h1 class="sr-only as-focus-to">
...
</h1>
On any ajax request
// whenever an view updates...
function onMyCustomEvent() {
// this will:
// a) close all dialogs
// b) set focus to ".as-focus-to"
WCAG.onViewChanged()
}
You can pass custom params:
WCAG.init({contrastCookieName: "my_cookie"})
...and custom events:
WCAG.init({}, {onContrastEnable: () => { //... })
{
// ## WCAG keyboard
// class name added when any keyboard key pressed
keyboardClassName: "wcag-using-keyboard",
// class name added when TAB key pressed
keyboardTabClassName: "wcag-using-tab",
// ## WCGA contrast
// contrast toggler selector
contrastToggleSelector: ".wcag-contrast-toggle",
// document class name for high contrast
contrastClassName: "wcag-contrast",
// user cookie name for high contrast (value 1 or 0)
contrastCookieName: "r_wcag_contrast",
// ## WCAG dialog focus trap
// selector for "dialog toggler" (multiple dialogs allowed)
dialogToggleSelector: "*[data-dialog-toggle]",
// selector for "dialog toggler" (only one dialog allowed)
dialogToggleOneSelector: "*[data-dialog-one]",
// selector for "dialog close"
dialogCloseSelector: "*[data-dialog-close]",
// ## First focus on view swap selector
onSwapFocusToSelector: ".as-focus-to",
// ## Focus to selector
focusToSelector: "*[data-focus-to]",
// Focusable heading selector
focusFirstHeadingSelector: "h2"
}
{
// On contrast change (by default toggle document's class name)
onContrastChange: () => {
document.documentElement.classList.toggle(WCAG.params.contrastClassName)
},
// On contrast enable
onContrastEnable: false,
// On contrast disable
onContrastDisable: false,
// On "Esc" key press (by default close all open dialogs)
onEscKeyDown: () => {
WCAG._closeLastOpenedDialog()
}
}