The text-like wait state — three currentColor dots sweeping like an ellipsis being typed; where Spinner marks a region waiting for content, dots say something is being composed: generation, chat, an async row filling in. Each dot is a quarter of the box at radius.full, spaced by space.1; the sweep runs at 6× motion.duration.slow on motion.easing.standard.
One sm/md/lg dialect on the shared icon scale, same as Spinner; the default is medium.
| Example | Size | Modifier | Box | Usage |
|---|---|---|---|---|
| Small | --sm | size.icon.sm | Inline with text, dense rows | |
| Medium | ds-loading-dots | size.icon.md | The default — chat and generation surfaces | |
| Large | --lg | size.icon.lg | Feature areas, empty states |
The color contract is Spinner's: currentColor, so the dots take the text color of wherever they sit. The wiring differs by whether visible text accompanies them.
| Example | Context | Wiring | Inherits | Usage |
|---|---|---|---|---|
| Standalone | role="status"aria-label | text.primary | A typing indicator or generation placeholder announces itself | |
| Thinking | After text | aria-hidden | text.primary | The dots are the sentence's ellipsis — the text carries the announcement |
Dots and Spinner split one job: dots for composition, Spinner for waiting.
| Verdict | Rule |
|---|---|
| Do | Reach for dots when something is being written or generated — chat replies, streaming text, an async cell filling in; a region simply waiting for content gets a Spinner. |
| Do | Announce standalone dots with role="status" plus aria-label; beside visible text they go aria-hidden — the text carries the update. |
| Don’t | Ship more or fewer than exactly three ds-loading-dots__dot spans — the sweep is choreographed for three. |
| Don’t | Color the dots directly — recolor their context and currentColor follows. |