Kingdom.md — Navigation design

Design for the file-tree navigation, focused on staying usable at arbitrary nesting depth, across the desktop sidebar and the mobile drawer. Brainstormed 2026-06-16, then validated and revised by prototyping. Read-only viewer; calm Warm Editorial aesthetic.

Status: validated against the working prototype (working/design-prototype.html). The chosen model is the inline subnav (below). The originally-brainstormed re-rooting + focus-header approach was superseded during prototyping — kept here as the decision trail. Pairs with a future nav-plan.md.

What changed (and why): the brainstorm settled on auto-promote re-rooting — a deep folder takes over the whole sidebar and the kingdom switcher morphs into a focus-header. In the prototype that mode-shift felt jarring (the sidebar swaps out from under you, the anchor moves). The pivot: a deep folder instead opens a small inline subnav panel in place — its own breadcrumb + contents — leaving the rest of the tree visible and the kingdom switcher untouched. Same goal (arbitrary depth, no runaway indent), calmer feel.


Understanding summary

  • What: how Kingdom.md's file tree behaves under arbitrary depth, on desktop (sidebar) and mobile (drawer).
  • Why: indented trees degrade past ~3–4 levels (indent budget runs out, levels stop being distinguishable, deep branches sprawl). Support arbitrary nesting without presuming how deep anyone's corpus goes.
  • Who: someone browsing a read-only personal markdown corpus in the viewer.
  • Reuses what's built: the reading-pane breadcrumb and Cmd+K / "/" search.
  • Non-goals: folder-notes (folders are never pages); encoding nav state in the URL; solving nav↔open-doc divergence for MVP.

Assumptions

  1. Navigating the tree/subnav is nav-only — expanding, drilling into a folder, or moving inside a subnav changes only what the sidebar shows, never the reading pane. Only clicking a file changes content. So "you are here" (open doc) and "you are looking here" (where the nav is browsing) can legitimately diverge.
  2. Each document already has its own URL (server-rendered Laravel routes).
  3. The viewer stays server-rendered Blade + minimal Alpine; tree/subnav state is client-side.

