The Basics

What it is

Tree is a list with multiple levels of hierarchy, used to navigate quickly among items or to select items at any level. It’s made of parent and child nodes; children nested in the same parent node should be related.

Typically, Tree is used to navigate among separate web pages. It also has a checkable variation, which enables users to check individual list items or a parent node, which checks all its available children.

How it works

  • To open and view the children of any parent node, the user clicks or activates the Expand icon or uses the right arrow.
  • To select a node, the user clicks or activates the list item text or uses Space or Enter.
  • When selected, nodes are marked as active.
  • To close a node, the user clicks or activates the Collapse icon or uses the left arrow.

In the checkable variation:

  • Checking a parent node automatically checks its children. Users can click or activate the parent’s checkbox or use Space.
  • If some children are checked, their parent node is partially checked (its checkbox contains a horizontal line instead of a check mark).
  • When all children are checked or unchecked, their parent node’s state reflects that overall state.
  • Disabled nodes can’t be expanded or checked.

When to use

  • For navigation among separate web pages or sections on the same page
  • To enable users to set filter options at different levels
  • To ask users to select items in a nested list

When not to use

  • For displaying long content

What to use instead

Accordion

Use Accordion to display long content with 2 levels of hierarchy.

Menu

Use Menu for navigation among web pages at the same level.

Tabs

Use Tabs for navigation among sections on the same page.

How to use

Hierarchy

Don’t use more than 3 levels of hierarchy in Tree. A deeper hierarchy can lead to display issues like wrapping text and excessive indentation. After 6 levels of hierarchy, Tree stops automatically indenting child nodes.

Display options

Tree can be set to show dividers above and below each parent node. If your Tree has many parent nodes, use dividers to help differentiate them.

You can also set certain nodes to be expanded and/or checked by default on page load. This is useful for setting filters based on stored queries, but it can also be helpful when users first load a website or filtering feature with nothing selected yet. Expanding the starting parent category for website navigation or pre-checking certain filters can help users get started and move quickly through a task.

Expanding a node by default works best when the expanded node is the first one in the Tree. Otherwise, users might be confused to see that a random node partway down the Tree is expanded by default.

Do:

Set a parent node to be expanded if it’s frequently used.

<p>Set a parent node to be expanded if it’s frequently used.</p>
Don't:

Set all parent nodes as expanded for a Tree with many nodes.

<p>Set all parent nodes as expanded for a Tree with many nodes.</p>

The content of each Tree node can be plain text or custom HTML, which can include text formatting, links, and icons. Don’t add other interactive elements, which can interfere with selecting a node.

Links should be used for navigating among separate web pages or sections on the same page.

Icons should be used mainly to add context and help differentiate parent nodes. Avoid also using icons for children, because this can lead to visual clutter.

Do:

If using icons, apply them to all nodes in the same level.

<p>If using icons, apply them to all nodes in the same level.</p>
Don't:

Apply icons to just some of the nodes in the same level.

<p>Apply icons to just some of the nodes in the same level.</p>

Checkable variation

Tree’s checkable variation adds checkboxes to the nodes. When used, this variation applies to the entire Tree. Tree should not contain a mix of checkable and read-only nodes.

If all of a parent node’s children are checked, then the parent’s checkbox is checked. The exception is if any of the children are disabled. In this case, there’s no way to check off all the children, so the parent checkbox can only ever be partially checked, never fully checked. This is a deliberate design decision by the Forge team.

Style

Design details

Animation

Tree nodes expand vertically only. Each node opens or closes smoothly when changing state. This visual cue tells users that the parent and child nodes are related. This animation uses the ShowHide component. It takes 1/4 second (250ms), regardless of how many children the node has.

The Expand and Collapse icons rotate 180 degrees to preview the action that will take place when the parent node is clicked or activated. This transition takes 1/2 second (500ms).

The timing and animation for Tree can’t be customized.

Placement and hierarchy

If used for primary navigation, Tree should be placed to the left of the content area. For secondary, same-page navigation, Tree should be placed to the right of the content area.

