Settling card
ProA card from the registry whose write may not have settled yet, so it never reads as done before the service says it is. Around RegistryCard, which draws the card (and its own fallbacks) unchanged.
pending: the card draws under a line saying it is waiting for the service to confirm, and the card isaria-busy.failed: the service's reason, in a degraded panel with Retry when the app can retry, then the card marked "Not applied".settled: the card alone. Set it only from the service's own confirmation; nothing here shows success before it.
One status region stays in the page for the card's life and its words change with the settlement, so a screen reader hears "Waiting…" when the card turns pending, and the failure is announced when it fails. When the person presses Retry, focus moves to the status line rather than being lost with the button. The card's definition reads the state with useCardSettlement() to lock its own actions while pending.
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
First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/settling-card
Brings in: bidi, card-registry, degraded-panel, locale, status-dot, tokens, use-announcer, utils · npm: lucide-react@^1.67.0
Usage
"use client"
import * as React from "react"
import { CardRegistryProvider, defineCard, isObject, isString } from "@/components/candor/card-registry"
import { SettlingCard, useCardSettlement } from "@/components/candor/settling-card"
import { Button } from "@/components/candor/ui/button"
import { Locked } from "@/components/candor/locked"
/** The card's own action is locked until the service confirms the write. */
function RefundCard({ amount, order }: { amount: string; order: string }) {
const settlement = useCardSettlement()
return (
<div className="flex items-center justify-between gap-3 rounded-lg border bg-card px-3 py-2.5 text-sm">
<span>
Refund {amount} on order {order}
</span>
<Locked reason={settlement === "pending" ? "Waiting for the service to confirm" : settlement === "failed" ? "Nothing to undo: it wasn’t applied" : undefined}>
<Button size="xs" variant="outline">
Undo
</Button>
</Locked>
</div>
)
}
const cards = {
refund: defineCard<{ amount: string; order: string }>({
label: "Refund",
check: (p) => (isObject(p) && isString(p.amount) && isString(p.order) ? null : "it needs an amount and an order"),
render: (p) => <RefundCard {...p} />,
}),
}
export default function Example() {
const [settlement, setSettlement] = React.useState<"pending" | "settled" | "failed">("pending")
return (
<CardRegistryProvider cards={cards}>
<div className="flex max-w-lg flex-col gap-3">
<SettlingCard
name="refund"
props={{ amount: "£40.00", order: "1042" }}
summary="Refund £40.00 on order 1042"
settlement={settlement}
service="the billing service"
failure="The card on file has expired."
onRetry={() => setSettlement("pending")}
/>
<div className="flex gap-2">
<Button size="xs" variant="ghost" onClick={() => setSettlement("settled")}>
The service confirms
</Button>
<Button size="xs" variant="ghost" onClick={() => setSettlement("failed")}>
The service refuses
</Button>
</div>
</div>
</CardRegistryProvider>
)
}<SettlingCard>
| Prop | Type | Default | Description |
|---|---|---|---|
| namerequired | string | — | Which card to draw, from the registry. |
| propsrequired | unknown | — | The card's data, checked before it draws. |
| summaryrequired | string | — | The plain-text version, shown when the card can't be. |
| settlementrequired | CardSettlement | — | Where the card's write stands: "pending" until the service confirms it, "settled" once it has, "failed" if it refused. |
| service | string | undefined | — | Who must confirm the write, named by the app ("the billing service"). Left out, the line doesn't name one. |
| failure | string | undefined | — | Why the service refused it, in its own words; shown after the sentence saying it wasn't applied. |
| onRetry | (() => void) | undefined | — | Shows Retry on a failed write. |
| className | string | undefined | — | Classes, merged with Candor's. |
Functions
useCardSettlement()Where the card being drawn stands, for a card definition's own render: "pending" while its write waits for the service, "settled" once confirmed, "failed" when refused, and undefined outside a SettlingCard. Lock the card's own actions while it is pending, with a reason, rather than letting them act on something not yet true: <Locked reason={useCardSettlement() === "pending" ? "Waiting for the service to confirm" : undefined}>.
Strings
The fixed words, in English by default. Change any of them under settlingCard in <LocaleProvider strings={{ … }}>; the table is exported as settlingCardStrings.
| Key | English |
|---|---|
| waiting | Waiting for {service} to confirm |
| waitingUnnamed | Waiting for confirmation |
| failed | {service} didn’t apply this. |
| failedUnnamed | This wasn’t applied. |
| notApplied | Not applied |
Types
- CardSettlement
- Where a card's write stands: sent and not yet confirmed, confirmed by the service, or refused by it.
"pending" | "settled" | "failed"