Nº 463 of 520
Tree
A place tree. Dispatch and Asar start open, Gate 4 is current, and Bhadra and People start closed. A click opens a branch or moves the current page.
Preview
Use it
Free to use · credit appreciated1 Once, in your project
npx skills add SusanAcharya/Design-Lounge 2 Then ask
Using the Design Lounge skill, build "Tree" (piece tree-nav) in my stack. Match its brief; restyle it onto my product's theme.
No skill? Paste the brief instead. It carries the numbers, tokens and behaviour.
<!-- Design Lounge Nº 463 · "Tree" · designlounge.vercel.app -->
# Tree
> **Build brief for a coding agent.** Rebuild this piece in the reader's stack. If they haven't said which stack, ask once, then default to semantic HTML + CSS + a little vanilla JS. Match the numbers below; don't "improve" them. When a kit is locked, the current row uses `--primary-soft` and the row height follows the family. This is not the collapsing sidebar. That piece is a rail of icons. This piece is nested pages.
## What it is
A tree of places, 320px wide. Dispatch is open. Inside it, Asar is open on Gate 4 and Gate 2, and Gate 4 is the current page. Bhadra is closed, and it holds Shift list. People is closed, and it holds Roles. A branch button shows – when open and + when closed. Opening Bhadra reveals Shift list. Clicking a leaf moves `aria-current="page"` to that leaf. The current row sits on the soft green. There is no indentation ornament beyond 16px per level, and no animation.
## Reference behaviour
1. Dispatch and Asar are expanded. Gate 4 has `aria-current="page"`. Bhadra and People are collapsed, and their children are not shown.
2. Clicking a branch toggles `aria-expanded` and swaps the mark between – and +.
3. Clicking Gate 2, Shift list, or Roles makes that leaf current and clears the previous current. The branches stay as they were.
4. Collapsing Asar hides Gate 4 and Gate 2. Gate 4 remains the current page even while hidden, and it shows again when Asar opens.
5. There is no animation. Focus ring is 2px `--focus`, offset 2px.
6. The tree does not navigate the frame. Current is a state on the row.
## Structure
```
padding 48px 64px
Places 12px
tree, width 320
– Dispatch
– Asar
Gate 4 current
Gate 2
+ Bhadra
+ People
each row min-height 40, indent 16px per level
```
- Nested `ul` elements. The outer list has no bullets.
- A branch is a button with `aria-expanded`. Its child list is the next sibling.
- A leaf is a button. The current leaf has `aria-current="page"`.
- The + and – marks are `aria-hidden`. The button name is the place.
## Tokens
… 128 more lines. Copy or download for the full brief. Loading the source…Brief
168 linesBuild brief for a coding agent. Rebuild this piece in the reader’s stack. If they haven’t said which stack, ask once, then default to semantic HTML + CSS + a little vanilla JS. Match the numbers below; don’t “improve” them. When a kit is locked, the current row uses
--primary-softand the row height follows the family. This is not the collapsing sidebar. That piece is a rail of icons. This piece is nested pages.
What it is
A tree of places, 320px wide. Dispatch is open. Inside it, Asar is open on Gate 4 and Gate 2, and Gate 4 is the current page. Bhadra is closed, and it holds Shift list. People is closed, and it holds Roles. A branch button shows – when open and + when closed. Opening Bhadra reveals Shift list. Clicking a leaf moves aria-current="page" to that leaf. The current row sits on the soft green. There is no indentation ornament beyond 16px per level, and no animation.
Reference behaviour
- Dispatch and Asar are expanded. Gate 4 has
aria-current="page". Bhadra and People are collapsed, and their children are not shown. - Clicking a branch toggles
aria-expandedand swaps the mark between – and +. - Clicking Gate 2, Shift list, or Roles makes that leaf current and clears the previous current. The branches stay as they were.
- Collapsing Asar hides Gate 4 and Gate 2. Gate 4 remains the current page even while hidden, and it shows again when Asar opens.
- There is no animation. Focus ring is 2px
--focus, offset 2px. - The tree does not navigate the frame. Current is a state on the row.
Structure
padding 48px 64px
Places 12px
tree, width 320
– Dispatch
– Asar
Gate 4 current
Gate 2
+ Bhadra
+ People
each row min-height 40, indent 16px per level
- Nested
ulelements. The outer list has no bullets. - A branch is a button with
aria-expanded. Its child list is the next sibling. - A leaf is a button. The current leaf has
aria-current="page". - The + and – marks are
aria-hidden. The button name is the place.
Tokens
:root {
--bg: #f6f4ef;
--ink: #161513;
--ink-2: #5a554c;
--primary-soft: #e7f2ec;
--focus: #1f4d3a;
--sans: "IBM Plex Sans", system-ui, sans-serif;
}
Row radius is 2px. The family replaces it. Do not put each row in a card. The current row is the only fill.
Typography
| Role | Family | Size | Weight | Colour |
|---|---|---|---|---|
| Where | sans | 12px | 500 | --ink-2 |
| Row | sans | 14px | 400 | --ink |
| Current | sans | 14px | 500 | --ink |
| Mark | sans | 12px | 400 | --ink-2 |
The where-line letter-spacing is 0.04em. The mark is 16px wide so the words align.
Motion
None. A branch opens in one frame. Reduced motion has nothing to remove. Do not animate the height.
| Thing | Trigger | What changes |
|---|---|---|
| Branch | click | expanded, mark, child list |
| Leaf | click | which row is current |
| Focus | keyboard | 2px ring |
States
- Row resting: min-height 40px, padding 0 8px, transparent, radius 2px, gap 8px.
- Branch open:
aria-expanded="true", mark –, child list visible. - Branch closed:
aria-expanded="false", mark +, child listdisplay: none. Use the attribute in CSS so a closed list is not only visually gone if you also hide it from the tree.display: noneremoves it from the accessibility tree. - Current leaf: background
--primary-soft, weight 500. - Focus-visible: 2px outline, offset 2px.
- Do not invert the current row into a solid primary button.
- Hover may use
--surface-2. Current wins over hover.
Accessibility
- Branch buttons expose
aria-expanded. - The current page is
aria-current="page"on one leaf. - Marks are
aria-hidden="true". - Tab order follows the visible rows. Closed children are not tabbed.
- Hit target: every row is at least 40px, and 44px on a phone.
- Contrast:
#161513on#e7f2ecclears 4.5. - Do not use a triangle image with no button name. The place name is the name.
Responsive rules
- At 1280 the tree is 320px, padding 48px 64px.
- Below 640 the tree is full width inside 20px padding. Indent stays 16px. Rows stay at least 40px.
- Do not collapse this tree into a select. The nesting is the point.
- A product with one level of pages uses a list, not a tree. This demo has two levels under Dispatch and one under People.
Acceptance checklist
- Dispatch and Asar start open. Bhadra and People start closed.
- Gate 4 starts as the current page, on
#e7f2ec. - Opening Bhadra shows Shift list. Opening People shows Roles.
- The mark is – when open and + when closed, and it is hidden from assistive tech.
- Clicking Gate 2 moves the current page and clears Gate 4.
- Closing Asar hides its gates. Reopening shows Gate 4 current if it was current.
- Rows are at least 40px. Indent is 16px. The tree is 320px wide.
- Radius is 2px.
- There is no animation and no icon rail.
- Focus ring is 2px, offset 2px.
Implementation notes
The child list is the next sibling of the branch button. CSS hides it while the button is collapsed.
button[aria-expanded="false"] + ul { display: none; }
Toggle the attribute and the mark together.
Common mistakes:
- A collapsing icon rail. That is
collapsing-sidebar-rail. - A dropdown menu. That is
nested-dropdown-menu. It closes when you leave. A tree stays on the page. - A breadcrumb plus a tree that repeat the same path in two styles. The breadcrumb is the path of the current page. The tree is the map. If both are on one screen, Gate 4 is current in both.
- Checkboxes on the rows. This tree navigates. It does not multi-select.
- Animating the open height.
- A current row in solid primary.
- Pill rows on a square family.
Where it sits in a product:
- Use it for nested places: a yard, a file tree, a set of settings groups.
- A flat nav of five items is not a tree.
- The current row is
--primary-softandaria-current="page". - Height and radius follow the family.
- When a theme is locked, the current fill is that theme’s
--primary-soft. - One tree per screen. Do not also draw a second sidebar of the same pages.
- The where-line Places is the screen name.
- Gate 4 here is the same gate as the breadcrumb demo. Do not rename it on one and not the other if both are in the product.
- People holds Roles, which is the list in
people-role-list. Do not invent a second role set inside the tree. - Keep the credit line on the token block.
Rebuild order:
- Set the paper and IBM Plex Sans.
- Place the nested lists. Open Dispatch and Asar. Close Bhadra and People.
- Mark Gate 4 current.
- Wire branch toggles.
- Wire leaf clicks to move the current page.
- Check a closed branch is not in the tab order.
- Map the current fill and the radius onto the kit.
Copy you keep:
- Places.
- Dispatch, Asar, Gate 4, Gate 2, Bhadra, Shift list, People, Roles.
- Gate 4 starts current.
Details
- Palette
- Type
- IBM Plex Sans
- Motion
- Static
- Build
- One session
- Tags
Studied
Tailwind CSS docsPut each instruction next to its code. Draw the grid with thin lines and let the empty sides carry a faint hatch.
All sourcesOn the shelves