library / 17

Installation

tokens.css + task-list.css + button.css
head.html
<link rel="stylesheet" href="tokens.css">
<link rel="stylesheet" href="components/task-list/task-list.css">

Basic

task-list / Basicinteractive
50%
Review refundpending

Waiting on approval.

Verify vendor recordsin progress

Checking 12 suppliers.

Cancelled importcancelled

Stopped before writing files.

Build reorder listcompleted

7 SKUs queued.

Code

task-list.html + task-list.css
task-list
<style>
/* agent-ui / task-list — rows + capsules (formerly task-rows) */
/* agent-ui / task-rows — first-class component (promoted from host extracts). */
/* 06 Task rows */
.au-task-rows { display: grid; gap: 8px; }
.au-task-row {
  background: var(--au-surface);
  border: 1px solid var(--au-border-color);
  border-radius: var(--au-radius-md);
  padding: 12px;
}
.au-task-row > summary {
  align-items: center;
  cursor: pointer;
  display: flex;
  gap: 8px;
  list-style: none;
}
@media (max-width: 640px) {
  .au-task-row > summary { min-height: 40px; }
}
.au-task-row > summary::-webkit-details-marker { display: none; }
.au-task-row[open] > summary .au-task-row__meta {
  color: var(--au-fg);
}
.au-task-rows .au-task-row {
  animation: au-task-row-in 280ms var(--au-ease) both;
}
.au-task-rows .au-task-row:nth-child(2) { animation-delay: 40ms; }
.au-task-rows .au-task-row:nth-child(3) { animation-delay: 80ms; }
.au-task-rows .au-task-row:nth-child(4) { animation-delay: 120ms; }
@media (prefers-reduced-motion: reduce) {
  .au-task-rows .au-task-row { animation: none; }
}
.au-task-row__index {
  color: var(--au-fg-subtle);
  font: 500 12px/1 var(--au-font-mono);
  min-width: 1.2rem;
}
.au-task-row__title { color: var(--au-fg); flex: 1; font: 500 13px/1.3 var(--au-font-sans); }
.au-task-row__meta { color: var(--au-fg-muted); font: 400 12px/1.3 var(--au-font-sans); }
.au-task-row__body {
  color: var(--au-fg-muted);
  font: 400 13px/1.45 var(--au-font-sans);
  margin: 8px 0 0;
  padding-left: calc(1.2rem + 8px);
}
.au-task-capsules { display: flex; flex-wrap: wrap; gap: 8px; }
.au-task-capsule {
  background: var(--au-surface);
  border: 1px solid var(--au-border-color);
  border-radius: var(--au-radius-pill);
  color: var(--au-fg-muted);
  font: 400 12px/1.3 var(--au-font-sans);
  padding: 8px 12px;
}

@keyframes au-task-row-in {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}


.au-task-list { display: contents; }

/* --- status vocabulary + visual status (adopted from tool-ui Plan;
     status glyphs sharpened from 21st.dev agent-elements todo-tool) ---
   Each task row carries data-au-state = pending | in_progress | completed | cancelled.
   The status badge encodes state by SHAPE, not just color, so it stays legible
   for color-blind and low-vision readers and at a glance:
     pending      → hollow circle
     in_progress  → arrow (→)
     completed    → check (✓)
     cancelled    → hollow circle with line-through title
   Defaults stay text-forward / monochrome (token-driven). */

.au-task-row__status {
  position: relative;
  border: 1.5px solid var(--au-border-emphasis);
  border-radius: 999px;
  color: var(--au-fg-muted);
  flex: none;
  font: 700 10px/1 var(--au-font-mono);
  height: 16px;
  width: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.au-task-row__status::before,
.au-task-row__status::after {
  position: absolute;
}

.au-task-row[data-au-state="pending"] .au-task-row__title { color: var(--au-fg-muted); }

.au-task-row[data-au-state="in_progress"] .au-task-row__status {
  border-color: var(--au-action);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--au-action) 18%, transparent);
  color: var(--au-action);
}
.au-task-row[data-au-state="in_progress"] .au-task-row__status::after {
  content: "→";
}
.au-task-row[data-au-state="in_progress"] .au-task-row__title { color: var(--au-fg); }

