# Tree

> Collapsible tree, built on native elements.

Expanding is done by `<details>`: it works from the keyboard, survives
printing, and costs not a line of JavaScript.

## A file tree

Click a folder to expand it.

<Tree>
  <TreeItem label="docpensieve.config.mjs" />
  <TreeItem label="docs" open>
    <TreeItem label="v1.0" open>
      <TreeItem label="index.md" />
      <TreeItem label="guide">
        <TreeItem label="installation.md" />
        <TreeItem label="configuration.md" />
      </TreeItem>
      <TreeItem label="components">
        <TreeItem label="card.mdx" />
        <TreeItem label="tree.mdx" />
      </TreeItem>
    </TreeItem>
  </TreeItem>
  <TreeItem label="dist" />
</Tree>

```mdx
<Tree>
  <TreeItem label="docs" open>
    <TreeItem label="index.md" />
  </TreeItem>
</Tree>
```

## Branch or leaf

The difference is read from the writing, with no prop to set: an entry **with
children** is a collapsible branch, an entry **without children** is a leaf.
`open` expands the branch as soon as the page opens.

<Columns>
  <Column span={6}>
    <Card style={{ height: '100%' }}>
      <CardHeader>Closed by default</CardHeader>
      <CardBody>
        <Tree>
          <TreeItem label="package">
            <TreeItem label="index.js" />
          </TreeItem>
        </Tree>
      </CardBody>
    </Card>
  </Column>
  <Column span={6}>
    <Card style={{ height: '100%' }}>
      <CardHeader>Opened by `open`</CardHeader>
      <CardBody>
        <Tree>
          <TreeItem label="package" open>
            <TreeItem label="index.js" />
          </TreeItem>
        </Tree>
      </CardBody>
    </Card>
  </Column>
</Columns>

## A plain list

Without any branch, the tree becomes a monospaced list — useful to list
produced files.

<Tree>
  <TreeItem label="index.html" />
  <TreeItem label="versions.json" />
  <TreeItem label="assets/docpensieve.css" />
</Tree>

## Something that is not a file

Nothing forces you to describe a file tree. A data structure reads just as
well.

<Tree>
  <TreeItem label="config" open>
    <TreeItem label="projectName : string" />
    <TreeItem label="siteUrl : string" />
    <TreeItem label="versions" open>
      <TreeItem label="slug : string" />
      <TreeItem label="current : boolean" />
      <TreeItem label="prerelease : boolean" />
    </TreeItem>
    <TreeItem label="theme">
      <TreeItem label="framework : 'tailwind' | 'custom'" />
      <TreeItem label="tokens : Record&lt;string, string&gt;" />
    </TreeItem>
  </TreeItem>
</Tree>

## A composite label

`label` accepts content, not just text.

<Tree>
  <TreeItem
    label={
      <span>
        📦 <strong>package</strong>
      </span>
    }
    open
  >
    <TreeItem label={<code>index.js</code>} />
    <TreeItem
      label={
        <span>
          <em>types</em> — generated
        </span>
      }
    />
  </TreeItem>
</Tree>

```mdx
<TreeItem
  label={
    <span>
      📦 <strong>package</strong>
    </span>
  }
>
  …
</TreeItem>
```

> One caveat: what is written between braces is an **expression**, and the
> compiler does not read it — its result only exists at render time. A URL
> placed there is therefore not rewritten and will ignore the deployment
> prefix. For a link in a label, write the full URL.

## Styling the tree

<ForTheme framework="tailwind">

<Tree className="text-indigo-700 dark:text-indigo-300">
  <TreeItem label="in colour" open>
    <TreeItem label="the children inherit" />
  </TreeItem>
</Tree>

```mdx
<Tree className="text-indigo-700 dark:text-indigo-300">…</Tree>
```

</ForTheme>
<ForTheme framework="custom">

A class of your own colours it — here `accent-text`, from
`theme/99-docpensieve.css`, which follows the palette in dark mode too:

<Tree className="accent-text">
  <TreeItem label="in colour" open>
    <TreeItem label="the children inherit" />
  </TreeItem>
</Tree>

```mdx
<Tree className="accent-text">…</Tree>
```

```css
.accent-text {
  color: var(--dp-accent);
}
```

</ForTheme>

## What it does not announce

The structure is a nested list, not a `role="tree"`. That role promises a
screen reader arrow-key navigation that nothing here would implement:
announcing it would lie about what the page can do.

A `TreeItem` written outside a `Tree` is refused — it would produce an `<li>`
outside any list, invalid HTML that no browser reports. An entry without a
label is refused too.

A tree is how this documentation shows the shape of a project. What those
folders become once built — the order, the addresses — is in
[Writing pages](/versions/beta/guide/writing-pages/).

## Properties

`TreeItem`:

| Property    | Type            | Effect                                      |
| ----------- | --------------- | ------------------------------------------- |
| `label`     | text or element | What the line shows.                        |
| `open`      | `boolean`       | Opens the branch as soon as the page opens. |
| `className` | `string`        | Classes added to the line.                  |
| `style`     | `object`        | Inline styles on the line.                  |

`Tree` takes `className` and `style`.
