← All proposals

Icon: agentic icons

Add the new sharp, solid sparkles glyph to the Icon set alongside zappy.

Extends a PDS componentOpen in Storybook

proposals/Icon/HANDOFF.md71 lines · View on GitHub

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, Icon unchanged. One local wrapper (Icon.tsx) renders the new names with v2's Icon markup and passes every other name to the published Icon. The port deletes the wrapper.
  • Name sparklesSolid, per v2's {name}Solid convention next to the existing sparkles. Open: it says "solid", not "sharp".
  • Custom path, not a Font Awesome registry entry, because v2's registry only takes the regular, solid and brands styles 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).
  • microphoneLines is Font Awesome Pro regular, so the port can add it as a registry entry (faMicrophoneLines) and let v2 extract it, instead of a hand path.
  • Icon consumers 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 Icon for every existing name.
  • Net-new: two icon names (sparklesSolid, microphoneLines); no component, class or variable. See custom.md.

Accessibility

  • The markup matches v2's Icon: aria-hidden='true' with focusable='false', so a decorative icon is not announced. An icon that carries meaning on its own needs a label from its parent (a button's aria-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 xs to 4xl next to Font Awesome icons has not been checked by eye in a session.
  • Inline style warning. npm run check:tokens warns about style={{ display, verticalAlign, ...style }} in Icon.tsx. It is copied from v2's own Icon markup 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'] }, matching zappy. Confirm.

Port notes

  • Put the sparklesSolid path data in custom-icons.tsx as a type: 'path' icon and add the registry entry. Add microphoneLines as a Font Awesome entry (faMicrophoneLines, style regular) in the registry.
  • Delete the local Icon wrapper (proposals/Icon/Icon.tsx). The proposals that import it switch to the real Icon.
  • 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).