Handoff: Agentic Button
What and why
A button for an action the agent does: the secondary Button look with the AI gradient as its border, and the gradient working spinner. It is a separate component, not an option of the Button (decided 2026-10-21; it was an isAgentic prop, then a variant attempt before that). It takes every Button prop except variant, because there is one look: the secondary treatment, not the primary one. It reuses the Button's markup, classes (pds-button, pds-button--secondary, the sizes) and CSS file, and adds the class pds-agentic-button.
- Figma / Jira: none. Source: Erika's design for an agentic button. The Figma page of the Button is out of date (it still shows the old agentic option).
- Context:
context.md
Exploration and decisions
- Separate component, secondary only. The agentic button is its own component; the Button goes back to plain PDS. No primary (dark) version.
- Border technique.
--pds-gradient-ai-activeis a gradient, so it cannot go inborder-color. The border is transparent, the gradient paints the border-box, and the secondary fill sits on the padding-box over an opaque--pds-color-surface-defaultlayer so the translucent secondary fill does not show the gradient through. - Working spinner.
isWorkingalways shows the gradient Spinner;isLoadingclears the gradient so the pulse shows cleanly. isAnimatedshimmers the border (the animated agentic Panel's loop; off for reduced motion). Opt-in; the stories turn it on.
Full list: decisions.md.
API
Every Button prop except variant (see the Button handoff), plus:
| Prop | Type | Default | Purpose |
|---|---|---|---|
isAnimated |
boolean |
false |
Shimmers the gradient border. Off for reduced motion. |
Variants and states: all four sizes; default, disabled, loading, working (with disableWhenWorking), with icon, tally and status dot; the gradient border. Stories: Default, With Icon, With Tally, With Status Dot, Loading State, Working State, Working State Interactive, With Offset, All States, All Sizes.
Tokens used
--pds-animation-duration-ai-shimmer--pds-color-surface-default--pds-gradient-ai-active
The rest is the Button's own (it reuses its CSS).
Impact
From impact.md: no existing PDS component is reached; everything is scoped to .pds-agentic-button. Proposals that build on it: AgenticMenuButton (its trigger) and Panel (the Approval Report's Approve button), and through them LabeledDivider. The Section Message used it briefly and now uses the standard secondary Button.
Reused vs net-new
- Reused: the whole Button (markup, classes, CSS),
Icon,Tally,Tooltip, the localSpinner(itsagenticcolor). - Net-new:
.pds-agentic-buttonwith--animated, and the propisAnimated. Seecustom.md(no raw values).
Accessibility
- Unchanged from the Button: a native
button, visible focus ring,ariaLabel, and the loading and working states. - The gradient border is decorative; the label and the spinner's label carry the meaning.
- The a11y panel has not been run on these stories, and light and dark were not checked by eye in a session. Run it before the port.
Decisions and open questions
- Should there be a filled (primary) agentic button later, for the one main action on a screen?
- It repeats the Button's component logic (about 300 lines). The port may prefer to let the Button take the agentic styling as an internal detail; that would reintroduce a prop on Button.
Port notes
- New component: use
npm run generate:component, then copy the files. It reuses the PDS Button's markup and CSS (the local base copy is inproposals/_base/Button/, see its README). The only change over the published Button is adisplay: contentsspan with the classpds-button__leadingaround the leading spinner, icon and status dot (it keeps page translation from breaking React); add it to the Button when porting. It also needs Spinner (theagenticcolor). - Swap the local
utilsstand-ins (mergeClasses,StatusDot,extractText) for the real@libs/...imports.
Preview
npm run storybook, then Component Proposals/Buttons/Agentic Button. Figma: none yet.