Status

Where the work stands, for picking up in a new session. Generated and refreshed by the session-handoff skill; read CLAUDE.md first for the rules. Last refreshed: 2026-10-21.

Read this first

Token checks

Font-size coverage was widened on 2026-10-16: npm run check:tokens now also flags a raw size in a custom variable (--x-font-size: 14px), in the font shorthand, inside calc() and in inline fontSize in TSX (a test with deliberately bad values caught all of them before the real proposals were re-checked: 0 problems). npm run refresh runs the token check too. The Figma send checks font-size tokens bound to the captured text (untested end to end).

Figma

The send-to-figma skill (added 2026-10-16) captures a proposal's Storybook stories into Figma through the Figma MCP server (generate_figma_design, code to canvas). Changed 2026-10-16: it now sends only to the PDS-Proposals file (key AMGWJbraJoi2PKWnxo29Ah, the old PDS2 Working File renamed; its PROPOSALS page 154:1656 is a divider, proposal pages go after it), one page per proposal with every story in light and dark. Each proposal records its page in proposals/<Name>/figma.json (page id, name, URL, frame ids), so "update Figma" replaces the frames in place and a rename renames the page and frames; docs/FIGMA.md holds an index generated by npm run refresh. The blank-canvas and PDS Design Library branch destinations were removed. First real send done 2026-10-16: Spinner (10 frames) and Agent Avatar (12 frames) are on their own pages in PDS-Proposals, with figma.json written and linked from each HANDOFF.md; in-place update and rename are still untested. Captures only complete while the Browser pane is on screen, and a deleted page makes frames land on COVER (both are in the skill). Not bound to variables: the AI gradient, font weight and line height. the capture method itself was test-run earlier (Chain of Thought, Timeline, Timeline Item and Thinking State, 28 frames, deleted afterwards). Capture fixes still apply (auto body height, animations off). Net-new dependencies are sent to their own pages (node scripts/port-order.mjs --needs=<Name>), token binding is checked with get_variable_defs (the file has PDS Design Library v2 attached, confirmed 2026-10-16). Claude opens the page in the in-app browser after a send and asks once after a proposal is marked ready.

2026-10-20, all proposals on Figma: every proposal now has a page in PDS-Proposals (24 pages in the index). The designer hand-built Chat Attachment (ChatFileUpload), Chat Input, Chat Message, Chat Panel, Select, Suggestion Card and Feedback Bar as components, and figma.json records them with no frames; the other 17 are workflow captures (light only). The last send of 10 pages (44 stories: Avatar Label, Button, Chain of Thought, Code Diff, Icon, Icon Button, Identity Block, Labeled Divider, Menu Button, Panel) swapped 52 captured icons for library instances and bound the 4 monospace labels to the code font variable; icons at 14px, 18px and 28px (no library size), non-square icons, avatar icons and gradient icons stay as captured. The frames are the full viewport height (1191px), not hugging the content. If a capture batch ever fails, check tabs_context: a second Browser tab in front stalls captures.

Changed 2026-10-20: sends are light only (no dark frames; figma.json frames is now story id -> node id, older {light, dark} entries still work); icons found in the PDS Design Library v2 are swapped for its icon component sets (Size S/M/L/XL/2XL/3XL; the lookup, import and instance were tested, the position matching on a real capture was not); and unbound text font families are bound to the library's primitive/typography/font-family variables (tested on a throwaway node). Audit that prompted it: Timeline has 4 labels as raw Menlo (the code font token resolves to the first installed font; unbound and a missing font in Figma), and Chat Input and Chat Panel have some unbound Inter text in nested instances; none of those pages were changed. Existing pages keep their dark frames until "update Figma" is run.

Proposals (all under proposals/, Storybook group Component Proposals)

A second group, Recipes (story titles Recipes/<Name>; the files live in proposals/<Name>/ like every proposal), is for compositions of components that are documentation, not an API (for example an event log with an agent in it). It appears in the sidebar after Component Proposals once the first recipe story exists; none exists yet. Recipes so far: Event log with agent and Chat with an agent (proposals/ChatWithAgent/, added 2026-10-19: the interactive chat in the drawer, from the empty state to a conversation with a chain of thought, a suggestion card with a code diff, feedback thumbs and file drops; the expand-to-full-screen layout was removed the same day, see its decisions.md).

