Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

Commit

Permalink
[terra-menu] - Fixed SR not announcing menu group name information. (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
PK106552 authored Oct 31, 2023
1 parent 1aef125 commit 4559333
Show file tree
Hide file tree
Showing 11 changed files with 60 additions and 18 deletions.
7 changes: 5 additions & 2 deletions packages/terra-collapsible-menu-view/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

* Added
* Added `GroupId` prop that used in menu item for `aria-describedby` that labels the group for accessibility.

## 6.83.0 - (October 25, 2023)

* Changed
Expand All @@ -23,7 +26,7 @@
* Added the ability to add hyperlinks.
* Added `isMultiSelect` prop to support multiselect group items.
* Added aria-label prop for `collapsible-menu-view` to announce group information.

* Fixed
* Fixed responsive menu icon not being vertical in the lowlight and fusion themes.

Expand Down Expand Up @@ -105,7 +108,7 @@
* Added
* Added `isStartAligned` prop
* Added new Jest test and snapshots

## 6.65.0 - (March 29, 2023)

* Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ const propTypes = {
* String that labels the group for accessibility.
*/
ariaLabel: PropTypes.string,
/**
* String that used in menu item for aria-describedby that labels the group for accessibility.
*/
groupId: PropTypes.string,
};

const defaultProps = {
Expand Down Expand Up @@ -75,6 +79,7 @@ class CollapsibleMenuViewItemGroup extends React.Component {
isMultiSelect,
selectedKeys,
ariaLabel,
groupId,
...customProps
} = this.props;

Expand All @@ -90,7 +95,7 @@ class CollapsibleMenuViewItemGroup extends React.Component {
});
return (
<li role="none">
<div {...customProps} role="group">
<div {...customProps} role="group" id={groupId} aria-label={ariaLabel}>
{cloneChildren}
</div>
</li>
Expand All @@ -99,7 +104,7 @@ class CollapsibleMenuViewItemGroup extends React.Component {
if (onChange) {
return (
<li role="none">
<Menu.ItemGroup {...customProps} onChange={this.handleMenuOnChange} aria-label={ariaLabel}>
<Menu.ItemGroup {...customProps} onChange={this.handleMenuOnChange} id={groupId} aria-label={ariaLabel}>
{children}
</Menu.ItemGroup>
</li>
Expand Down
3 changes: 3 additions & 0 deletions packages/terra-framework-docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

* Added
* Added `aria-label` and `ariaDescribedBy` props.

## 1.43.0 - (October 25, 2023)

* Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,12 @@ class AlwaysCollapsedMenuItemsDemo extends React.Component {
]}
/>
<CollapsibleMenuView.Divider key="divider1" />
<CollapsibleMenuView.ItemGroup ariaLabel="View Type Single Selection" key="ViewTypeSelection" selectedKeys={[this.state.displayType]} onChange={this.handleDisplayTypeChange}>
<CollapsibleMenuView.ItemGroup ariaLabel="View Type Single Selection" groupId="view-type-single-select" key="ViewTypeSelection" selectedKeys={[this.state.displayType]} onChange={this.handleDisplayTypeChange}>
<CollapsibleMenuView.Item
icon={<IconTable />}
text="Table View"
key="tableView"
ariaDescribedBy="view-type-single-select"
isIconOnly
shouldCloseOnClick={false}
isSelected={this.state.displayType === 'tableView'}
Expand All @@ -66,6 +67,7 @@ class AlwaysCollapsedMenuItemsDemo extends React.Component {
icon={<IconVisualization />}
text="Chart View"
key="chartView"
ariaDescribedBy="view-type-single-select"
isIconOnly
shouldCloseOnClick={false}
isSelected={this.state.displayType === 'chartView'}
Expand All @@ -74,6 +76,7 @@ class AlwaysCollapsedMenuItemsDemo extends React.Component {
icon={<IconTreemap />}
text="Treemap View"
key="treemapView"
ariaDescribedBy="view-type-single-select"
isIconOnly
shouldCloseOnClick={false}
isSelected={this.state.displayType === 'treemapView'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,12 @@ class CollapsibleMenuViewDemo extends React.Component {
]}
/>
<CollapsibleMenuView.Divider key="Divider2" />
<CollapsibleMenuView.ItemGroup ariaLabel="View Type Single Selection" key="ViewTypeSelection" selectedKeys={[this.state.displayType]} onChange={this.handleDisplayTypeChange}>
<CollapsibleMenuView.ItemGroup ariaLabel="View Type Single Selection" groupId="view-type-single-select" key="ViewTypeSelection" selectedKeys={[this.state.displayType]} onChange={this.handleDisplayTypeChange}>
<CollapsibleMenuView.Item
icon={<IconTable />}
text="Table View"
key="tableView"
ariaDescribedBy="view-type-single-select"
isIconOnly
shouldCloseOnClick={false}
isSelected={this.state.displayType === 'tableView'}
Expand All @@ -103,6 +104,7 @@ class CollapsibleMenuViewDemo extends React.Component {
icon={<IconVisualization />}
text="Chart View"
key="chartView"
ariaDescribedBy="view-type-single-select"
isIconOnly
shouldCloseOnClick={false}
isSelected={this.state.displayType === 'chartView'}
Expand All @@ -111,6 +113,7 @@ class CollapsibleMenuViewDemo extends React.Component {
icon={<IconTreemap />}
text="Treemap View"
key="treemapView"
ariaDescribedBy="view-type-single-select"
isIconOnly
shouldCloseOnClick={false}
isSelected={this.state.displayType === 'treemapView'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,12 @@ class CollapsibleMenuViewStartAligned extends React.Component {
]}
/>
<CollapsibleMenuView.Divider key="Divider2" />
<CollapsibleMenuView.ItemGroup ariaLabel="View Type Single Selection" key="ViewTypeSelection" selectedKeys={[this.state.displayType]} onChange={this.handleDisplayTypeChange}>
<CollapsibleMenuView.ItemGroup ariaLabel="View Type Single Selection" groupId="view-type-single-select" key="ViewTypeSelection" selectedKeys={[this.state.displayType]} onChange={this.handleDisplayTypeChange}>
<CollapsibleMenuView.Item
icon={<IconTable />}
text="Table View"
key="tableView"
ariaDescribedBy="view-type-single-select"
isIconOnly
shouldCloseOnClick={false}
isSelected={this.state.displayType === 'tableView'}
Expand All @@ -103,6 +104,7 @@ class CollapsibleMenuViewStartAligned extends React.Component {
icon={<IconVisualization />}
text="Chart View"
key="chartView"
ariaDescribedBy="view-type-single-select"
isIconOnly
shouldCloseOnClick={false}
isSelected={this.state.displayType === 'chartView'}
Expand All @@ -111,6 +113,7 @@ class CollapsibleMenuViewStartAligned extends React.Component {
icon={<IconTreemap />}
text="Treemap View"
key="treemapView"
ariaDescribedBy="view-type-single-select"
isIconOnly
shouldCloseOnClick={false}
isSelected={this.state.displayType === 'treemapView'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,12 @@ class CollapsibleMenuViewWithMultiSelectItems extends React.Component {
]}
/>
<CollapsibleMenuView.Divider key="Divider2" />
<CollapsibleMenuView.ItemGroup ariaLabel="View Type Multi Selection" key="ViewTypeSelection" isMultiSelect selectedKeys={this.state.selectedKeys} onChange={this.handleDisplayTypeChange}>
<CollapsibleMenuView.ItemGroup ariaLabel="View Type Multi Selection" groupId="view-type-multi-select" key="ViewTypeSelection" isMultiSelect selectedKeys={this.state.selectedKeys} onChange={this.handleDisplayTypeChange}>
<CollapsibleMenuView.Item
icon={<IconTable />}
text="Table View"
key="tableView"
ariaDescribedBy="view-type-multi-select"
isIconOnly
shouldCloseOnClick={false}
isSelected={this.state.selectedKeys.includes('tableView')}
Expand All @@ -90,6 +91,7 @@ class CollapsibleMenuViewWithMultiSelectItems extends React.Component {
icon={<IconFlowsheet />}
text="Expanded View"
key="expandedView"
ariaDescribedBy="view-type-multi-select"
isIconOnly
shouldCloseOnClick={false}
isSelected={this.state.selectedKeys.includes('expandedView')}
Expand All @@ -98,6 +100,7 @@ class CollapsibleMenuViewWithMultiSelectItems extends React.Component {
icon={<IconVisualization />}
text="Trending View"
key="trendingView"
ariaDescribedBy="view-type-multi-select"
isIconOnly
shouldCloseOnClick={false}
isSelected={this.state.selectedKeys.includes('trendingView')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,10 @@ class BasicMenu extends React.Component {
]}
/>
<Menu.Divider key="Divider3" />
<Menu.ItemGroup key="Group" onChange={this.handleOnChange}>
<Menu.Item text="Behavioral Health" key="GroupItem1" isSelected={this.state.groupSelectedIndex === 0} />
<Menu.Item text="Ambulatory Surgery Center" key="GroupItem2" isSelected={this.state.groupSelectedIndex === 1} />
<Menu.Item text="Critical Care" key="GroupItem3" isSelected={this.state.groupSelectedIndex === 2} isDisabled />
<Menu.ItemGroup key="Group" aria-label="Health Information" id="health-info" onChange={this.handleOnChange}>
<Menu.Item ariaDescribedBy="health-info" text="Behavioral Health" key="GroupItem1" isSelected={this.state.groupSelectedIndex === 0} />
<Menu.Item ariaDescribedBy="health-info" text="Ambulatory Surgery Center" key="GroupItem2" isSelected={this.state.groupSelectedIndex === 1} />
<Menu.Item ariaDescribedBy="health-info" text="Critical Care" key="GroupItem3" isSelected={this.state.groupSelectedIndex === 2} isDisabled />
</Menu.ItemGroup>
</Menu>
<Button onClick={this.handleButtonClick} text="Explore Clinical Solution" aria-haspopup icon={<IconCaretDown />} isReversed refCallback={this.setButtonNode} />
Expand Down
9 changes: 6 additions & 3 deletions packages/terra-menu/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

* Added
* Added `ariaDescribedBy` prop for `menu-item` to announce group information.

## 6.79.0 - (October 25, 2023)

* Changed
Expand Down Expand Up @@ -98,9 +101,9 @@

## 6.65.1 - (April 12, 2023)

* Fixed
* Fixed
* Fixed issue of navigation on menu header click.

* Added
* Allow screen readers to recognise as menu button
* Added context for menu item index, item with submenu and selected/unselected state
Expand All @@ -114,7 +117,7 @@

* Changed
* Allow existing classnames on icon to be retained

## 6.63.0 - (February 14, 2023)

* Changed
Expand Down
6 changes: 6 additions & 0 deletions packages/terra-menu/src/MenuItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ const propTypes = {
* The intl object to be injected for translations. Provided by the injectIntl function.
*/
intl: PropTypes.shape({ formatMessage: PropTypes.func }).isRequired,
/**
* If additional visible information text is used, provide a string containing the IDs for html elements that
* help describe the intent of the group of menu.
*/
ariaDescribedBy: PropTypes.string,
};

const defaultProps = {
Expand Down Expand Up @@ -246,6 +251,7 @@ class MenuItem extends React.Component {
isInstructionsForUse,
isSelectable,
isToggleable,
ariaDescribedBy,
subMenuItems,
isActive,
icon,
Expand Down
16 changes: 13 additions & 3 deletions packages/terra-menu/src/_MenuContent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class MenuContent extends React.Component {
this.onKeyDown = this.onKeyDown.bind(this);
this.onKeyDownBackButton = this.onKeyDownBackButton.bind(this);
this.validateFocus = this.validateFocus.bind(this);
this.ariaDescribedByHandle = this.ariaDescribedByHandle.bind(this);
this.needsFocus = props.isFocused;
this.handleContainerRef = this.handleContainerRef.bind(this);
this.menuHeaderId = `terra-menu-headertitle-${uuidv4()}`;
Expand Down Expand Up @@ -342,6 +343,14 @@ class MenuContent extends React.Component {
);
}

ariaDescribedByHandle(value, index) {
if (!MenuUtils.isMac() && !this.props.index && this.props.showHeader && index === 0) {
const ariaDescribedByValue = (value.props.ariaDescribedBy) ? ` ${value.props.ariaDescribedBy}` : '';
return `${this.menuTopHeaderId}${ariaDescribedByValue}`;
}
return value.props.ariaDescribedBy;
}

render() {
let index = -1;
const totalItems = MenuUtils.totalItems(this.props.children);
Expand All @@ -356,28 +365,29 @@ class MenuContent extends React.Component {
index += 1;
const onKeyDown = this.wrapOnKeyDown(item, index, item.props.isDisabled);
const isActive = this.state.focusIndex === index;

const ariaDescribedByHandleValue = this.ariaDescribedByHandle(item, index);
newItem = React.cloneElement(item, {
onClick,
onKeyDown,
isActive,
totalItems,
index,
intl: this.props.intl,
'aria-describedby': !MenuUtils.isMac() && !this.props.index && this.props.showHeader && index === 0 ? this.menuTopHeaderId : undefined,
'aria-describedby': ariaDescribedByHandleValue,
});
// If the child has children then it is an item group, so iterate through it's children
} else if (item.props.children) {
const children = item.props.children ? [] : undefined;
React.Children.forEach(item.props.children, (child) => {
index += 1;
const ariaDescribedByHandleValue = this.ariaDescribedByHandle(child, index);
const clonedElement = React.cloneElement(child, {
onKeyDown: this.wrapOnKeyDown(child, index, child.props.isDisabled),
isActive: index === this.state.focusIndex,
totalItems,
index,
intl: this.props.intl,
'aria-describedby': !MenuUtils.isMac() && !this.props.index && this.props.showHeader && index === 0 ? this.menuTopHeaderId : undefined,
'aria-describedby': ariaDescribedByHandleValue,
});
children.push(clonedElement);
});
Expand Down

0 comments on commit 4559333

Please sign in to comment.