.au-task-row[data-au-state="completed"] .au-task-row__status {
  background: var(--au-success);
  border-color: var(--au-success);
  color: var(--au-on-accent);
}
.au-task-row[data-au-state="completed"] .au-task-row__status::after {
  content: "✓";
}
.au-task-row[data-au-state="completed"] .au-task-row__title { color: var(--au-fg-muted); }

.au-task-row[data-au-state="cancelled"] .au-task-row__status {
  background: var(--au-danger);
  border-color: var(--au-danger);
}
.au-task-row[data-au-state="cancelled"] .au-task-row__title {
  color: var(--au-fg-subtle);
  text-decoration: line-through;
}

/* --- task progress indicator (adopted from tool-ui Plan progress) --- */
.au-task-rows__progress {
  align-items: center;
  display: flex;
  gap: 8px;
}
.au-task-rows__progress-track {
  background: var(--au-surface-muted);
  border-radius: var(--au-radius-pill);
  display: block;
  flex: 1;
  height: 4px;
  overflow: hidden;
}
.au-task-rows__progress-fill {
  background: var(--au-action);
  border-radius: var(--au-radius-pill);
  display: block;
  height: 100%;
}
.au-task-rows__progress-value {
  color: var(--au-fg-subtle);
  font: 500 12px/1 var(--au-font-mono);
}

@media (prefers-reduced-motion: reduce) {
  .au-task-rows__progress-fill { transition: none; }
}
</style>

<div class="au-task-rows" data-au-component="task-list" aria-label="Tasks"><div class="au-task-rows__progress" aria-label="Task progress"><span class="au-task-rows__progress-track" aria-hidden="true"><span class="au-task-rows__progress-fill" style="width: 50%"></span></span><span class="au-task-rows__progress-value">50%</span></div><details class="au-task-row" data-au-state="pending" open data-task-id="task-1"><summary><span class="au-task-row__index" aria-hidden="true">1</span><span class="au-task-row__status" aria-hidden="true"></span><span class="au-task-row__title">Review refund</span><span class="au-task-row__meta">pending</span></summary><p class="au-task-row__body">Waiting on approval.</p></details><details class="au-task-row" data-au-state="in_progress" open data-task-id="task-2"><summary><span class="au-task-row__index" aria-hidden="true">2</span><span class="au-task-row__status" aria-hidden="true"></span><span class="au-task-row__title">Verify vendor records</span><span class="au-task-row__meta">in progress</span></summary><p class="au-task-row__body">Checking 12 suppliers.</p></details><details class="au-task-row" data-au-state="cancelled" data-task-id="task-4"><summary><span class="au-task-row__index" aria-hidden="true">4</span><span class="au-task-row__status" aria-hidden="true"></span><span class="au-task-row__title">Cancelled import</span><span class="au-task-row__meta">cancelled</span></summary><p class="au-task-row__body">Stopped before writing files.</p></details><details class="au-task-row" data-au-state="completed" open data-task-id="task-3"><summary><span class="au-task-row__index" aria-hidden="true">3</span><span class="au-task-row__status" aria-hidden="true"></span><span class="au-task-row__title">Build reorder list</span><span class="au-task-row__meta">completed</span></summary><p class="au-task-row__body">7 SKUs queued.</p></details></div>

Component contract

Install
tokens.css · task-list.css · button.css
States
Host-owned via data-au-state and documented variants
Host
content, state transitions, and execution behind actions
For agents
task-list.contract
# agent-ui / task-list
component: task-list
selector: .au-task-list
data_au_component: task-list
purpose: Task rows with a status vocabulary (pending/in_progress/completed/cancelled), collapsible details, and an optional progress indicator.

install:
  - tokens.css
  - task-list.css
  - button.css when rendering actions

states: Host-owned via data-au-state and documented variants.
css_variables: Uses shared semantic tokens.
events: native form, focus, and click only — no custom events or runtime required
no_javascript: Markup and native controls remain usable without script.
host_owns: The host owns content, state transitions, and execution behind actions.
accessibility: Prefer labelled regions and text status, not color alone.
security: Escape untrusted model and tool text before insertion.

rules:
  - Host owns execution, authorization, persistence, validation, and state transitions.
  - Components render host-provided state; they never execute tools or imply approval.
  - Escape untrusted model output, tool args, and tool output before insertion.
  - Use only documented data-au-* attributes and data-au-state values.
  - Keep the no-JS path usable. Do not add React, Tailwind, bundlers, or remote assets.
source: components/task-list/task-list.{html,css} + README.md + fixture.html