Customize

Custom node cards

Replace the default card per kind, or globally. The render callback receives the same context the default uses.

tsx
import { WireNodeCardView, type WireNodeRenderContext } from "@aigentive/wire-react";

function BannerCard(ctx: WireNodeRenderContext) {
  return (
    <div className="grid gap-1">
      <span className="rounded-t-lg bg-amber-100 px-2 py-1 text-[10px] font-bold uppercase">
        beta
      </span>
      <WireNodeCardView {...ctx} />
    </div>
  );
}
Ticket webhook
event: ticket.created
trigger · single option
Plan answer
gpt-5.4-mini
model: gpt-5.4-mini / temperature: 0.3
ai · selected · model + temperature
Update ticket
zendesk.update_ticket
ref: zendesk.update_ticket
tool · ref + requiresApproval
Plan answer
gpt-5.4-mini
model: gpt-5.4-mini / temperature: 0.3
Neutral · the default
Plan answer
gpt-5.4-mini
model: gpt-5.4-mini / temperature: 0.3
Success
Plan answer
gpt-5.4-mini
model: gpt-5.4-mini / temperature: 0.3
Warning
Plan answer
gpt-5.4-mini
model: gpt-5.4-mini / temperature: 0.3
Error
Plan answer
gpt-5.4-mini
model: gpt-5.4-mini / temperature: 0.3
Info
Plan answer
gpt-5.4-mini
model: gpt-5.4-mini / temperature: 0.3
AI
triggerTicket webhookminimal
Minimal — dashed border, centered, no shadow, no kind chip
$ wire-aiPlan answerid: planterminal
Terminal — slate-950 surface, monospace, emerald accents
tool
Update ticketrow · custom renderer
Row — kind dot, side-by-side meta, no shadow
tsx
function MinimalCard(ctx: WireNodeRenderContext) {
  return (
    <div className="grid h-[140px] content-center gap-1 rounded-lg border border-dashed
                    border-slate-300 bg-white px-4 py-3 text-center
                    dark:border-slate-700 dark:bg-slate-900">
      <span className="text-[10px] font-bold uppercase tracking-wider
                       text-slate-500">{ctx.kind}</span>
      <strong className="text-[14px] text-slate-950 dark:text-slate-50">{ctx.node.title}</strong>
      <span className="font-mono text-[11px] text-slate-400">minimal</span>
    </div>
  );
}
tsx
function TerminalCard(ctx: WireNodeRenderContext) {
  return (
    <div
      aria-selected={ctx.selected}
      className={`grid h-[140px] content-start gap-1 rounded-lg border bg-slate-950
                  px-3.5 py-3 font-mono text-[12px] ${
        ctx.selected ? "border-emerald-400 ring-2 ring-emerald-400/20" : "border-slate-700"
      }`}
    >
      <span className="text-emerald-400">$ wire-{ctx.kind}</span>
      <strong className="text-emerald-100">{ctx.node.title}</strong>
      <span className="text-slate-500">id: {ctx.node.id}</span>
    </div>
  );
}
tsx
function RowCard(ctx: WireNodeRenderContext) {
  return (
    <div className="grid h-[140px] content-center gap-2 rounded-lg border border-slate-200
                    bg-white px-4 py-3 dark:border-slate-800 dark:bg-slate-900">
      <div className="flex items-center gap-2">
        <span className={`h-2 w-2 rounded-full ${kindDotClass(ctx.kind)}`} />
        <span className="font-mono text-[11px] uppercase tracking-wider
                         text-slate-500">{ctx.kind}</span>
      </div>
      <strong className="text-[15px] text-slate-950">{ctx.node.title}</strong>
    </div>
  );
}
tsx
<WireWorkspace
  diagram={diagram}
  onChange={setDiagram}
  optionCatalog={catalog}
  renderNodeCard={(ctx) =>
    ctx.kind === "ai" ? <TerminalCard {...ctx} /> : <RowCard {...ctx} />
  }
/>;
tsx
function GroupFrame(ctx: WireNodeRenderContext) {
  return (
    <div
      aria-selected={ctx.selected}
      className={`grid h-full content-start gap-1 rounded-lg border-2 border-dashed
                  bg-slate-50/60 p-3 dark:bg-slate-900/40 ${
        ctx.selected
          ? "border-blue-400 ring-2 ring-blue-400/20"
          : "border-slate-300 dark:border-slate-700"
      }`}
      style={{ width: ctx.width, height: ctx.height }}
    >
      <span className="text-[10px] font-bold uppercase tracking-wider
                       text-slate-500 dark:text-slate-400">
        Stage · {ctx.node.title}
      </span>
    </div>
  );
}

<WireWorkspace
  diagram={diagram}
  onChange={setDiagram}
  optionCatalog={catalog}
  renderNodeCard={Card}
  renderGroup={GroupFrame}
/>;
NextListen to events