docs GitHub

Design systemDraft

Artifact card

An agent made something durable (a document, a report, a page, a dashboard, a diagram, a deck, a small app) and it lives on the box, versioned, private by default. This card is how it shows in chat; the panel it opens is the full viewer. Agreed with the artifacts team (AR1-AR8, CHAT.md, 30 Sep) and cohesion-2; the panel/diff/list-row reuse below was agreed there first and is restated here as part of the one chat-components contract. New 30 Sep.

SurfaceImplementing fileStatus
Decknonenot built
Appnonenot built
Lumennonenot built

Anatomy: chat card

A compact row-card, height 56, padding 10 12, radius --radius-card (12), fill --panel, 1 px --rule:

  1. Icon, 32: a kind glyph (doc, report, page, dashboard, diagram, deck) on --hover, radius 8
    • never a live-rendered thumbnail in chat (that's the panel's job; the row stays cheap).
  2. Title and meta, a column: title (base 600, --text, one line, ellipsis) - "kind · vN · made by <agent> · <relative time>" (meta, --label).
  3. Actions, right: Open (outline, opens the panel) and Share (ghost, opens the share sheet, AR3/AR8) side by side.

Anatomy: panel (artifacts-options.html section 3, Option A, confirmed)

panel:<name> (ADR 0033's slot grammar), 340 wide by default; a page or deck kind may widen to 50% of the window with one control (docs/design/system/layout.md's named exception, committed 9c8479f5) - every other kind stays at 340.

  1. Version bar, 44 tall, padding 0 16: the title, then right-aligned a version toggle (pill buttons per version, v1 v2 ..., the current one filled --text/--bg, others outline), Changes (ghost, toggles the diff view below) and Share (ghost).
  2. Content, by kind:
    • doc / report: Vyre's own Markdown renderer, in the design system (type scale, no custom CSS from the artifact itself).
    • diagram: Mermaid or inline SVG, same renderer as everywhere else diagrams appear.
    • dashboard: a chart spec drawn with the dataviz palette (the project's existing chart conventions, not a new one).
    • page / app: HTML inside a sandboxed iframe, sandbox="allow-scripts" with no allow-same-origin, matching ADR 0033's /m/<module>/ rule exactly (confirmed 06:38, CHAT.md) - the raw content URL also carries its own restrictive CSP so even a top-level open runs at an opaque origin.
  3. Changes view (when toggled): diff.md's unified diff between the selected version and the one before it - added on the bone wash, removed struck... no, per diff.md's own rule, removed on the neutral wash with no strikethrough. Exactly diff.md, not a second diff renderer.

Anatomy: Artifacts tab (per project)

A list-row.md list: title, kind/creator/date meta, a visibility chip (chip.md's Tag: "Public · 29 days" in a neutral, "Only you" otherwise - never an accent, matching every other neutral-chip rule in this system) right-aligned. Sits beside Threads/Brief/Files/Memory as its own tab (artifacts-options.html section 3).

Variants

  • Chat card, phone: same anatomy, full width, Open leads to the full-screen sheet instead of a panel.
  • Panel, phone: full-screen sheet (ADR 0033's panel:<name> phone rule), version bar becomes a bottom bar (Versions / Changes / Share, per the confirmed mockup) rather than top-of-panel, since the phone's safe-area top is precious and the title needs the space instead.
  • Lumen (compact): not drawn at all in the panel/rows/footer shell - "Open in the Deck" only, same rule as every other rich-content card here (pr-review.md, email-thread.md, calendar.md's compose forms).

Sizes

Chat card 56 tall. Panel 340 default / 50% widened (page, deck only). Version pills 28 tall, 8 horizontal padding.

States

  • Open as above.
  • Loading (panel content still rendering): a skeleton block matching the content kind's rough shape (text lines for doc/report, a blank canvas for diagram/dashboard).
  • Diff loading: the version bar's Changes button shows a spinner in place, content stays on the current version until the diff is ready.
  • Shared: the chat card's meta line gains the visibility chip too, so a shared artifact reads the same in chat as it does in the Artifacts tab.
  • Error (page/app failed to render in the sandbox): "This page didn't load" with the failed mark, --text, no further detail leaked from the sandboxed origin (nothing to leak by design).

Keyboard and touch

Version pills are a radiogroup; ← → move between them when focused. Share opens with S when the panel has focus (no conflict - draft-card.md's "D" is Discard, this panel has no Discard).

Motion

Panel open/close at --motion-panel (220), matching every other panel:<name>. Version switch crossfades the content, no slide (a slide would misread as "this is a different artifact," not "this is the same artifact, an earlier moment").

Copy

"kind · vN · made by <agent> · <relative time>", "Open", "Share", "Changes", "Public · <n> days", "Only you". Never "AI-generated" as a label - the "made by <agent>" meta already says who/what made it, in the same plain register avatar.md's teammate-tag rule uses elsewhere.

Emission (agreed with artifacts, sessions, native-core - AR1/AR2)

thread.artifact {thread, artifact, version, kind, title} (AR2, agreed in CHAT.md) drives the chat card. The panel reads the artifact's own versions via artifacts.get/artifacts.diff (AR1) directly, not through a chat event - opening the panel is a navigation, not a new message.

What the person's actions do

Open navigates to the panel/sheet, a read action, no Gate involvement. Share opens the share sheet (AR3/AR8's artifacts.share, outward: post - held with Touch ID only when an agent decided to share alone, matching every other outward classification in this contract; runs at once when the person tapped or asked, per "asking is approving"). Restoring an old version (artifacts.restore, if the panel exposes it - flagged to artifacts as a possible addition, not yet in AR1's tool list) would be a write to the person's own project, not outward, so no Touch ID.

What agents can do for the person

An agent creates and updates artifacts on its own (artifacts_create/artifacts_update, AR4's harness-brief line) without asking each time - that's the whole point, replacing scattered one-off publishing with one governed store. It may never share one publicly on its own without the person's Touch ID (AR1's artifacts.share classification), and it may never delete one without an explicit ask (AR1 lists delete as a plain tool, not outward, but a destructive action the person didn't ask for still needs "asking is approving" to actually match a said intent - flagged to vault/assistant to confirm delete's Gate treatment, since AR1's own table doesn't mark it held).

Accessibility

  • The chat card is a button-like row (role="link" semantics: Open is the default action).
  • The panel is a dialog region (matching every other panel:<name>'s existing pattern) labelled by the artifact's title.
  • The sandboxed iframe carries title describing the artifact, so assistive tech announces what it's entering even though its content is opaque to the host page.

Gaps

Everything - new component, no surface has built it. Depends on AR1's tools and AR2's event landing first (artifacts' own build order).