Handoff: Icon (agentic icons)
What and why
Agentic surfaces (agentic Button, Icon Button, Spinner, Thinking State, the Agent Avatar) need an icon that says who the agent is, and the Chat Input needs a voice button. This proposal adds two icon names to the PDS v2 Icon set. Icon itself does not change.
sparklesSolid(new): other, third-party agents. A sharp, solid sparkles glyph.microphoneLines(new): the voice button in Chat Input.zappy: PDS agents. Already in v2 as a custom icon; shown beside the new ones.Figma / Jira: none. Source: Erika's SVG for sparkles (Font Awesome Pro 7.3.1, sharp solid) and a Figma export for the microphone.
Context:
context.md
Exploration and decisions
- New icons,
Iconunchanged. One local wrapper (Icon.tsx) renders the new names with v2'sIconmarkup and passes every other name to the publishedIcon. The port deletes the wrapper. - Name
sparklesSolid, per v2's{name}Solidconvention next to the existingsparkles. Open: it says "solid", not "sharp". - Custom path, not a Font Awesome registry entry, because v2's registry only takes the
regular,solidandbrandsstyles and the supplied glyph is sharp solid. The path was cropped to the glyph and scaled to 512 high with the origin at 0,0, like v2's other custom icons (519 x 512, one compound path). microphoneLinesis Font Awesome Proregular, so the port can add it as a registry entry (faMicrophoneLines) and let v2 extract it, instead of a hand path.Iconconsumers in this repo (IconButton, MenuButton, ThinkingState, Timeline and others) import the local wrapper so the new names work.
API
Icon keeps the v2 API. The only change is the type of iconName, which widens to include the new names.
| Prop | Type | Default | Purpose |
|---|---|---|---|
iconName |
PDSIcon | 'sparklesSolid' | 'microphoneLines' |
required | Which icon to render. |
size |
v2 icon sizes | 'xl' |
Unchanged from v2. |
display, verticalAlign, className, style |
as v2 | as v2 | Unchanged from v2. |
Variants and states: the new icons at every size (xs to 4xl), next to zappy and a Font Awesome icon for optical balance.
Tokens used
None. The icons are currentColor paths.
Impact
From impact.md: nothing reaches existing components; the change is two new names. It is the most depended-on proposal here: AgentAvatar, ChainOfThought, CodeDiff, IconButton, LabeledDivider, MenuButton, Panel, SuggestionCard, ThinkingState and Timeline use it directly, and the rest reach it through them. Port it first.
Reused vs net-new
- Reused: the published
Iconfor every existing name. - Net-new: two icon names (
sparklesSolid,microphoneLines); no component, class or variable. Seecustom.md.
Accessibility
- The markup matches v2's
Icon:aria-hidden='true'withfocusable='false', so a decorative icon is not announced. An icon that carries meaning on its own needs a label from its parent (a button'saria-label, for example), as with any v2 icon. - axe-core (the engine behind the Storybook a11y panel) found no violations on the Default and All sizes stories in light and dark.
Decisions and open questions
- Rename
sparklesSolid? It says "solid" not "sharp". - Licence. The sparkles and microphone paths come from Font Awesome Pro. v2 already extracts Pro paths into
generated-icon-data.ts, so this is consistent, but confirm the licence covers a hand-copied glyph. - Optical balance at
xsto4xlnext to Font Awesome icons has not been checked by eye in a session. - Inline style warning.
npm run check:tokenswarns aboutstyle={{ display, verticalAlign, ...style }}inIcon.tsx. It is copied from v2's ownIconmarkup so the new icons size and align the same way, and goes away when the wrapper is deleted in the port. - Registry entry (suggested):
sparklesSolid: { source: 'custom', aliases: ['ai', 'agent', 'third-party', 'magic'], categories: ['custom', 'status'] }, matchingzappy. Confirm.
Port notes
- Put the
sparklesSolidpath data incustom-icons.tsxas atype: 'path'icon and add the registry entry. AddmicrophoneLinesas a Font Awesome entry (faMicrophoneLines, styleregular) in the registry. - Delete the local
Iconwrapper (proposals/Icon/Icon.tsx). The proposals that import it switch to the realIcon. - Port this first: every other proposal here that shows an icon depends on it. See
docs/PORT-ORDER.md.
Preview
npm run storybook, then Component Proposals/Icon.
Figma: https://www.figma.com/design/AMGWJbraJoi2PKWnxo29Ah/PDS-Proposals?node-id=374-47, page Icon (2 stories, light only; captures of Storybook with library icons swapped in, sent 2026-10-20).