When Tree is used for filtering, it should be placed to the left of the data or content.

Placement and hierarchy

Content

Node content can be plain text or custom HTML, including formatted text, links, and icons. Don’t put interactive elements in nodes; this can interfere with node selection.

When content hits the right edge of the container, it wraps instead of truncating. For this reason, when using Tree in a narrow container (like a left-hand navigation section), node labels should be informative but as short as possible. Avoid text that’s long enough to wrap. The text for a parent node should clearly describe the category of the children it contains.

Do:

Group related children under a label that makes sense for the group.

<p>Group related children under a label that makes sense for the group.</p>
Don't:

Group unrelated child nodes.

<p>Group unrelated child nodes.</p>

Demos

Uncontrolled Share

Controlled Share

Checkable Uncontrolled Share

Checkable Controlled Share

Custom Nodes Share

Coding

Developer tips

Each element in Tree must have a unique ID. This is required for the expanding and collapsing behavior to work correctly.

Any content can be passed into a Tree node, including a navigation link. Use the renderTitle prop and pass in <a href>link</a> for Tree-based navigation.

In the checkable variation, if a parent node is checked by default and contains child nodes that aren’t defined in the defaultChecked list, those child nodes are implicitly checked even though they aren’t included in the defaultChecked list.

If a child node is the default selected node, Tree automatically expands the path of the selected node even if that node ID isn’t included in the defaultExpanded list.

If using React testing library, a data-testid attribute can either be explicitly defined or is implicitly defined as the node ID.

Tree is made up of individual TreeNodes that can be configured with the Tree's data prop. Use data to set the Tree contents; don’t use TreeNode itself. The data prop takes an array of objects of type DataNode, which is an abstraction of TreeNode’s props. All the properties of each DataNode match the corresponding prop on the TreeNode API (see Props for details), except for children. The children prop in each DataNode takes an array of other DataNodes, while the children prop of the TreeNode component takes an array of actual TreeNode components.

Repository

Implementation links

Tree directory in Bitbucket

TreeNode directory in Bitbucket

Implementation details

It is strongly recommended to familiarize yourself with the Forge source code. While this documentation is a best effort to document the intent and usage of a component, sometimes some features only become clear when looking at the source code. Also, looking at Forge's source code may help identify and fix bugs in either your application or Forge itself.

Storybook files

Forge maintains at least one storybook file per component. While the primary audience for these files is typically the Forge team, these storybook files may cover usages of the component not covered by a demo. The storybook for the latest version of forge can be found at go/forge-storybook.

Testing library

Forge strongly encourages using testing-library to write tests for your application.

"The more your tests resemble the way your software is used, the more confidence they can give you."

If you're having trouble testing a Forge component using testing-library, it would be a good idea to see how Forge tests its own components. For the most part, Forge tries to use screen.getByRole as much as it can, as that API provides the best feedback on a11y compliance. Forge discourages the use of document.querySelector and screen.getByTestId as both APIs encourage using implementation details to test your component, and discourage adding roles to your component.

With that being said, many of Forge's components were not built with accessability in mind. These components do break the recommendations listed above.

Import statements

In Nimbus applications

athenaOne serves the Forge bundle independently from your application's bundle. Importing Forge components directly from '@athena/forge' takes advantage of this feature.

import { Tree, TreeNode } from '@athena/forge'

In standalone applications

Importing components using the exact path to the module takes advantage of webpack's tree shaking feature. Webpack will include only that module and its dependencies.

import Tree from '@athena/forge/Tree';
import TreeNode from '@athena/forge/TreeNode';

To use this import guidance, Typescript applications must use typescript >= 4.7.3, and should add this setting to their tsconfig.json file:

{
"compilerOptions": {
"moduleResolution": "Node16",
}
}

If this setting doesn't work for your application, use this import statement instead:

import Tree from '@athena/forge/dist/Tree';
import TreeNode from '@athena/forge/dist/TreeNode';

Props