112Conversation rail
History, grouped by recency, in the terminal-row idiom the rest of the system uses for lists. The course a conversation belongs to is the mono line above the question — a student's chat history is organised by module, not by date.
Use it for
- The assistant's history sidebar
- Grouping by Today / Earlier this week / Earlier — a date stamp per row is noise
- The quota meter at the foot, where it is information rather than a warning
Not for
- A navigation menu — this is a list of documents, use Sidebar nav for routes
- An icon-only collapsed strip: there is no glyph for “the one about triggers”, so the rail collapses to nothing instead
Anatomy
markup
<aside class="ns-ai__side" style="block-size:26rem;border:1px solid var(--color-border);border-radius:var(--radius-card);overflow:hidden">
<div class="ns-aiside__head">
<span class="ns-aiside__brand"><i class="ph ph-sparkle" aria-hidden="true"></i>Namaste AI</span>
<button type="button" class="ns-btn ns-btn--outline ns-btn--sm ns-btn--block"><i class="ph ph-plus" aria-hidden="true"></i> New chat</button>
<span class="ns-input-wrap">
<i class="ph ph-magnifying-glass ns-input-wrap__icon" aria-hidden="true"></i>
<input class="ns-input ns-input--has-icon" type="search" placeholder="Search chats" aria-label="Search conversations">
</span>
</div>
<div class="ns-aiside__list">
<div class="ns-aiside__group">
<p class="ns-aiside__label">Today</p>
<a class="ns-aiside__item" href="#0" aria-current="true">
<span><span class="ns-aiside__course">Apex basics</span><span class="ns-aiside__title">Why does my trigger hit governor limits?</span></span>
<span class="ns-aiside__when">09:12</span>
</a>
<a class="ns-aiside__item" href="#0">
<span><span class="ns-aiside__course">Career</span><span class="ns-aiside__title">Resume review for admin roles</span></span>
<span class="ns-aiside__when">08:40</span>
</a>
</div>
<div class="ns-aiside__group">
<p class="ns-aiside__label">Earlier this week</p>
<a class="ns-aiside__item" href="#0">
<span><span class="ns-aiside__course">Flows, end to end</span><span class="ns-aiside__title">Record-triggered vs scheduled flow</span></span>
<span class="ns-aiside__when">Tue</span>
</a>
</div>
</div>
<div class="ns-aiside__foot">
<div class="ns-aiside__quota">
<span class="ns-aiside__quota-row">Questions today <b>12 / 30</b></span>
<progress class="ns-progress" value="12" max="30" aria-label="12 of 30 questions used today"></progress>
<a class="ns-link" href="#0">Go unlimited with Pro</a>
</div>
</div>
</aside>Empty history
Told honestly, not as a skeleton pretending to load. It says where the chats will go and what groups them.
markup
<aside class="ns-ai__side" style="block-size:14rem;border:1px solid var(--color-border);border-radius:var(--radius-card);overflow:hidden">
<div class="ns-aiside__list">
<div class="ns-empty">
<i class="ph ph-chats-circle ns-empty__icon" aria-hidden="true"></i>
<p class="ns-empty__title">No conversations yet</p>
<p class="ns-empty__text">Your chats appear here, grouped by the course they belong to.</p>
</div>
</div>
</aside>Accessibility contract
- The current conversation is aria-current="true", not a class
- Rows are real links — a conversation is a page, and middle-click must work