Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WNMGDS-2694] Audit ARIA on generic roles #2978

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/design-system/src/components/Alert/Alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ export const Alert: React.FC<AlertProps> = (props: AlertProps) => {
}

return (
// 🥑
// This component supports a variety of roles and I have questions about their inclusion.
// - `alertDialog` (https://www.w3.org/TR/wai-aria-1.2/#alertdialog) requires a lot of dialog functionality that isn't available by simply applying this role alone (no focus trapping, no auto focussing on interactive element inside Alert, etc.)
// - `alert` (https://www.w3.org/TR/wai-aria-1.2/#alert) and `status` (https://www.w3.org/TR/wai-aria-1.2/#status) state that element shouldn't manage focus, but this component is using `tabIndex` to make it focusable.
// - Unsure if `alert` should be allowed since it's for "important, and usually time-sensitive, information"
// tl;dr - I think this component might just need `region` role, and `tabIndex` should be removed.

<div
className={classes}
ref={mergeRefs([alertRef, focusRef])}
Expand Down
4 changes: 4 additions & 0 deletions packages/design-system/src/components/Autocomplete/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export function renderReactStatelyItems(
});
}

// 🥑
// https://www.w3.org/TR/wai-aria-1.2/#option
// - "Default for aria-selected is false."
// Could remove `aria-selected="false"` from the `li` element.
export function renderStatusMessage(message: ReactNode) {
return (
<li aria-selected="false" className="ds-c-autocomplete__menu-item-message" role="option">
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Remove aria-selected attr as false is implied by its role.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ export const ChoiceList: React.FC<ChoiceListProps> = (props: ChoiceListProps) =>
});

return (
// 🥑
// https://www.w3.org/TR/wai-aria-1.2/#group
// - "aria-invalid (state) (deprecated on this role in ARIA 1.2)"
<fieldset
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: If choice is radio, set role="radiogroup"

aria-invalid={invalid}
aria-describedby={describeField({ ...props, hintId, errorId })}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ export function MultiInputDateField(props: DateFieldProps): React.ReactElement {
dateFormatter: defaultDateFormatter,
};

// 🥑
// https://www.w3.org/TR/wai-aria-1.2/#group
// - "aria-invalid (state) (deprecated on this role in ARIA 1.2)"
return (
<fieldset
aria-invalid={invalid}
Expand Down
5 changes: 5 additions & 0 deletions packages/design-system/src/components/Dialog/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ export const Dialog = (props: DialogProps) => {

useBodyScrollPrevention(modalProps.isOpen ?? true);

// 🥑
// Is `tabIndex` necessary here? It's not clear why it's being set to -1.
// It's also not clear why the `role` attribute is being set to `document`.
// Should this allow for more flexible heading tags? Locked into `h1` for now.
// Can we remove `role="main"` from the `main` element?
return (
<NativeDialog
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO:

  1. Replace tabIndex with autofocus attr
  2. Replace <h1> with <h2>
  3. Remove role="main"
  4. Apply aria-labelledby to dialog and not div

I don't believe the Bootstrap issue exists on native dialog elements, so I don't believe the role="document" is needed. Will experiment with removing this role.

className={dialogClassNames}
Expand Down
3 changes: 3 additions & 0 deletions packages/design-system/src/components/Drawer/Drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ export const Drawer = (props: DrawerProps) => {

const Heading = `h${props.headingLevel}` as const;

// 🥑
// Why is `tabIndex` needed here?
// `aria-labelledby` not allowed on `role="generic"` element
return (
<NativeDialog
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO:

  1. Explore replacing tabindex with autofocus
  2. Apply aria-labelledby to dialog and not div

className={classNames(props.className, 'ds-c-drawer')}
Expand Down
4 changes: 4 additions & 0 deletions packages/design-system/src/components/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ export const Dropdown: React.FC<DropdownProps> = (props: DropdownProps) => {
ref: mergeRefs([triggerRef, inputRef, useAutofocus<HTMLButtonElement>(props.autoFocus)]),
'aria-controls': menuId,
'aria-labelledby': `${buttonContentId} ${labelProps.id}`,

// 🥑
// https://www.w3.org/TR/wai-aria-1.2/#button
// - "aria-invalid (state) (deprecated on this role in ARIA 1.2)"
'aria-invalid': invalid,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Investigate if role="combobox" still causes issues for VO as remediation for aria-invalid deprecation. May need further exploration if combobox still has issues.

'aria-describedby': describeField({ ...props, hintId, errorId }),
// TODO: Someday we may want to add this `combobox` role back to the button, but right
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ export const MonthPicker = (props: MonthPickerProps) => {
const { hintId, hintElement } = useHint({ ...props, id });
const labelProps = useLabelProps({ ...props, id });

// 🥑
// https://www.w3.org/TR/wai--1.2/#group
// - "aria-invalid (state) (deprecated on this role in ARIA 1.2)"

return (
<fieldset
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Add role="listbox" as possible remediation of deprecated aria-invalid attr on group roles.

aria-invalid={invalid}
Expand Down
3 changes: 3 additions & 0 deletions packages/design-system/src/components/Tabs/Tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ export const Tab = forwardRef((props: TabProps, ref: any) => {
{props.children}
</a>
) : (
// 🥑
// https://www.w3.org/TR/wai-aria-1.2/#generic
// - "aria-disabled (state) (deprecated on this role in ARIA 1.2)"
<span aria-disabled="true" {...sharedTabProps}>
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't realize the {...sharedTabProps} included role="tab". Disregard.

{props.children}
</span>
Expand Down
3 changes: 3 additions & 0 deletions packages/design-system/src/components/Tabs/TabPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ export const TabPanel = (props: TabPanelProps) => {
const classes = classnames('ds-c-tabs__panel', props.className);

return (
// 🥑
// https://www.w3.org/TR/wai-aria-1.2/#tabpanel
// - "aria-disabled (state) (deprecated on this role in ARIA 1.2)"
<div
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Explore purpose of disabled Tabs. It's recommended not to disable interactive elements as it can confuse users.

aria-disabled is deprecated on tabpanel roles. Need to figure out purpose of disabling component before mitigation can be decided.

aria-labelledby={props.tabId}
aria-hidden={!props.selected}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export type VerticalNavComponent = React.ReactElement<any> | any | ((...args: an

export interface VerticalNavProps {
/**
* An optional arial label for the `<nav>` element in this component.
* An optional aria label for the `<nav>` element in this component.
* This prop is necessary when there is more than one nav element on a page.
*/
ariaNavLabel?: string;
Expand Down