Skip to content

Commit

Permalink
feat(:wheelchair:) adding correct ARIA attribs
Browse files Browse the repository at this point in the history
Switch was missing aeria-checked which is required. Adding a small hook util
to help manage correct aria-checked attribute values when switch is
used as an uncontrolled component
  • Loading branch information
atomicpages committed Sep 10, 2020
1 parent f77511b commit 01bc2f5
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/components/switch/Switch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { State } from '../state/State';
import { PCRSwitchProps } from '../../typings/PCRSwitchProps';
import { useCommonProps } from '../../hooks/utility/useCommonProps';
import { UseCheckboxState } from '../checkbox/Checkbox';
import mergeRefs from 'react-merge-refs';
import { useAriaChecked } from './useAriaChecked';

export const Switch = React.forwardRef<HTMLInputElement, PCRSwitchProps>((props, ref) => {
const { checked, value, state, ...rest } = useControlled<
Expand All @@ -20,16 +22,21 @@ export const Switch = React.forwardRef<HTMLInputElement, PCRSwitchProps>((props,
const { children, locked, color, id, className, style, htmlProps } = useCommonProps(rest);
const styles = useLocked({ locked, style });

const htmlRef = useAriaChecked({ setState: props.setState, checked });

return (
<div
style={styles}
className={classNames('pretty', 'p-switch', useClassNames(props, true), className)}>
<input
ref={ref}
ref={mergeRefs([ref, htmlRef])}
type="checkbox"
role="switch"
value={value}
id={id}
// required for role="switch"
// @see https://www.w3.org/TR/wai-aria-1.1/#switch
aria-checked={checked}
checked={checked}
{...htmlProps}
/>
Expand Down
38 changes: 38 additions & 0 deletions src/components/switch/useAriaChecked.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import * as React from 'react';
import { PCRSwitchProps } from '../../typings/PCRSwitchProps';

export type UseAriaCheckedOptions = {
setState?: PCRSwitchProps['setState'];
checked?: PCRSwitchProps['checked'];
};

const handler = (e: any) => {
e.currentTarget.setAttribute('aria-checked', e.currentTarget.checked + '');
};

/**
* A small hook to help manage correct aria-checked state when switch
* is used as an uncontrolled component.
*/
export const useAriaChecked = ({ setState, checked }: UseAriaCheckedOptions) => {
const ref = React.useRef<HTMLInputElement>(null);

React.useEffect(() => {
const elem = ref.current;
let bound = false;

if (!setState && !checked && elem) {
elem.setAttribute('aria-checked', elem.checked + '');
elem.addEventListener('change', handler);
bound = true;
}

return () => {
if (bound && elem) {
elem.removeEventListener('change', handler);
}
};
}, [setState, checked]);

return ref;
};

0 comments on commit 01bc2f5

Please sign in to comment.