From 46cbd84dcbe1c5d7eb85ed200f4d2fc6dbfc1222 Mon Sep 17 00:00:00 2001 From: Eric Baruch Date: Wed, 22 Apr 2026 18:41:52 -0700 Subject: [PATCH] =?UTF-8?q?feat(design):=20voice=20tokens=20=E2=80=94=20co?= =?UTF-8?q?py=20style=20guidance=20for=20the=20agent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit stream-ui is rendered by an agent, so component copy is part of the design system alongside colors/typography. Adds a `voice:` section to DESIGN.md with six tokens: formality, density, capitalization, emoji, errorTone, ctaStyle. Each has a prose entry with a concrete do/don't example. Voice is a namespaced extension (unknown-but-preserved per the spec — linter accepts it, emits no CSS vars). The agent reads DESIGN.md at cold start and honors the guidance in streamed copy. Verified with a live probe: prompt: "primary CTA for saving, plus error alert if save fails" → button: "Save" (short-verb CTA ✓) → alert: "Couldn't save — name is required." (matter-of-fact ✓) Agent's own narration cited "matter-of-fact copy", "short-verb CTA", "sentence-case labels" — the voice tokens are reaching the system prompt and shaping output. --- DESIGN.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/DESIGN.md b/DESIGN.md index 64d92c4..c529cf6 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -79,6 +79,13 @@ components: textColor: "{colors.link}" link-hover: textColor: "{colors.link-hover}" +voice: + formality: conversational + density: concise + capitalization: sentence-case + emoji: sparingly + errorTone: matter-of-fact + ctaStyle: short-verb variants: dark: colors: @@ -144,6 +151,35 @@ Use `easing.standard` for general acceleration; `emphasized` for first-time reveals (enter animations). No bounce, no overshoot — streaming UI should feel precise, not playful. +## Voice + +Stream-UI is rendered by an agent, so copy is part of the design system. +Component labels, alert text, empty-state prose and button CTAs all inherit +the tokens below. These apply to every string the agent streams into a spec. + +- **formality: conversational** — write like a helpful coworker, not a lawyer + and not a TV announcer. Contractions are fine. Second person ("you") is + welcome. Never "please click here" — respect the user's time. +- **density: concise** — one sentence where one sentence works. No preamble + ("Here's a button for you!"), no restating the obvious. Agents often want + to narrate the spec they just emitted — don't; the UI shows itself. +- **capitalization: sentence-case** — `Save changes`, not `Save Changes`. + Applies to buttons, headings, table headers, menu items. Preserves proper + nouns and brand names as written. +- **emoji: sparingly** — reserved for status (✓ ✗ ⚠) or when the user's own + prompt establishes a playful tone. Never in error messages, never in CTAs. +- **errorTone: matter-of-fact** — "Couldn't save — name is required" beats + "Oops! Something went wrong 😔". State the cause, suggest the fix, no + apology. Reserve apologies for our failures, not the user's input. +- **ctaStyle: short-verb** — primary buttons use a single verb when possible + (`Save`, `Continue`, `Delete`), verb + object when not (`Add item`, not + `Add a new item to the list`). Cancel/dismiss buttons stay `Cancel` — not + `Nevermind`, not `Go back`, not `×`. + +When a prompt is ambiguous between two voices, pick the one that matches +these tokens. When the user's prompt explicitly overrides (e.g. "make the +copy playful"), honor the prompt. + ## Components Component tokens map to stream-ui's built-in kinds. Variants (hover, pressed,