Sidebar order is alphabetical by story title (storySort in .storybook/preview.tsx). The AI chat pieces are in one group, AI Chat (2026-10-19): Chat Attachment, Chat Input, Chat Message, Chat Panel and Suggestion Card (Send Button was removed 2026-10-21: Send is now variant='primary' on Icon Button). They used to be split into Composer and Conversation sub-groups; those were removed the same day (too many levels for a few components each). Timeline, Thinking State, Chain of Thought and Feedback Bar stay at the top level because they are used outside chat too (for example on an Autopilot page).

Proposal What it is Base Marked net-new
Spinner color='agentic' (AI gradient) added to the existing color prop; hasAvatar shows the Zappy bolt in the ring in the plain foreground color (the disc and the gradient bolt were removed 2026-10-21) v2 Spinner no (extension)
Badge Copy of the v2 Badge (added 2026-10-19) plus color='agentic-filled' (the AI gradient as the fill); local mergeClasses stand-in and local Icon wrapper; ready-for-dev with HANDOFF.md 2026-10-20 (a11y panel not run; light-mode contrast of the white text on the gradient is an open question; Figma page Badge sent 2026-10-20, 2 frames) v2 Badge no (copy)
SectionMessage (Component Proposals/Section Message) ready-for-dev with HANDOFF.md 2026-10-20 (a11y panel not run; Figma page Section Message sent 2026-10-20, 6 frames; decided 2026-10-21: the agentic message uses the Agent Avatar in place of the icon, as the standard (no more suggestions under the stories), see its decisions.md). Copy of the v2 Section Message (added 2026-10-19) with type='agentic' (gradient border on a surface fill, iconName zappy or sparklesSolid, standard secondary Button CTA, filled agentic Badge); an avatarProps option swaps the icon for the Agent Avatar (shown under every story as captioned suggestions, for review with the engineer: the avatar on the gradient border, and the avatar on the discovery palette); depends on the local Button, Badge and AgentAvatar proposals v2 SectionMessage no (copy)
ChatPanel (Component Proposals/AI Chat/Chat Panel) ready-for-dev with HANDOFF.md 2026-10-20, unverified by eye. Frame of the AI chat drawer or docked panel: title row with built-in CloseButton, pinned header, scrolling children, pinned footer, all slots and all optional; headerInset / contentInset / footerInset (default / none bleed), hasHeaderDivider / hasFooterDivider; size m (default) / l; onFilesDrop + dropLabel turn on drag and drop of files over the whole panel (overlay on the content area); hasScrollToLatest + scrollToLatestLabel (a floating button when scrolled away from the end, and following the end only while at the end) and hasContentFade (a fade into the footer); a view switch (Compose / Chat / Review) is the PDS SegmentedButton in header. Stories: Default, Bleed, ContentOnly, Scrolling (a long conversation with the button and the fade) (the working chat moved to the recipe Recipes/Chat with an agent on 2026-10-19; no Drawer story: the PDS Drawer wraps children in a padded box, see decisions.md) none (new) yes
Icon Local Icon wrapper adding sparklesSolid (third-party agents) and microphoneLines; zappy already exists v2 Icon no
AgenticButton (Component Proposals/Buttons/Agentic Button) ready-for-dev with HANDOFF.md 2026-10-21 (a11y panel not run, no Figma page). A separate component: the secondary Button look with the AI gradient border and the gradient working spinner; every Button prop except variant; isAnimated (shimmer; the offset ring was dropped 2026-10-21). Reuses the Button's markup, classes and CSS. Used by AgenticMenuButton (the trigger) and the Panel's Approval Report copy of Button yes
IconButton variant='agentic' (the AI gradient border, always bordered; replaced isAgentic on 2026-10-21, so it is an extension like Send), variant='primary' (primary Button fill) and isWorking (spinner, disabled, aria-busy), added to replace SendButton: send is iconName='paperPlane', stop is iconName='stop' (new icon in the Icon wrapper), working is isWorking v2 IconButton no (extension)
AgenticMenuButton (Component Proposals/Buttons/Agentic Menu Button) ready-for-dev with HANDOFF.md 2026-10-21 (a11y panel not run, no Figma page). A copy of MenuButton with the trigger fixed: the AgenticButton (secondary look), or an Icon Button variant='agentic' when iconOnly; no variant or isAgentic. Used by Labeled Divider for the agentic tones copy of MenuButton yes
AgenticSplitButton (Component Proposals/Buttons/Agentic Split Button) Added 2026-10-21 (as Split Button, made a separate component the same day), ready-for-dev with HANDOFF.md 2026-10-21 (a11y panel not run, no Figma page). The PDS Split Button with the AI gradient as the border around the whole control, secondary look only, isAnimated shimmer; no variant; same height as an Agentic Button v2 SplitButton yes
Panel (Component Proposals/Panel) agentic-default, agentic-raised, agentic-sunken variants (existing surface plus the AI gradient border) and isAnimated shimmer v2 Panel no (extension)
ChatInput Textarea-style field with a toolbar inside it (aboveField, fieldHeader, actionsStart / actionsEnd slots; aboveField and fieldHeader added 2026-10-16); variant: default / compact; label hidden by default Textarea foundations yes
ChatAttachment (Component Proposals/AI Chat/Chat Attachment) One attached file or image for ChatInput's fieldHeader slot (added 2026-10-16): fileType file (fixed-width chip, name shortened in the middle, full name in a Tooltip) or image (square thumbnail, icon when no previewUrl); round remove button on hover, focus and always on touch Icon, IconButton, PDS Tooltip yes
Select (Component Proposals/Select) Wrapper around the published PDS Select with one new prop, variant: default (unchanged) or bare (no border, fill or container: the value and chevron on the surface, secondary text at rest and default on hover and open; label hidden, trigger hugs the selected value, list as wide as its longest option). It replaced ModelSelector on 2026-10-19: the model picker in Chat Input and the recipe is the bare Select. Option descriptions and an xs size were not carried over (see decisions.md). ready-for-dev with HANDOFF.md 2026-10-20 (a11y panel not run; its Figma page is the designer's hand-built SelectUtility set, figma.json has no frames) v2 Select no (extension)
ChatMessage (Component Proposals/AI Chat/Chat Message) ready-for-dev with HANDOFF.md 2026-10-20 (a11y panel not run; its Figma page now holds the designer's hand-built ChatMessage component set instead of captures, with variants Sender=Agent and Sender=Sender (the second looks like a naming slip for User); figma.json has no frames). One turn in a conversation; sender: agent (plain, full width) / user (filled bubble on the right, hugs content, max 80%); children slot; required hidden label for screen readers; plus a thin ChatMessageList that owns the gap between turns (20px) none (new) yes
SuggestionCard (Component Proposals/AI Chat/Suggestion Card) ready-for-dev with HANDOFF.md 2026-10-20 (a11y panel not run; needs Feedback Bar in the port order, which is ready; its Figma page is now the designer's hand-built component set on ↳ Suggestion card (300:7510), figma.json has no frames). An agent's proposed changes in chat, built on Panel (two optional footer slots: actionsStart at the left for the decision buttons, replaced by the result line once accepted or dismissed; dismissed also hides the changes, with Undo in actionsEnd as the screen's choice, and actionsEnd at the right in every state, for example a Feedback Bar): title, description, actions slot, state: pending / accepted (+ statusLabel); SuggestionChange rows (field label, before/after with dl) PDS Panel yes
FeedbackBar (Component Proposals/Feedback Bar) Built 2026-10-19, unverified by eye. ready-for-dev with HANDOFF.md 2026-10-20 (a11y panel not run; its Figma page is now the designer's hand-built component set, figma.json has no frames). Thumbs up and down for rating agent output, UI only (reports up / down / null through onValueChange; the screen owns what happens next). Built from the local IconButton (isPressed). Just the two thumbs (the bordered prompt-bar look was dropped 2026-10-19); statusLabel replaces the thumbs with text (Copy XS, secondary; announced); children slot for extra actions. Stories: Interactive (press a thumb, status shows then fades back) and All States (copy is the PDS Clipboard Button). Used in the Suggestion Card's new feedback slot (accepted state) and under replies in Chat Panel's With Sample Content. What the signal is for is undecided (open question in decisions.md) none (new) yes
ThinkingState Icon + label + optional elapsed time; sizes xs / s / m; AI shimmer on the label and a pulsing icon while active StatusIndicator family yes
Timeline (Component Proposals/Timeline/Timeline) List of events over time: ol/li semantics, spacing, optional hasRail joining the icons of neighbouring items; dividers, Chain of Thought or Thinking State can sit between items new yes
TimelineItem (Component Proposals/Timeline/Timeline Item) Renamed from AgentStep (2026-10-16). One event or piece of work: optional status icon, label, quiet secondary text, time, isAgentic, optional expandable detail, children slot new yes
ChainOfThought Collapsible list of agent steps (a Timeline without the rail); summary line is a Thinking State with a chevron; isOpen, expandWhenActive ThinkingState + Timeline + TimelineItem yes
AgentAvatar (Identity/Agent Avatar) Purpose-built agent avatar so people can tell an agent from a person: circle (default) or square shape, dark fill (--pds-color-foreground-default), icon in --pds-color-foreground-reverse, AI-gradient ring ("halo", hasHalo, default on) with a gap; iconName: zappy (Pantheon agents, default) or sparklesSolid (third-party); sizes xs-xl; required label (screen-reader text), linkContent + ariaLabel v2 Avatar, with image / per-user color / user fallback removed yes
AvatarLabel (Identity/Avatar Label) PDS Avatar Label with the Agent Avatar in place of every Avatar; avatarProps is required (it carries label, iconName, hasHalo); class stays pds-avatar-label v2 AvatarLabel yes
IdentityBlock (Identity/Identity Block) v2 Identity Block with the Agent Avatar in place of Avatar (avatarProps requires label); added a Collapsed story v2 IdentityBlock no
Code diff (Recipes/Code diff, folder proposals/CodeDiff/) A recipe since 2026-10-21 (it was a component): the package PanelList, PanelRow (expandable), CodeBlock (language='diff') and FileDiff, a list of changed files each expanding to its diff. The composition lives in a story-only helper, _story-helpers/CodeDiffSample; nothing to port as a component none (built from PDS parts) no
ContentDiff (Component Proposals/Content Diff) ready-for-dev with HANDOFF.md 2026-10-21 (a11y panel not run, no Figma page). A before and after of a piece of content, stacked like a text diff: the old value on a red line with a minus, the new on a green line with a plus. before, after, hidden beforeLabel / afterLabel. Taken out of SuggestionChange, which now composes it none (new) yes
Dropzone (Component Proposals/Dropzone) ready-for-dev with HANDOFF.md 2026-10-21 (a11y panel not run, no Figma page), unverified by eye. A compact area to add files by dragging them in or by browsing, from the designer's reference: a dashed outline with an upload icon, label and a browse button (real button, opens the file dialog; browseLabel); states default, drag over (solid highlighted outline), disabled; onFilesDrop(files) from a drop or the dialog, filtered by accept, one file unless multiple; the screen owns the file list. Not an extension of the PDS File Upload (a form field with no drag and drop) none (new) yes

The recommended port order is generated: see docs/PORT-ORDER.md (npm run plan:port). It starts from the priorities in docs/PRIORITY.md (hand-written: now, next, later; none set yet as of 2026-10-16), then dependencies. Older hand-written notes on cross-proposal dependencies follow, for what the script cannot see:

Cross-proposal dependencies (the port needs these together): IconButton (for isWorking) and the base Button use the local Spinner (for 'agentic'); IconButton, MenuButton and ThinkingState use the local Icon wrapper (for the new icons, including stop); MenuButton uses the local Button and IconButton; ChatInput composes IconButton (also as the Send button), MenuButton, Select (bare variant) and ChatAttachment (story only); ChainOfThought composes ThinkingState, Timeline and TimelineItem; AgentAvatar uses the local Icon wrapper (sparklesSolid); AvatarLabel renders the local AgentAvatar.

Conventions that were settled (don't relitigate)

Usage pages (new)

Every proposal has a <Name>/<Name>.mdx docs page, shown as Usage in the sidebar (<Meta of={...} name='Usage' />, Purpose, Usage, Implementation with a Canvas and Controls for one story). .storybook/main.ts now includes ../proposals/**/*.mdx. The designer has edited them by hand: Usage sections were removed from Button, Icon Button, Menu Button, Spinner and Chain of Thought; Agent Avatar, Agent Step, Icon, Thinking State, Chat Input and Avatar Label keep short ones. The wording is Claude's drafting plus her edits, so ask before adding guidance back.

Hosting

npm run build writes the static Storybook to storybook-static/. The current hosted copy is an unmerged PR on pantheon-systems/claude-prototypes; the plan is to host it from a Next.js site (see README).

Tooling in .storybook/

Things that behave in a way you might not expect

Open questions (also in each decisions.md)

Suggested next steps

  1. Decide whether the hosted Storybook should be refreshed with any later edits.
  2. The designer walks through each story in light and dark (hover, focus, open menus, Annotate on) and reports problems; fix those first.
  3. Resolve the open questions above, then run the handoff-package skill for the proposals without a handoff (Labeled Divider). Nothing has been checked against raw color values; grep before handoff (the Spinner mask data URIs contain stroke='black', alpha-only).
  4. Commit.