in packages/eui/src/components/tree_view/tree_view.tsx [268:367]
render() {
const {
children,
className,
items,
display = 'default',
expandByDefault,
showExpansionArrows,
theme,
...rest
} = this.props;
const styles = euiTreeViewStyles(theme);
const cssStyles = [styles.euiTreeView, styles[display]];
// Computed classNames
const classes = classNames('euiTreeView', className);
const instructionsId = `${this.state.treeID}--instruction`;
return (
<EuiTreeViewContext.Provider value={this.state.treeID}>
{!this.isNested && (
<EuiI18n
token="euiTreeView.listNavigationInstructions"
default="You can quickly navigate this list using arrow keys."
>
{(listNavigationInstructions: string) => (
<EuiScreenReaderOnly>
<p id={instructionsId}>{listNavigationInstructions}</p>
</EuiScreenReaderOnly>
)}
</EuiI18n>
)}
{/* eslint-disable-next-line jsx-a11y/no-redundant-roles */}
<ul
css={cssStyles}
className={classes}
id={!this.isNested ? this.state.treeID : undefined}
aria-describedby={!this.isNested ? instructionsId : undefined}
role="list" // VoiceOver doesn't parse lists with `list-style: none` as the correct role - @see https://www.scottohara.me/blog/2019/01/12/lists-and-safari.html
{...rest}
>
{items.map((node, index) => {
const buttonId = node.id;
const wrappingId = this.treeIdGenerator(buttonId);
const isNodeExpanded = node.children
? this.isNodeOpen(node)
: undefined; // Determines the `aria-expanded` attribute
let icon = node.icon;
if (node.iconWhenExpanded && isNodeExpanded) {
icon = node.iconWhenExpanded;
} else if (!icon && node.useEmptyIcon) {
icon = <></>; // Renders a placeholder
}
return (
<EuiTreeViewItem
key={buttonId + index}
id={buttonId}
className={node.className}
buttonRef={(ref) => this.setButtonRef(ref, index)}
aria-controls={node.children ? wrappingId : undefined}
label={node.label}
icon={icon}
hasArrow={showExpansionArrows}
isExpanded={isNodeExpanded}
isActive={this.state.activeItem === node.id}
display={display}
data-test-subj={`euiTreeViewButton-${this.state.treeID}`}
onKeyDown={(event: React.KeyboardEvent) =>
this.onKeyDown(event, node)
}
onClick={() => this.handleNodeClick(node)}
>
{node.children && (
<div
id={wrappingId}
onKeyDown={(event: React.KeyboardEvent) =>
this.onChildrenKeydown(event, index)
}
>
{isNodeExpanded && (
<EuiTreeView
items={node.children}
display={display}
showExpansionArrows={showExpansionArrows}
expandByDefault={this.state.expandChildNodes}
/>
)}
</div>
)}
</EuiTreeViewItem>
);
})}
</ul>
</EuiTreeViewContext.Provider>
);
}