Skip to content

Commit

Permalink
Form elements a11y (#48)
Browse files Browse the repository at this point in the history
* add a11y to form elements helptext

* bump version

* treat helpText as accordions

* bump version

* fix aria hidden

* aria hide the button icon, not the button
  • Loading branch information
aurorascharff authored Dec 8, 2023
1 parent 97800da commit cc11928
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 25 deletions.
2 changes: 1 addition & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@miljodirektoratet/md-react",
"version": "1.0.31",
"version": "1.0.32",
"description": "React-komponenter for Miljødirektoratet",
"author": "Miljødirektoratet",
"main": "./dist/index.js",
Expand Down
23 changes: 17 additions & 6 deletions packages/react/src/formElements/MdAutocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const MdAutocomplete = React.forwardRef<HTMLInputElement, MdAutocompleteProps>(
const [autocompleteValue, setAutocompleteValue] = useState('');
const [results, setResults] = useState<MdAutocompleteOptionProps[]>([]);

const inputId = id && id !== '' ? id : uuidv4();
const uuid = id && id !== '' ? id : uuidv4();

const classNames = classnames('md-autocomplete', {
'md-autocomplete--open': !!open,
Expand Down Expand Up @@ -105,10 +105,14 @@ const MdAutocomplete = React.forwardRef<HTMLInputElement, MdAutocompleteProps>(
return (
<div className={classNames}>
<div className="md-autocomplete__label">
{label && label !== '' && <label htmlFor={inputId}>{label}</label>}
{label && label !== '' && <label htmlFor={uuid}>{label}</label>}
{helpText && helpText !== '' && (
<div className="md-autocomplete__help-button">
<MdHelpButton
ariaLabel={`Hjelpetekst for ${label}`}
id={`md-autocomplete_help-button_${uuid}`}
aria-expanded={helpOpen}
aria-controls={`md-autocomplete_help-text_${uuid}`}
onClick={() => {
return setHelpOpen(!helpOpen);
}}
Expand All @@ -120,7 +124,13 @@ const MdAutocomplete = React.forwardRef<HTMLInputElement, MdAutocompleteProps>(

{helpText && helpText !== '' && (
<div className={`md-autocomplete__help-text ${helpOpen ? 'md-autocomplete__help-text--open' : ''}`}>
<MdHelpText>{helpText}</MdHelpText>
<MdHelpText
role="region"
id={`md-autocomplete_help-text_${uuid}`}
aria-labelledby={helpText && helpText !== '' ? `md-autocomplete_help-button_${uuid}` : undefined}
>
{helpText}
</MdHelpText>
</div>
)}

Expand All @@ -140,7 +150,8 @@ const MdAutocomplete = React.forwardRef<HTMLInputElement, MdAutocompleteProps>(
</div>
)}
<input
id={inputId}
id={`md-autocomplete_${uuid}`}
aria-describedby={helpText && helpText !== '' ? `md-autocomplete_help-text_${uuid}` : undefined}
className={inputClassNames}
value={open ? autocompleteValue : displayValue}
tabIndex={0}
Expand Down Expand Up @@ -173,8 +184,8 @@ const MdAutocomplete = React.forwardRef<HTMLInputElement, MdAutocompleteProps>(
{(autocompleteValue ? results : defaultOptions ? defaultOptions : options ? options : []).map(option => {
return (
<button
key={`md-autocomplete-option-${inputId}-${option.value}`}
id={`md-autocomplete-option-${inputId}-${option.value}`}
key={`md-autocomplete-option-${uuid}-${option.value}`}
id={`md-autocomplete-option-${uuid}-${option.value}`}
type="button"
tabIndex={open ? 0 : -1}
className={optionClass(option)}
Expand Down
22 changes: 18 additions & 4 deletions packages/react/src/formElements/MdCheckboxGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ const MdCheckboxGroup: React.FunctionComponent<MdCheckboxGroupProps> = ({
{label && label !== '' && <div>{label}</div>}
{helpText && helpText !== '' && (
<MdHelpButton
ariaLabel={`Hjelpetekst for ${label}`}
id={`md-checkboxgroup_help-button_${groupId}`}
aria-expanded={helpOpen}
aria-controls={`md-checkboxgroup_help-text_${groupId}`}
onClick={() => {
return setHelpOpen(!helpOpen);
}}
Expand All @@ -102,16 +106,26 @@ const MdCheckboxGroup: React.FunctionComponent<MdCheckboxGroupProps> = ({

{helpText && helpText !== '' && (
<div className={`md-checkboxgroup__help-text ${helpOpen ? 'md-checkboxgroup__help-text--open' : ''}`}>
<MdHelpText>{helpText}</MdHelpText>
<MdHelpText
role="region"
id={`md-checkboxgroup_help-text_${groupId}`}
aria-labelledby={helpText && helpText !== '' ? `md-checkboxgroup_help-button_${groupId}` : undefined}
>
{helpText}
</MdHelpText>
</div>
)}

<div className={optionsClassNames}>
<div
id={groupId}
aria-describedby={helpText && helpText !== '' ? `md-checkboxgroup_help-text_${groupId}` : undefined}
className={optionsClassNames}
>
{options.map(option => {
return (
<MdCheckbox
key={`key_${groupId}_${option.value}`}
id={`${groupId}_${option.value}`}
id={`md-checkboxgroup_${groupId}_${option.value}`}
label={option.text}
disabled={disabled}
checked={optionIsSelected(option)}
Expand All @@ -126,7 +140,7 @@ const MdCheckboxGroup: React.FunctionComponent<MdCheckboxGroupProps> = ({
})}
</div>

{error && error !== '' && <div className="md-radiogroup__error">{error}</div>}
{error && error !== '' && <div className="md-checkboxgroup__error">{error}</div>}
</div>
);
};
Expand Down
17 changes: 14 additions & 3 deletions packages/react/src/formElements/MdInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,14 @@ const MdInput = React.forwardRef<HTMLInputElement, MdInputProps>(
return (
<div className={`md-input__outer-wrapper ${outerWrapperClass}`}>
<div className="md-input__label">
{label && label !== '' && <label htmlFor={inputId}>{label}</label>}
{label && label !== '' && <label htmlFor={`md-input_${inputId}`}>{label}</label>}
{helpText && helpText !== '' && (
<div className="md-input__help-button">
<MdHelpButton
ariaLabel={`Hjelpetekst for ${label}`}
id={`md-input_help-button_${inputId}`}
aria-expanded={helpOpen}
aria-controls={`md-input_help-text_${inputId}`}
onClick={() => {
return setHelpOpen(!helpOpen);
}}
Expand All @@ -89,7 +93,13 @@ const MdInput = React.forwardRef<HTMLInputElement, MdInputProps>(

{helpText && helpText !== '' && (
<div className={`md-input__help-text ${helpOpen ? 'md-input__help-text--open' : ''}`}>
<MdHelpText>{helpText}</MdHelpText>
<MdHelpText
role="region"
id={`md-input_help-text_${inputId}`}
aria-labelledby={helpText && helpText !== '' ? `md-input_help-button_${inputId}` : undefined}
>
{helpText}
</MdHelpText>
</div>
)}
<div className={wrapperClassNames}>
Expand All @@ -103,7 +113,8 @@ const MdInput = React.forwardRef<HTMLInputElement, MdInputProps>(
</div>
)}
<input
id={inputId}
id={`md-input_${inputId}`}
aria-describedby={helpText && helpText !== '' ? `md-input_help-text_${inputId}` : undefined}
className={classNames}
value={value}
type={type}
Expand Down
18 changes: 15 additions & 3 deletions packages/react/src/formElements/MdMultiSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const MdMultiSelect: React.FunctionComponent<MdMultiSelectProps> = ({
'md-multiselect--small': size === 'small',
});

const buttonClasseNames = classnames('md-multiselect__button', {
const buttonClassNames = classnames('md-multiselect__button', {
'md-multiselect__button--open': !!open,
});

Expand Down Expand Up @@ -142,6 +142,10 @@ const MdMultiSelect: React.FunctionComponent<MdMultiSelectProps> = ({
{helpText && helpText !== '' && (
<div className="md-multiselect__help-button">
<MdHelpButton
ariaLabel={`Hjelpetekst for ${label}`}
id={`md-multiselect_help-button_${uuid}`}
aria-expanded={helpOpen}
aria-controls={`md-multiselect_help-text_${uuid}`}
onClick={() => {
return setHelpOpen(!helpOpen);
}}
Expand All @@ -153,7 +157,13 @@ const MdMultiSelect: React.FunctionComponent<MdMultiSelectProps> = ({

{helpText && helpText !== '' && (
<div className={`md-multiselect__help-text ${helpOpen ? 'md-multiselect__help-text--open' : ''}`}>
<MdHelpText>{helpText}</MdHelpText>
<MdHelpText
role="region"
id={`md-multiselect_help-text_${uuid}`}
aria-labelledby={helpText && helpText !== '' ? `md-multiselect_help-button_${uuid}` : undefined}
>
{helpText}
</MdHelpText>
</div>
)}

Expand All @@ -165,7 +175,9 @@ const MdMultiSelect: React.FunctionComponent<MdMultiSelectProps> = ({
>
<button
type="button"
className={buttonClasseNames}
id={`md-multiselect_${uuid}`}
aria-describedby={helpText && helpText !== '' ? `md-multiselect_help-text_${uuid}` : undefined}
className={buttonClassNames}
tabIndex={0}
onClick={() => {
return !disabled && setOpen(!open);
Expand Down
18 changes: 16 additions & 2 deletions packages/react/src/formElements/MdRadioGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ const MdRadioGroup: React.FunctionComponent<MdRadioGroupProps> = ({

{helpText && helpText !== '' && (
<MdHelpButton
ariaLabel={`Hjelpetekst for ${label}`}
id={`md-radiogroup_help-button_${radioId}`}
aria-expanded={helpOpen}
aria-controls={`md-radiogroup_help-text_${radioId}`}
onClick={() => {
return setHelpOpen(!helpOpen);
}}
Expand All @@ -100,11 +104,21 @@ const MdRadioGroup: React.FunctionComponent<MdRadioGroupProps> = ({

{helpText && helpText !== '' && (
<div className={`md-radiogroup__help-text ${helpOpen ? 'md-radiogroup__help-text--open' : ''}`}>
<MdHelpText>{helpText}</MdHelpText>
<MdHelpText
role="region"
id={`md-radiogroup_help-text_${radioId}`}
aria-labelledby={helpText && helpText !== '' ? `md-radiogroup_help-button_${radioId}` : undefined}
>
{helpText}
</MdHelpText>
</div>
)}

<div className={optionsClassNames}>
<div
aria-describedby={helpText && helpText !== '' ? `md-radiogroup_help-text_${radioId}` : undefined}
id={`md-radiogroup_${radioId}`}
className={optionsClassNames}
>
{options &&
options.map(option => {
return (
Expand Down
18 changes: 15 additions & 3 deletions packages/react/src/formElements/MdSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ const MdSelect = React.forwardRef<HTMLButtonElement, MdSelectProps>(
return value && value !== '' && value == option.value;
};

const buttonClasseNames = classnames('md-select__button', {
const buttonClassNames = classnames('md-select__button', {
'md-select__button--open': !!open,
'md-select__button--error': !!error,
});
Expand All @@ -129,6 +129,10 @@ const MdSelect = React.forwardRef<HTMLButtonElement, MdSelectProps>(
{helpText && helpText !== '' && (
<div className="md-select__help-button">
<MdHelpButton
ariaLabel={`Hjelpetekst for ${label}`}
id={`md-select_help-button_${uuid}`}
aria-expanded={helpOpen}
aria-controls={`md-select_help-text_${uuid}`}
onClick={() => {
return setHelpOpen(!helpOpen);
}}
Expand All @@ -140,7 +144,13 @@ const MdSelect = React.forwardRef<HTMLButtonElement, MdSelectProps>(

{helpText && helpText !== '' && (
<div className={`md-select__help-text ${helpOpen ? 'md-select__help-text--open' : ''}`}>
<MdHelpText>{helpText}</MdHelpText>
<MdHelpText
role="region"
id={`md-select_help-text_${uuid}`}
aria-labelledby={helpText && helpText !== '' ? `md-select_help-button_${uuid}` : undefined}
>
{helpText}
</MdHelpText>
</div>
)}

Expand All @@ -151,7 +161,9 @@ const MdSelect = React.forwardRef<HTMLButtonElement, MdSelectProps>(
className="md-select__container"
>
<button
className={buttonClasseNames}
id={`md-select_${uuid}`}
aria-describedby={helpText && helpText !== '' ? `md-select_help-text_${uuid}` : undefined}
className={buttonClassNames}
type="button"
tabIndex={0}
onClick={() => {
Expand Down
13 changes: 12 additions & 1 deletion packages/react/src/formElements/MdTextArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ const MdTextArea: React.FunctionComponent<MdTextAreaProps> = ({
{helpText && helpText !== '' && (
<div className="md-textarea__help-button">
<MdHelpButton
ariaLabel={`Hjelpetekst for ${label}`}
id={`md-textarea_help-button_${textAreaId}`}
aria-expanded={helpOpen}
aria-controls={`md-textarea_help-text_${textAreaId}`}
onClick={() => {
return setHelpOpen(!helpOpen);
}}
Expand All @@ -63,12 +67,19 @@ const MdTextArea: React.FunctionComponent<MdTextAreaProps> = ({

{helpText && helpText !== '' && (
<div className={`md-textarea__help-text ${helpOpen ? 'md-textarea__help-text--open' : ''}`}>
<MdHelpText>{helpText}</MdHelpText>
<MdHelpText
role="region"
id={`md-textarea_help-text_${textAreaId}`}
aria-labelledby={helpText && helpText !== '' ? `md-textarea_help-button_${textAreaId}` : undefined}
>
{helpText}
</MdHelpText>
</div>
)}
<div className="md-textarea__wrapper">
<textarea
id={`md-textarea_${textAreaId}`}
aria-describedby={helpText && helpText !== '' ? `md-textarea_help-text_${textAreaId}` : undefined}
value={value}
rows={rows}
className={classNames}
Expand Down
15 changes: 13 additions & 2 deletions packages/react/src/help/MdHelpButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@ export interface MdHelpButtonProps {
onClick: React.MouseEventHandler<HTMLButtonElement>;
expanded: boolean;
hideArrow?: boolean;
id?: string;
ariaLabel?: string;
className?: string;
}

const MdHelpButton: React.FunctionComponent<MdHelpButtonProps> = ({
onClick,
className,
expanded = false,
id,
ariaLabel,
hideArrow = false,
...otherProps
}: MdHelpButtonProps) => {
Expand All @@ -23,8 +27,15 @@ const MdHelpButton: React.FunctionComponent<MdHelpButtonProps> = ({
});

return (
<button {...otherProps} className={buttonClasses} onClick={onClick} type="button">
<MdHelpIcon className="md-helpbutton__icon" />
<button
{...otherProps}
id={id}
aria-label={ariaLabel || 'Hjelpetekst'}
className={buttonClasses}
onClick={onClick}
type="button"
>
<MdHelpIcon aria-hidden="true" className="md-helpbutton__icon" />
</button>
);
};
Expand Down

0 comments on commit cc11928

Please sign in to comment.