Side rail
App navigation in a panel: the current page is a recess with its lamp lit. The rail on the left of this page is one.
Kit part · File trees
Folders and files as a real tree, printed like a wiring diagram: traces with an elbow into every item, chevrons that turn, and the chosen file set in a recess with its lamp lit. Written as a plain nested list.
Both finishes, side by side. Hover, pressed and focus are forced with .is-hover, .is-down and .is-focus; checked and disabled are real.
Aluminium
| Part | Rest | Hover | Focus | Chosen |
|---|---|---|---|---|
| File |
|
|
|
|
| Folder |
|
|
|
|
Graphite
| Part | Rest | Hover | Focus | Chosen |
|---|---|---|---|---|
| File |
|
|
|
|
| Folder |
|
|
|
|
| Name | Kind | Values | What it does |
|---|---|---|---|
| label | attribute | required | Names the tree (aria-label on the role="tree" list). |
| ul > li | markup | nested | An item. Its text before any nested <ul> is its name; an <li> holding a <ul> is a folder. |
| data-open | attribute | on a folder <li> | Starts open. Folders on the path to the chosen item open anyway. |
| aria-selected="true" | attribute | on one <li> | The chosen item: a recess with its lamp lit, and the tab stop. |
| data-meta | attribute | text | A short fact at the row’s end: a size, a count. |
| value | property | "kit/parts/calendar.mjs" | The chosen item’s path, names joined by “/”. |
| change | event | bubbles | A different item was chosen. |
| --tui-trace | CSS property | ink-3 at 55% | The colour of the printed guides. |
| ArrowDown · ArrowUp | keyboard | — | Next and previous visible item. |
| ArrowRight · ArrowLeft | keyboard | — | Open a folder, then step into it; close it, then step out to its parent. |
| Home · End | keyboard | — | First and last visible item. |
| Enter · Space | keyboard | — | Choose the item; on a folder, also open or close it. |
| * | keyboard | — | Open every folder beside the focused one. |
| Letters | keyboard | type-ahead | Jump to the next item whose name starts with what you typed. |
<tui-file-tree label="Project files">
<ul>
<li data-open>kit
<ul>
<li>brain<ul><li>rules.md</li></ul></li>
<li data-open>parts
<ul>
<li data-meta="6 KB">calendar.css</li>
<li data-meta="15 KB" aria-selected="true">calendar.mjs</li>
</ul>
</li>
<li data-meta="96 KB">kit.css</li>
</ul>
</li>
<li data-meta="2 KB">README.md</li>
</ul>
</tui-file-tree>import '/kit/kit.mjs'; // defines <tui-file-tree>
const tree = document.querySelector('tui-file-tree');
tree.addEventListener('change', () => open(tree.value)); // "kit/parts/calendar.mjs"Needs kit.css and kit.mjs. How to install the kit.
role="tree", treeitem with aria-level, aria-expanded and aria-selected, nested role="group" lists. The part writes all of it from plain markup.aria-selected; folders read as expanded or collapsed.A custom element that reads a nested list and writes the tree roles into it, wrapping each name in a row with a printed chevron, a folder or page mark (SVG masks in currentColor, so they print in either finish), the meta and a lamp. The guides are two hairlines per item (a vertical run on its ::before that stops at the elbow for the last child, and the elbow on the row’s ::before), so they follow the tree as it opens and closes with no drawing code. The chevron turns 90° over 120ms; nothing else moves.
Write names in nested lists and let the part do the ARIA; open only the path to what matters.
5 rules in this file, with the foundations they rest on and the anti-patterns that break them. Full rules ship in the brain with the Pass.
App navigation in a panel: the current page is a recess with its lamp lit. The rail on the left of this page is one.
Rows in a rack: a mark, a title, a second line and a fact or a key at the end. Chosen rows sink into a recess with their check key latched; in a running order, a row lifts out of the rack on its skirt and slides past the others, from the keyboard or by its grip.
The only colour in the kit: a lamp that is on. Green is on, amber is waiting, red is recording or failing, blue is linked, white is standing by. Always next to words.