Skip to content
Tier

Artifact chip

Pro

A chip in the thread for something that lives in a panel beside it: a diff, an approval, a form, a table or a plan the agent made. Pressing it calls onOpen, and the app opens that thing's tab in its panel; active marks the chip whose tab is showing. The thing's state is a word and an icon, never colour alone: "Being prepared", "Waiting for you", "Applied", "Rejected" or "Failed". Set "applied" only from the settled outcome, never on the person's press. The title is the model's text, drawn as text. Screen readers hear the kind before the title ("Diff: Raise the refund limit"): Candor's word for a kind it knows, or the app's own with kindLabel.

Markdown
Version 5.2.0· other versions

This page is for 5.2.0, the current release. An earlier release’s page is the Markdown that release published, so the docs match the version you have installed (candor-lock.json records it).

Not in the docs of 1.3.0, 1.4.0, 1.5.0, 1.5.1, 1.6.0, 1.7.0, 1.8.0, 1.8.1, 1.9.0, 1.9.1, 2.0.0, 2.1.0, 2.2.0, 2.3.0, 2.4.0, 2.5.0, 2.5.1, 2.6.0, 2.6.1, 2.6.2, 2.7.0, 2.8.0, 2.9.0, 2.10.0, 3.0.0, 4.0.0, 4.0.1, 4.0.2 and 4.1.0: the page came later, or had another name then.

Docs pages weren’t kept for 1.0.0, 1.0.1, 1.1.0, 1.1.1, 1.2.0 and 1.2.1: they are kept from 1.3.0 on, and before that only llms.txt was published.

Preview

Loading the preview

Install

With the Candor CLI

First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/artifact-chip

Brings in: badge, bidi, locale, status, tokens, utils · npm: lucide-react@^1.67.0

Usage

TSX · The example above
"use client"

import * as React from "react"
import { ArtifactChip } from "@/components/candor/artifact-chip"

// A kind Candor has no word for ("chart") is named by the app with kindLabel, so it is read "Chart: …".
const artifacts: { id: string; kind: string; kindLabel?: string; title: string; state: "pending" | "open" | "applied" | "rejected" }[] = [
  { id: "a1", kind: "diff", title: "Raise the refund limit to £500", state: "open" },
  { id: "a2", kind: "approval", title: "Refund three duplicate charges", state: "applied" },
  { id: "a3", kind: "table", title: "Orders charged twice in October", state: "pending" },
  { id: "a4", kind: "plan", title: "Move the team to the new rota", state: "rejected" },
  { id: "a5", kind: "chart", kindLabel: "Chart", title: "Refunds by week", state: "open" },
]

export default function Example() {
  const [showing, setShowing] = React.useState<string>("a1")
  return (
    <div className="flex max-w-lg flex-col items-start gap-2">
      {artifacts.map((a) => (
        <ArtifactChip key={a.id} kind={a.kind} kindLabel={a.kindLabel} title={a.title} state={a.state} active={showing === a.id} onOpen={() => setShowing(a.id)} />
      ))}
      <p className="text-xs text-muted-foreground">The panel would show {artifacts.find((a) => a.id === showing)?.title}.</p>
    </div>
  )
}

<ArtifactChip>

PropTypeDefaultDescription
kindrequiredstring—What it is: "diff", "approval", "form", "table" and "plan" have their own icon and word; any other kind a generic icon.
titlerequiredstring—Its title, often the agent's ("Raise the refund limit").
staterequiredArtifactState—Where it stands: "pending" while the agent prepares it, "open" when it waits for the person, then "applied", "rejected" or "failed". "applied" only once the outcome has settled. The chip carries it as `data-artifact-state` for your styles (not `data-state`, which a Radix app's `[data-state=open]` styles would match).
onOpenrequired() => void—Opens its tab in the app's panel.
activeboolean | undefined—Its tab is the one showing in the panel (`aria-current`).
kindLabelstring | undefined—The app's word for its kind, read before the title as "{kindLabel}:" for any kind; for one of Candor's kinds it replaces Candor's word. Left out, a kind Candor doesn't know is read with no kind word. The app's word, not the model's; drawn as text either way. The icon doesn't change.
classNamestring | undefined—Classes, merged with Candor's.

Strings

The fixed words, in English by default. Change any of them under artifactChip in <LocaleProvider strings={{ … }}>; the table is exported as artifactChipStrings.

KeyEnglish
opensOpens in the panel
pendingBeing prepared
openWaiting for you
appliedApplied
rejectedRejected
failedFailed
kind{kind}:
diffDiff
approvalApproval
formForm
tableTable
planPlan

Motion

MomentFamilyWhat it does
tinttintThe chip's border darkens when the pointer is over it, and a ring fades in when it takes keyboard focus. Its state badge changes colour with its word when the state changes.

Set with --cd-motion-artifact-chip-<moment>-* in your brand file; the families are in the design reference.