Activity
Says what the agent is doing now in plain words, and sums up the turn when it ends.
Examples
- Refunded 3 orders, ran an eval
- Refunded 3 orders, 1 slow
- Looked up 2 orders, 1 failed
- Stopped by Ana Marsh
- Looked up order 4812212ms
- Read refund-policy.md480ms
- Sent the receipt to ana@example.commailbox full
- Retry for Maya Chen to approvedenied
State
waiting
- Searching docs
activedefault
- Refunded 3 orders
done
Status
- Refunded 3 orders
okdefault
- Refunded 3 orders
warn
- Looked up 2 orders
fail
- Stopped by Ana Marsh
stopped
Sizes
- Refunded 3 orders
defaultdefault
- Refunded 3 orders
sm
States
waiting
- Searching docs
active
- Refunded 3 orders
done
- Looked up 2 orders
fail
Usage
When to use it
- Use
- The agent works for a few seconds before any text, and the person needs to know it is alive.
- Use
- A finished turn folds its tool rows to one line, like "Worked for 14s".
- Not for
- A thread already shows each tool as a running row. Use Tool call.
- Not for
- The wait is a determinate task with a percent. Use Progress.
- Not for
- The model's thinking is the content the person reads. Use Reasoning.
Rules
8 rules
- Must
- Write label as an -ing verb and its object: "Searching docs", "Running eval". Because the done label is derived from it by pastTense, so "Searching docs" becomes "Searched docs" and a noun phrase does not.
- Must
- Use waiting only for the gap before the first token, reasoning or tool call of a turn. Because the loader is the first-wait state; once anything arrives the phrase or the thread row takes over.
- Should
- Pass doneLabel with a summary of the whole turn, and joinSummary for trouble counts. Because the default is the past tense of the last phrase, which tells only about the last step of the turn.
- Must
- Pass status="warn" or "fail" when the turn warned or failed; stopped when a person ended it. Because the end word and the reserved hue are the only signal that a turn did not go well, and ok hides it.
- Must
- Pass announce={false} on every Activity inside a Conversation. Because Conversation makes one announcement per turn end, and each Activity with its own region reads the same turn again.
- Should
- Leave delay, minLoader, minDisplay and settle at their defaults. Because they are tuned so a reply under 150ms never flashes a loader and a phrase stays long enough to read.
- Should
- Close an ActivityGroup for a finished turn and open it only while the person is reading the rows. Because the summary line already says what happened, and a thread of open groups becomes a list of every call.
- Never
- Add a spinner, dots or an animated phrase of your own beside Activity. Because the running arc is the one moving shape in the system, and a second one shows two kinds of working.
State order
4 states, highest first
- 1
- waiting
- 2
- active
- 3
- done
- 4
- idle
Accessibility
6 checks
- One polite status region reads the loader label and the settled phrase; live phrases are never read, so a burst of tools does not talk over the person.
- aria-busy is set while it is waiting or active.
- Done is words: warn and fail add their word ("failed", "with a warning") and a status mark, so grayscale and screen readers get it too.
- The step glyph is aria-hidden; the row says its state in words.
- ActivityGroup is a disclosure button with a 32px row (44px on touch) and a 2px ink focus ring.
- Under reduced motion the arc stops and stays a static 3/4 arc.
Keyboard
1 key
- Enter, Space on an ActivityGroup
- Opens or closes the rows.
Edge cases
10 edge cases
- Reply in under 150ms
- The loader never shows.
- Loader shown, reply lands
- It stays at least 500ms, then gives way, so it never flashes for one frame.
- Phrases arrive faster than one a second
- Each holds for 1000ms and only the newest waiting one shows next; the rest are skipped.
- Tool ends and the next starts
- It waits 400ms before settling, so the two read as one live phrase.
- Phrase is not an -ing verb
- pastTense returns it unchanged, so write the phrase with an -ing verb.
- Summary already says "stopped"
- The end word is not repeated.
- No label and no doneLabel
- Renders nothing visible, and no region text.
- Long phrase
- Truncates with an ellipsis in one line.
- Right to left
- The arc and text mirror; the group chevron flips.
- Zoom 200%
- The row grows with the text and the phrase truncates.
API
15 props
labelstringactivebooleandefaultfalsewaitingbooleandefaultfalsedoneLabelstringstatus'ok' | 'warn' | 'fail' | 'stopped'default'ok'kind'agent' | 'key' | 'run' | 'deploy' | 'model'default'agent'size'default' | 'sm'default'default'minDisplay, settlenumberdefault1000, 400delay, minLoadernumberdefault150, 500announcebooleandefaulttruelabelsActivityLabelsdefaultEnglish wordsActivityGroup summary, meta, liveReactNode, ReactNode, booleandefaultrequired, -, falseActivityGroup open, defaultOpen, onOpenChangeboolean, boolean, (open) => voiddefault-, false, -StepGlyph state'running' | 'done' | 'fail' | 'stopped'defaultrequiredHelperspastTense, joinSummary, pickActivity
Tokens
14 tokens
--row-sm- 32px
--control-sm- 28px
--text-1- var(--ink)
--text-2- oklch(var(--ink-c) / 0.80)
--text-3- oklch(var(--ink-c) / 0.66)
--warn-text- oklch(49% 0.100 68)
--fail-text- oklch(51% 0.180 26)
--surface-hover- oklch(var(--ink-c) / 0.05)
--surface-pressed- oklch(var(--ink-c) / 0.08)
--radius-soft- 6px
--type-label- 400 14px/16px var(--font-sans)
--type-body-sm- 380 13px/18px var(--font-sans)
--dur-fast- 120ms
--ease-step- cubic-bezier(0.2, 0, 0, 1)