Handoff card

Pro

A run passed from one person to another while it's in flight: who from, who to, the run and where it is, the note, and what does and doesn't transfer. The recipient accepts or declines; until then it stays with the sender, unless pendingNote says what happens instead (say, the sender has already stepped back).

Markdown

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/handoff-card

Brings in: button, locale, relative-time, status, status-dot, utils · npm: lucide-react@^1.67.0

Usage

TSX · The example above
"use client"

import * as React from "react"
import { HandoffCard } from "@/components/handoff-card"

const ago = (m: number) => new Date(Date.now() - m * 60_000).toISOString()

export default function Example() {
  const [state, setState] = React.useState<"pending" | "accepted" | "declined">("pending")
  return (
    <HandoffCard
      className="max-w-xl"
      run="Add region to customers"
      status="waiting"
      from="Sam"
      to="Priya"
      note="Backfill is paused at batch 12. Staging looks good; Production needs an approver."
      at={ago(20)}
      moves={["The thread and its history", "The pending approval request", "Notifications for this run"]}
      stays={["Sam’s drafts in other threads", "Sam’s role on Production"]}
      state={state}
      onAccept={() => setState("accepted")}
      onDecline={() => setState("declined")}
    />
  )
}

<HandoffCard>

PropTypeDefaultDescription
runrequiredstring—The run or thread being handed over.
statusrequiredRunStatus—Where the run is now.
fromrequiredstring—Who hands it over.
torequiredstring—Who it goes to: a person or a team.
notestring | undefined—The sender's note for the recipient.
atrequiredstring—When it was handed over (ISO).
movesrequiredstring[]—What transfers, as the service defines it.
staysrequiredstring[]—What doesn't.
staterequired"pending" | "accepted" | "declined"—Whether the recipient has taken it over yet.
pendingNotestring | undefined—What happens while it waits, in place of "Stays with <from> until <to> accepts." E.g. "The agent has stopped replying; it waits for Support."
onAccept(() => void) | undefined—Take it over. Without it, there's no button.
onDecline(() => void) | undefined—Turn it down. Without it, there's no button.
classNamestring | undefined—Extra classes for the outer element.

Strings

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

KeyEnglish
handoffHandoff: {run}
toto
note“{note}”
movesToMoves to {to}
doesntMoveDoesn’t move
staysWithStays with {from} until {to} accepts.
declineDecline
takeOverTake it over
accepted{to} took it over.
declined{to} declined; it’s still with {from}.