Skip to content

Commit

Permalink
More aria attributes for Selectable (#3583)
Browse files Browse the repository at this point in the history
Co-authored-by: Greg Thompson <thompson.glowe@gmail.com>
  • Loading branch information
Michail Yasonik and thompsongl authored Jun 15, 2020
1 parent 3eb02e4 commit 0e168f2
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 7 deletions.
28 changes: 22 additions & 6 deletions src/components/selectable/selectable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ export class EuiSelectable extends Component<
...cleanedListProps
} = listProps || unknownAccessibleName;

let messageContent;
let messageContent: JSX.Element | undefined;

if (isLoading) {
messageContent = (
Expand Down Expand Up @@ -391,6 +391,7 @@ export class EuiSelectable extends Component<
className
);

const messageContentId = messageContent && this.rootId('messageContent');
const listId = this.rootId('listbox');
const makeOptionId = (index: number | undefined) => {
if (typeof index === 'undefined') {
Expand All @@ -414,15 +415,22 @@ export class EuiSelectable extends Component<
props:
| Partial<EuiSelectableSearchProps>
| EuiSelectableOptionsListPropsWithDefaults
| undefined
| undefined,
messageContentId?: string
) => {
if (props && props['aria-label']) {
return { 'aria-label': props['aria-label'] };
}

const messageContentIdString = messageContentId
? ` ${messageContentId}`
: '';

if (props && props['aria-describedby']) {
return {
'aria-describedby': props['aria-describedby'],
'aria-describedby': `${
props['aria-describedby']
}${messageContentIdString}`,
};
}

Expand All @@ -431,13 +439,18 @@ export class EuiSelectable extends Component<
}

if (ariaDescribedby) {
return { 'aria-describedby': ariaDescribedby };
return {
'aria-describedby': `${ariaDescribedby}${messageContentIdString}`,
};
}

return {};
};

const searchAccessibleName = getAccessibleName(searchProps);
const searchAccessibleName = getAccessibleName(
searchProps,
messageContentId
);
const searchHasAccessibleName = Boolean(
Object.keys(searchAccessibleName).length
);
Expand Down Expand Up @@ -467,7 +480,7 @@ export class EuiSelectable extends Component<
Object.keys(listAccessibleName).length
);
const list = messageContent ? (
<EuiSelectableMessage key="listMessage">
<EuiSelectableMessage key="listMessage" id={messageContentId}>
{messageContent}
</EuiSelectableMessage>
) : (
Expand All @@ -479,6 +492,9 @@ export class EuiSelectable extends Component<
visibleOptions={visibleOptions}
searchValue={searchValue}
activeOptionIndex={activeOptionIndex}
setActiveOptionIndex={index =>
this.setState({ activeOptionIndex: index })
}
onOptionClick={this.onOptionClick}
singleSelection={singleSelection}
ref={this.optionsListRef}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const selectableListRequiredProps = {
makeOptionId: (index: number | undefined) => `option_${index}`,
listId: 'list',
onOptionClick: () => {},
setActiveOptionIndex: () => {},
...requiredProps,
};

Expand Down
16 changes: 15 additions & 1 deletion src/components/selectable/selectable_list/selectable_list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,14 @@ import AutoSizer from 'react-virtualized-auto-sizer';
import {
FixedSizeList,
ListProps,
ListChildComponentProps,
ListChildComponentProps as ReactWindowListChildComponentProps,
areEqual,
} from 'react-window';

interface ListChildComponentProps extends ReactWindowListChildComponentProps {
data: EuiSelectableOption[];
}

// Consumer Configurable Props via `EuiSelectable.listProps`
export type EuiSelectableOptionsListProps = CommonProps &
HTMLAttributes<HTMLDivElement> & {
Expand Down Expand Up @@ -102,6 +106,7 @@ export type EuiSelectableListProps = EuiSelectableOptionsListProps & {
searchable?: boolean;
makeOptionId: (index: number | undefined) => string;
listId: string;
setActiveOptionIndex: (index: number) => void;
};

export class EuiSelectableList extends Component<EuiSelectableListProps> {
Expand Down Expand Up @@ -211,6 +216,8 @@ export class EuiSelectableList extends Component<EuiSelectableListProps> {
);
}

const labelCount = data.filter(option => option.isGroupLabel).length;

return (
<EuiSelectableListItem
id={this.props.makeOptionId(index)}
Expand All @@ -225,6 +232,8 @@ export class EuiSelectableList extends Component<EuiSelectableListProps> {
disabled={disabled}
prepend={prepend}
append={append}
aria-posinset={index + 1 - labelCount}
aria-setsize={data.length - labelCount}
{...optionRest as EuiSelectableListItemProps}>
{this.props.renderOption ? (
this.props.renderOption(option, this.props.searchValue)
Expand Down Expand Up @@ -254,6 +263,7 @@ export class EuiSelectableList extends Component<EuiSelectableListProps> {
bordered,
searchable,
listId,
setActiveOptionIndex,
'aria-label': ariaLabel,
'aria-labelledby': ariaLabelledby,
'aria-describedby': ariaDescribedby,
Expand Down Expand Up @@ -324,6 +334,10 @@ export class EuiSelectableList extends Component<EuiSelectableListProps> {

const { allowExclusions } = this.props;

this.props.setActiveOptionIndex(
this.props.options.findIndex(({ label }) => label === option.label)
);

if (option.checked === 'on' && allowExclusions) {
this.onExcludeOption(option);
} else if (option.checked === 'on' || option.checked === 'off') {
Expand Down

0 comments on commit 0e168f2

Please sign in to comment.