v1.2.0
  1. ds
  2. Agent
  3. Session row

Session row

A dense List row with title, workspace, relative time and running or error state.

Show code
<ul class="list sm" aria-label="Sessions">
  <li id="retry-queue">
    <a class="li sess" href="#retry-queue" aria-current="page" data-state="running">
      <span class="li-ico"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 19h8"/><path d="m4 17 6-6-6-6"/></svg></span>
      <span class="li-main"><b>Retry queue fix</b><span class="mono">~/work/checkout</span></span>
      <span class="sess-side">
        <span class="sess-state">Running</span>
        <time class="sess-time" datetime="2026-10-21T02:37:00Z" title="21 Oct 2026, 02:37 UTC">4 min ago</time>
      </span>
    </a>
  </li>
  <li id="webhook-replay">
    <a class="li sess" href="#webhook-replay" data-state="error">
      <span class="li-ico"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg></span>
      <span class="li-main"><b>Webhook replay</b><span class="mono">~/work/event-relay</span></span>
      <span class="sess-side">
        <span class="sess-state">Error</span>
        <time class="sess-time" datetime="2026-10-21T02:23:00Z" title="21 Oct 2026, 02:23 UTC">18 min ago</time>
      </span>
    </a>
  </li>
  <li id="docs-index">
    <a class="li sess" href="#docs-index">
      <span class="li-ico"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/></svg></span>
      <span class="li-main"><b>Index the docs</b><span class="mono">~/work/fin1te.com</span></span>
      <span class="sess-side">
        <span class="sess-state">Idle</span>
        <time class="sess-time" datetime="2026-10-21T00:40:00Z" title="21 Oct 2026, 00:40 UTC">2 h ago</time>
      </span>
    </a>
  </li>
</ul>

A session row is a line in the list people scan to find their work. It carries four facts: the title, the workspace, the state and the last activity. The state is a word and a dot, and the selected row also takes the accent wash and a left rule.

This extends List. Use .list.sm for the frame and the density, and put .li.sess on each row. The title and workspace use the existing .li-main, and the icon uses .li-ico. Nothing in List was renamed.

Running, idle, disabled

Show code
<ul class="list sm" aria-label="Sessions">
  <li>
    <button class="li sess" type="button" data-state="running" aria-busy="true">
      <span class="li-ico"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg></span>
      <span class="li-main"><b>Nightly cost report</b><span class="mono">~/work/cloud</span></span>
      <span class="sess-side">
        <span class="sess-state">Starting</span>
        <time class="sess-time" datetime="2026-10-21T02:41:00Z">just now</time>
      </span>
    </button>
  </li>
  <li>
    <button class="li sess" type="button" disabled>
      <span class="li-ico"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/></svg></span>
      <span class="li-main"><b>Archived: Q3 migration</b><span class="mono">~/work/warehouse</span></span>
      <span class="sess-side">
        <span class="sess-state">Archived</span>
        <time class="sess-time" datetime="2026-09-28T18:10:00Z">28 Sep</time>
      </span>
    </button>
  </li>
</ul>

data-state="running" turns the icon and the state word accent, and pulses the dot while the session works. data-state="error" turns them red and tints the row. A row with no state is idle. A button row can be disabled when the session cannot be opened, and a starting row sets aria-busy="true".

API

ClassOnWhat it does
.list.smulThe frame and density. Any List size works; sm is the session list default.
.li.sessli > a, li > button, li > divOne session row. Keeps the List layout.
.li-icospanThe session glyph. Turns accent or red with the state.
.li-mainspanThe title and the workspace, using the List classes.
.sess-sidespanState and relative time, stacked and aligned right.
.sess-statespanA dot and a word: Running, Error, Idle, Archived.
.sess-timetimeThe relative time. Keep the absolute value in datetime and title.
data-state="running".li.sessAccent icon and state, pulsing dot.
data-state="error".li.sessRed icon and state, tinted row.
aria-current="page".li.sessThe open session. Accent wash and a left rule.
aria-selected="true".li.sessThe selected row in a listbox. The existing List selected style applies.
aria-busy="true".li.sessA session that is starting. Pair it with a visible state word.
:disabled, aria-disabled="true".li.sessDims the row and removes the pointer target.
Do
  • Put the title first and the workspace second.
  • Use a real link for an open session and a real button for an action.
  • Keep the state word next to the dot.
Don't
  • A row with only a title and a green dot.
  • Hiding the workspace at 390px. Let it truncate instead.
  • Using colour alone for running and error.

Accessibility

  • Use an a with an href for navigation, or a button for an action. Both are focusable and work from the keyboard. The focused row gets an inset outline that the list frame does not clip.
  • Selected state uses aria-current="page" for navigation. If the rows are a listbox, use role="listbox", role="option", roving tabindex and aria-selected; the styles are the same.
  • The state is a word. Running and error also tint the icon and the row, but the word is the signal.
  • Relative time sits in a time element with a machine-readable datetime. Keep the absolute time in title for people who need it.
  • The running dot stops pulsing under prefers-reduced-motion. The word remains.
  • At 390px the title and workspace truncate and the side stacks. No fact is removed.