A file tree as a card-index cabinet. Folders are drawers, each with a label holder and a cup pull; open one and it slides out with its files standing in it as index cards, each showing its top edge over the card behind. A folder inside a drawer is a divider with a tab. It is a real tree for the keyboard and for a screen reader, drawn from data by one function.
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
Focus
Open
Drawer
keys1 file
lode-prod-3
keys1 file
lode-prod-3
keys1 file
lode-prod-32 KB
Card
keys2 files
lode-prod-2
lode-prod-3
keys2 files
lode-prod-2
lode-prod-3
keys2 files
lode-prod-2
lode-prod-3
Divider
specs1 file
audit1 file
export.md
specs1 file
audit1 file
export.md
specs1 file
audit1 file
export.md
Graphite
Part
Rest
Focus
Open
Drawer
keys1 file
lode-prod-3
keys1 file
lode-prod-3
keys1 file
lode-prod-32 KB
Card
keys2 files
lode-prod-2
lode-prod-3
keys2 files
lode-prod-2
lode-prod-3
keys2 files
lode-prod-2
lode-prod-3
Divider
specs1 file
audit1 file
export.md
specs1 file
audit1 file
export.md
specs1 file
audit1 file
export.md
03
API
Name
Kind
Values
What it does
drawerIndexHTML(tree, options)
function
kit.mjs
The cabinet as markup, from data. tree: [{ name, meta, open, children }]; a node with children is a folder.
options.label · options.chosen
option
string · a path
The tree’s name, and the path of the card that starts taken out: its drawer and dividers start open and it holds the tab stop.
node.meta
option
string
A few characters at the end of a card, or beside a folder’s name. A folder without one says how many files it holds.
.tui-drawer-index
class
the carcass
The cabinet, with ul[role="tree"].__cabinet inside it.
.__drawer · __front · __holder · __pull
class
level 1
A drawer: a treeitem with aria-expanded, its front, the label holder and the cup pull.
.__divider · __divide · __tab
class
level 2 and deeper
A folder in a drawer: pressboard with a tab. --tab (0, 1 or 2) says where along the row its tab is cut.
.__card
class
aria-selected
A file. The one taken out stands proud of the others, its lamp lit.
.__body · __group
class
role="group"
What slides out: the drawer’s box, or the cards behind a divider.
--di-card
custom property
length
How much of each card shows over the one behind it: 34px.
tui-open
event
detail.path · name · folder
When a card is taken out (folder: false) or a drawer or a divider is opened (folder: true). Bubbles from .tui-drawer-index. Needs kit.mjs.
Arrows · Home · End · Enter · Space · * · letters
keyboard
on an item
The tree pattern’s keys. Right opens a folder, then goes in; Left closes it, then goes out; * opens every folder beside this one; typing jumps to a name.
It is a WAI-ARIA tree: a list with role="tree", every drawer, divider and card a treeitem with its level, and every folder with aria-expanded. One item is in the tab order and the arrow keys move from there.
The keys are the pattern’s own: Up and Down; Right to open and then go in; Left to close and then go out; Home and End; * for every folder beside this one; and typing to jump to a name.
A shut drawer is out of reach: its cards are hidden from assistive technology and from Tab, not only slid out of sight.
A folder is named by its own name, so a screen reader says “runbooks, expanded, level 1”, and not every name inside it.
The card taken out is aria-selected, and it also stands proud of the rest with its lamp lit. Colour is never the only sign.
Names and sizes are paper ink on paper, 13:1 and 6:1, in both finishes.
With reduced motion drawers open and shut at once, with no slide.
06
How it’s built
The markup is a nested list written by drawerIndexHTML(), roles and all, so it can come from a server and needs only the key and click handling that kit.mjs delegates once for the page. A drawer’s body is a one-row grid that goes from 0fr to 1fr, so it slides open without being measured, and visibility follows it shut so nothing inside can be reached. The cards come forward a few pixels as it opens. Each card is paper with a ruled line, pulled up under the one before it, and throws a short shadow upward onto it; every third card sits a pixel off square. The divider is pressboard, a mix of the paper and its ink, and --tab places its tab at the first, second or third cut along the row, as dividers are cut. The label holder is a paper card behind a pressed frame drawn with spread shadows, and the pull is a hood with its hollow under it. Type-ahead is the file tree’s own fileTreeMatch.
07
Rules
drawer-index.rules.mdIn the brain
For files people browse by name a section at a time: runbooks, specs, a repository.
6 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.
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.
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.