104Training nav
The curriculum rail: track → module → unit, as nested <details>. On load it opens the module holding the current unit, closes the rest, and scrolls it into view inside the rail.
Use it for
- Any track or module page
- Curricula long enough that scrolling to find your place is the main cost
Not for
- Flat documentation — use Docs sidebar
- A course player — that has its own rail with a playlist
Rail with the current module open
markup
<nav class="ns-trainingnav" data-ns-trainingnav aria-label="Curriculum" style="position:static;max-block-size:22rem;inline-size:100%">
<a class="ns-trainingnav__track" href="#0">Salesforce Administrator</a>
<details class="ns-trainingnav__module" open>
<summary><i class="ph ph-caret-right ns-trainingnav__twist" aria-hidden="true"></i>Objects and fields<span class="ns-trainingnav__count">6</span></summary>
<ul class="ns-trainingnav__list">
<li><a class="ns-trainingnav__link" data-state="done" href="#0">Standard vs custom objects</a></li>
<li><a class="ns-trainingnav__link" data-state="done" href="#0">Field types</a></li>
</ul>
</details>
<details class="ns-trainingnav__module" open>
<summary><i class="ph ph-caret-right ns-trainingnav__twist" aria-hidden="true"></i>Security and access<span class="ns-trainingnav__count">8</span></summary>
<ul class="ns-trainingnav__list">
<li><a class="ns-trainingnav__link" data-state="done" href="#0">Profiles vs permission sets</a></li>
<li><a class="ns-trainingnav__link" href="#0" aria-current="page">The role hierarchy</a></li>
<li><a class="ns-trainingnav__link" href="#0">Sharing rules in practice</a></li>
</ul>
</details>
<details class="ns-trainingnav__module" open>
<summary><i class="ph ph-caret-right ns-trainingnav__twist" aria-hidden="true"></i>Automation: Flow<span class="ns-trainingnav__count">9</span></summary>
<ul class="ns-trainingnav__list"><li><a class="ns-trainingnav__link" href="#0">Record-triggered flows</a></li></ul>
</details>
</nav>Modules, sections and posts
THE STRUCTURAL DIFFERENCE BETWEEN TRAINING AND A COURSE. A course is a flat list of lessons; a training module is a body of writing with parts, so its posts group under section labels. One sidebar, three levels — track → module → section → post. Any deeper and it is a file tree, which is what this is designed not to be. Every row carries its kind as an icon, with the word on hover or focus.
markup
<nav class="ns-trainingnav" style="position:static;max-block-size:none;inline-size:100%;max-inline-size:19rem" aria-label="Training">
<a class="ns-trainingnav__track" href="#0">// Admin track</a>
<details class="ns-trainingnav__module" open>
<summary>
<i class="ph ph-caret-right ns-trainingnav__twist" aria-hidden="true"></i>
<span>Security and access</span>
<span class="ns-trainingnav__count">4</span>
</summary>
<div class="ns-trainingnav__bar"><progress class="ns-progress" value="2" max="4" aria-label="2 of 4 posts read"></progress></div>
<p class="ns-trainingnav__section">Concepts</p>
<ul class="ns-trainingnav__list">
<li><a class="ns-trainingnav__link" href="#0" data-state="done">
<i class="ph ph-article ns-trainingnav__icon" aria-hidden="true"></i>
<span>The permission set model</span><span class="ns-trainingnav__time">9m</span></a></li>
<li><a class="ns-trainingnav__link" href="#0" aria-current="page">
<i class="ph ph-video ns-trainingnav__icon" aria-hidden="true"></i>
<span>The role hierarchy</span><span class="ns-trainingnav__time">14m</span></a></li>
</ul>
<p class="ns-trainingnav__section">Practice</p>
<ul class="ns-trainingnav__list">
<li><a class="ns-trainingnav__link" href="#0">
<i class="ph ph-flask ns-trainingnav__icon" aria-hidden="true"></i>
<span>Build a sharing rule</span><span class="ns-trainingnav__time">22m</span></a></li>
<li><a class="ns-trainingnav__link" href="#0">
<i class="ph ph-exam ns-trainingnav__icon" aria-hidden="true"></i>
<span>Check what you know</span><span class="ns-trainingnav__time">6q</span></a></li>
</ul>
</details>
<details class="ns-trainingnav__module">
<summary>
<i class="ph ph-caret-right ns-trainingnav__twist" aria-hidden="true"></i>
<span>Automation</span>
<span class="ns-trainingnav__count">6</span>
</summary>
<ul class="ns-trainingnav__list">
<li><a class="ns-trainingnav__link" href="#0"><i class="ph ph-video ns-trainingnav__icon" aria-hidden="true"></i><span>Record-triggered flow</span><span class="ns-trainingnav__time">16m</span></a></li>
</ul>
</details>
</nav>Accessibility contract
- Open/closed, keyboard operation and in-page find all come from <details>
- aria-current="page" marks the unit AND is what the script reads to decide which module to open — one attribute, so highlight and announcement cannot drift
- Progressive: the markup ships every module
open, so with JS off nothing is hidden — the rail is only longer - Once the reader opens a module themselves the script stops managing state; a nav that re-collapses what you just opened is fighting you