SignatureStack
Hero example
When to use
Reach for SignatureStack when a multi-document signing package needs visibility before send — typically a financing close (subscription + SAFE + side letter + IP-assignment), an employee package (offer + at-will agreement + IP assignment + option grant), or any DocuSign-style envelope. The card carries enough metadata (signer count, pages, size, recipient list) for the user to verify the package contents and recipients before the send-for-signature action triggers the envelope.
Don't reach for SignatureStack for a single-document signing flow — for one document use BoardConsentCard (for resolutions) or a dedicated document-detail page. Don't use it once the package is sent either; post-send state belongs in a dedicated tracking page with per-recipient progress, not the staging card.
Anatomy
Four structural regions stacked top-to-bottom:
- Header block. Eyebrow ("Documents · Awaiting your review") + package name + right-aligned status
Pill(defaultDraft/ amber). Separated from the body by a 1px--ink-6rule. - Document list (
<ul>). One row perSignatureDoc. Each row: 28×36 document thumb (background--ink-4), title, meta line ("{signers}signers ·{pages}pages ·{size}") withBulletseparators. - Footer band. 6/20/14 padding wrapper hosting:
- Recipient stack. Overlapping 24px circular avatars (initials only, 2px ring in
--paper-50), 8px negative margin on overlap,{N} recipientslabel. - Footer actions. Primary
Send for signature+ secondaryEdit.
- Recipient stack. Overlapping 24px circular avatars (initials only, 2px ring in
The footer composes CardsKit.CardFooter with left={<RecipientStack>} slot — the standard pattern when a footer needs context plus action.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| packageNamerequired | string | — | — |
| docsrequired | SignatureDoc[] | — | — |
| recipients | { initials: string; accent?: string }[] | DEFAULT_RECIPIENTS | — |
| onSend | (receipt: { id: string; ts: number }) => void | — | — |
recipients defaults to a three-recipient demo set (JD, ML, SP) so the design-site preview renders without consumer wiring. In production, pass the real signer roster derived from the envelope.
onSend receives a { id, ts } receipt when the primary action completes — typically a Webhook.signature_request.sent callback. The CK footer handles loading state and disables the primary while in flight.
States
The card has three semantic states driven by the package lifecycle:
| State | Trigger | Status pill |
|---|---|---|
| Draft (default) | Envelope not yet sent | Draft (amber) |
| Sending | onSend mid-flight | CK footer disables primary; pill stays Draft |
| Sent | onSend completes | Card should be replaced by a tracking surface — don't keep SignatureStack mounted |
Density
In compact, document-row padding drops from 12/20 to 8/14. Recipient avatars stay 24px. The eyebrow size and letter-spacing stay constant — legibility floor at this letter-spacing matters more than vertical rhythm.
Themes
In dark, the document thumb uses --ink-4 (which adapts), and the avatar border ring (originally --paper-50) reads from the dark surface token automatically.
Tokens consumed
Document thumb reads --ink-4. List background reads --paper-50. Document row border reads --ink-6. Avatar ring reads --paper-50. Status pill reads --status-amber-bg / --status-amber-text.
Accessibility
- Keyboard interactions. Tab order:
Send for signature→Edit. Enter / Space activate. Document rows and recipient avatars are not focusable — actions live in the footer. - ARIA roles and properties. Document thumbs and bullets are
aria-hidden(decorative). Recipient avatars arearia-hidden; the recipient-count text carries the accessible identity. The status pill has no role override — accessible name is its text content. - Focus order. Footer only.
- Screen-reader expectations. Reading order: "Documents · Awaiting your review", package name, status label, then each document as "title,
{signers}signers,{pages}pages,{size}", then "{N}recipients", then footer buttons. - Reduced motion. No keyframes in the card. Footer hover lift collapses to opacity under reduced motion.
- Forced colors. Document thumb →
CanvaswithButtonBorder. Avatars →Highlight. Bullets disappear (system-color rendering removes the dot, which is fine — the surrounding text supplies the separation). - WIG rules. Decorative thumbs and bullets carry
aria-hidden(decorative-icon rule). Non-breaking space in measurements like "28 pages" via (WIG numeric rule). Touch targets on footer buttons exceed 44×44px.
Do / Don't
size strings ("1.2 MB", "412 KB") with proper non-breaking spaces between number and unit.title. The title is the document name as the signer will see it.recipients initials from the actual signer roster, in DocuSign-style envelope order.DEFAULT_RECIPIENTS placeholder in production. That set is for the design-site preview only.docs.length between 2 and 8 — that's the sweet spot for a multi-document envelope.Recipes
This card appears in:
- Equity recipe — closing-document envelopes.
- Board recipe — board-pack signing envelopes.
Code example
import { SignatureStack } from "@matter/components";
export function FinancingClosePackageInline({ envelope }: { envelope: SigningEnvelope }) {
return (
<SignatureStack
packageName={envelope.package_name}
docs={envelope.documents.map((d) => ({
title: d.title,
signers: d.signer_count,
pages: d.page_count,
size: d.size_human,
}))}
recipients={envelope.recipients.map((r) => ({
initials: r.initials,
accent: r.brand_color,
}))}
onSend={(receipt) => recordEnvelopeSent(envelope.id, receipt)}
/>
);
}Source
packages/components/src/InlineCard/SignatureStackPlanCard
Ordered checklist of plan steps with a `completed` cursor — title, x/n progress, list of items with done / active / pending states. Use when an agent proposes a multi-step plan and the user needs to track progress as steps complete.
Timeline
Namespace of primitives for event-feed surfaces — Timeline, Audit log, Inbox. Three layers: atoms (KindDot, KindChip, ActorChip, SourceChip), filter controls (Search, FilterSelect, KindToggleRow), and shared constants (KIND_CFG, ACTOR_TONES, SOURCE_LABEL).