Decision log

  1. Branch vs. leaf — folders are pure containers. Folders open/drill; files open; no node is ever both. Alternatives: folder-notes / split-target (a folder that's also a page). Why: a markdown corpus splits cleanly into containers (folders) and leaves (.md files); the only "landing" concept is the existing per-kingdom landing-page resolution (findLanding among README.md / kingdom.md / etc.), which is per-kingdom, not per-folder.

  2. Pattern — hybrid: indented tree (shallow) + inline subnav (deep). Up to a depth cap the sidebar is a normal indented tree; past it, a folder opens a contained subnav panel that navigates the deep subtree without indenting further, scrolling sideways, or disturbing the rest of the tree. Alternatives, and why not:

    • Re-rooting / drill-down (re-root the whole sidebar into the deep folder; kingdom switcher becomes a focus-header) — prototyped, then rejected: the whole-sidebar takeover and the morphing anchor were a jarring mode-shift.
    • Horizontal Miller columns — rejected: costs horizontal space / horizontal scroll, wrong for a narrow sidebar + reading focus. The subnav is a vertical, single-column Miller (a breadcrumb + one contents list) — Miller's unlimited depth without the sideways scroll.
    • Always-on indented tree — degrades past ~4 levels. Pure drill-down — loses the overview.
  3. Trigger — depth cap of 3. Folders expand/collapse inline for the first 3 levels; a folder at the cap (whose children would be a 4th level) opens its inline subnav instead of indenting. Why: guarantees indentation can never run away, at any corpus depth, with no new global UI. (The brainstorm's "auto-promote vs. explicit-focus A/B" is moot — the subnav is the mechanism.)

  4. Climb-out lives inside the subnav. The subnav has its own breadcrumb header (e.g. drafts / archive / 2024); clicking a segment climbs to that level within the panel. The kingdom switcher is never repurposed (this supersedes the brainstormed focus-header and its "up one level" fallback). Multiple deep folders can each have their own open subnav independently.

  5. Motion — directional slides inside the subnav. Drilling deeper slides the contents in from the right; climbing up slides them in from the left. Pure horizontal slide, no opacity fade. The subnav's first open also gets a brief fade-in. All gated to play once (on the move that triggered them), never on unrelated re-renders.

  6. Sort order — folders first, then alphabetical (in both the tree and the subnav). Why: matches the conventional file-explorer expectation.

  7. Breadcrumb(s) stay decoupled. There are two independent breadcrumbs that never cross-wire: the reading-pane breadcrumb tracks the open document's path (and does not drive the nav); the subnav breadcrumb is local to one deep folder's panel (drill position only). Consequence: the nav↔open-doc divergence "snap back to what I'm reading" problem is deferred for MVP (acceptable gap; recover by reopening the doc or via search).

  8. Deep-linking. The URL encodes the current document only (clean per-doc routes; refresh / back / shareable links work). Tree/subnav state is ephemeral client-side state; on load the sidebar opens the path to the current doc. Why: YAGNI — no need to encode nav state in the URL.

  9. Mobile — same model in the drawer. Cap 3, inline subnav, directional slides — no separate mobile nav logic. Drilling/opening a subnav keeps the drawer open; tapping a file closes it and navigates.

  10. Collapse preserves the active lineage (the open doc never hides). Collapsing a folder hides its off-path direct children but keeps its on-path child — so the active file and its whole ancestor chain stay visible no matter which ancestor you collapse. Deeper folders keep their own expand/collapse state: collapsing an ancestor does not force-collapse an expanded descendant. Example: with design-notes/planning/drafts/recursive-plan.md open and drafts expanded, collapsing planning hides planning's off-path children (lens-audit.md) but keeps drafts visible — and since drafts stays expanded, its contents stay shown too. Why: you should always be able to see where you are in the tree, and collapsing should only hide what you actually collapsed. Applies identically to the inline subnav: a cap folder containing the open doc can't be collapsed away — its subnav stays revealed to the active file. Built 2026-06-17. Revised from the brainstorm's original "strip every off-path branch" to this gentler per-folder rule (honors deeper folders' own state) after it felt wrong in testing.


Final design

The model in one line: an indented tree of the kingdom's contents shown up to 3 levels deep; a folder at the cap opens an inline subnav panel in place — a self-contained breadcrumb

  • single contents list — that browses the deep subtree to any depth without indenting further, scrolling sideways, or re-rooting the sidebar. The kingdom switcher never changes.

The tree (levels 0–2)

  • Folders expand/collapse inline; files open the document; folders past the cap open a subnav.
  • Sorted folders-first, then alphabetical. Long names ellipsis-truncate; hovering a file pops its frontmatter (title / type / updated / tags) as a tooltip from behind the sidebar. Every row also carries a native title tooltip with its full name (so a truncated name is recoverable on hover; complements the frontmatter card, which shows the human title rather than the filename).

The subnav (the depth valve)

  • A bounded, inset panel rendered in place under the cap folder's row; the rest of the tree continues below it.
  • Breadcrumb header = the drill path within this folder; segments climb. Contents list = the current level's children (folders-first/alphabetical), vertically scrollable if tall.
  • Drilling a subfolder replaces the list and extends the breadcrumb (slide from the right); climbing via the breadcrumb slides from the left. No horizontal scrolling, ever.

Highlight & divergence

  • The open document is highlighted whenever it's currently visible (in the tree or an open subnav).
  • Collapse never hides the open doc — collapsing any ancestor keeps the active file + its lineage visible (Decision 10). (Built 2026-06-17.)
  • Browsing the nav away from the open doc is allowed (nav-only); re-syncing back is not an MVP feature.

Load & URLs

  • Per-document URL = the source of truth for "what you're reading."
  • On load the sidebar opens the path to the current doc (expanding ancestors / opening the relevant subnav). Tree/subnav state is client-side (Alpine), re-derived from the current doc. (The prototype starts at the kingdom root for demo purposes; the real app auto-reveals.)

Accessibility baseline (established in the prototype — Task 6 must preserve)

  • Tree/subnav rows are real <button>s (focusable, Enter/Space-activatable), not click-divs. Folder + cap rows carry aria-expanded (kept in sync on toggle); the open doc carries aria-current="page"; decorative icons are aria-hidden; the tree <ul> is labelled.
  • Focus management on drill/climb (subnav). A sliding panel that moves content without moving focus is a keyboard/screen-reader dead end. When the subnav drills into a folder, focus moves into the new level (its first item, or the breadcrumb tail); when it climbs via a breadcrumb segment, focus returns there. This is the drill-down (single-column Miller) pattern's standard accessibility expectation — established here 2026-06-17 from a Miller-columns/drill-down research pass, closing a gap the prototype's purely-visual slide left open. (Pairs with: reset the panel's scroll to top on each level change, so a tall level never opens mid-scrolled.)
  • prefers-reduced-motion neutralizes transitions too (the furl, the caret), not just the keyframe slides.
  • Upgrade path (not required for MVP): the full WAI-ARIA tree pattern — role="tree"/"treeitem" with roving-tabindex + arrow-key navigation — instead of every row being its own tab stop.

Open / deferred items

  • Deferred (not MVP): nav↔open-doc divergence re-sync; folder-notes; encoding tree/subnav state in the URL; auto-collapse-siblings (accordion).
  • Built in Task 6 (2026-06-17): collapse preserves the active lineage (Decision 10), via the gentler per-folder rule above. Off-path siblings just hide (instant, no animation) — the fully-animated version (off-path siblings furl away while the active row stays put) remains a nice-to-have, not done.
  • Tuning knobs in the prototype: the depth cap (CAP), per-level indent, subnav max-height, slide speed/distance.

Background — deep-nav pattern taxonomy (reference)

Captured from a prior research pass (informed Decision 2):

  • Indented tree — whole tree visible; degrades at 3–4 levels.
  • Static rail + panel — buys ~one level of relief, then degrades like an indented tree.
  • Recursive drill-down / re-rooting — unlimited depth, every screen 1–2 levels deep; trade = no whole-tree view. (Brainstormed as our depth valve; superseded by the inline subnav.)
  • Miller columns — unlimited depth, more ancestor context, costs horizontal space. (Our subnav is a vertical, single-column variant — Miller's depth without the sideways scroll.)
  • IA red flag: routinely needing 4+ levels can mean the taxonomy itself is too deep.

Sources: boundev.ai multilevel-menu UX guide; easternstandard infinite-nesting menus; folwell.umn.edu vertical navigation; uxplanet sidebar best practices; eleken UX navigation.