render()

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>
    );
  }