CallRecord
StableOne call at a glance for the people who run a voice agent: status, why it ended, the AI's verdict with evidence, the cost and anything a person must fix.
Also known as call log, call summary, recording
Install with npm install @tattva/ui (setup), or copy the code from the kit in Downloads.
Completed call with evidence
Call with Hartley Home assistant
Completed- Started
- 8 Oct, 14:02
- Duration
- 1:04
- Ended because
- Caller hung up after the refund
- Said it is an AI
- Recording consent captured
Outcome
AI reviewThe caller asked for a refund for a damaged kettle, and the agent refunded £24 to their card.
Taken from the call
- Order
- 40-2219
- Reason
- Cracked lid
- Refund
- £24
Cost
| Speech to text | £0.03 |
|---|---|
| Model | £0.09 |
| Voice | £0.11 |
| Platform | £0.05 |
| Phone line | £0.03 |
| Total | £0.31. Calculated by code |
Transcript
Agent00:00
Hello, you are talking to the Hartley Home assistant. I am an AI, and this call is recorded.
Caller00:06
Hi. My kettle arrived with a cracked lid. Order 40-2219.
Agent00:19
Thanks. I can see the order. Would you like a replacement or a refund?
Caller00:27
A refund, please.
Agent00:41
I have refunded £24 to your card ending 4417. It should arrive in 3 to 5 working days.
Caller00:52
Great, thank you.
<CallRecord
title="Call with Hartley Home assistant"
status="completed"
startedAt="8 Oct, 14:02"
duration="1:04"
endedReason="Caller hung up after the refund"
disclosureGiven
consentRecorded
outcome={{ verdict: "success", rationale: "The caller asked for a refund and the agent refunded £24.", evidenceLineIds: ["l5"] }}
data={{ "Order": "40-2219", "Reason": "Cracked lid", "Refund": "£24" }}
cost={cost}
currency="GBP"
transcript={transcript}
/>The AI says the goal was met and why. Show in transcript marks the line it is based on. Switch the cost to Usage to see what was used.
When to use it
Lets an operator understand one call in seconds: did it work, why did it end, what did it cost, and is there anything they must fix in the agent.
Made of: Title · Status badge · Started, duration, ended because · Needs-you notices · Checks passed · Outcome with AI label · Taken from the call · Cost with Money or Usage switch · Transcript
Use it for
- The detail view when someone opens a row in a call log.
- Reviewing calls the AI marked as failed or unsure.
- Checking that the agent said it is an AI and asked before recording.
Not for
- The live call the customer sees: use VoicePanel.
- A list of many calls: use DataTable.
- An AI summary of a document or a thread: use SummaryCard.
Do and avoid
Call
Completed- Started
- 8 Oct, 14:02
- Duration
- 1:04
- Ended because
- Caller hung up after the refund
- Said it is an AI
- Recording consent captured
Outcome
AI reviewThe caller asked for a refund and got £24 back.
Taken from the call
- Order
- 40-2219
- Reason
- Cracked lid
- Refund
- £24
Call
Completed- Started
- 8 Oct, 14:02
- Duration
- 1:04
- Ended because
- Caller hung up after the refund
- Said it is an AI
- Recording consent captured
Outcome
AI reviewThe caller asked for a refund and got £24 back.
Taken from the call
- Order
- 40-2219
- Reason
- Cracked lid
- Refund
- £24
- Caller mood
- Frustrated 72%
Do
- Show the reason with every verdict, and link it to the lines it rests on.
- Keep a not sure verdict neutral. It is honest, not a warning.
- Use amber only for a missing AI disclosure or recording consent: a person must fix the agent.
Avoid
- Do not show emotion scores about the caller, such as frustrated 72%.
- Do not use amber for a Live badge. Live uses the danger colour or neutral.
- Do not show a verdict while the call is still live.
On a phone
- The facts fold into two columns, with why it ended on its own line, and the card padding shrinks a step.
- The transcript scrolls inside its own area, about 18rem tall, so the cost and outcome stay close.
- The Money or Usage switch and Show in transcript keep a 44px tap area on touch screens.
Seen in products
- Vapi's call log shows ended reason, start, duration and cost, with a money or quantity toggle on cost.
- Bland's call log shows direction, duration, status, version and tags.
- Retell AI QA checks hallucination, interruptions, sentiment and tool use, with transcript-level evidence.
- ElevenLabs post-call analysis gives a success evaluation of success, failure or unknown with a rationale, plus extracted data.
Properties
| Prop | Type | Default | Description |
|---|---|---|---|
| statusrequired | "live" | "completed" | "failed" | "voicemail" | "transferred" | none | Where the call is. Always shown in words. |
| endedReasonrequired | string | none | Why it ended, in plain words. Hidden while live. |
| durationrequired | string | none | How long it ran, or has run so far. |
| startedAtrequired | string | none | When it started, already formatted. |
| title | string | "Call" | Heading, such as the caller or the agent. |
| outcome | { verdict: "success" | "failure" | "unknown"; rationale: string; evidenceLineIds?: string[] } | none | The AI's verdict and its reason. Evidence ids link to transcript lines. |
| cost | { total: number; items: { label: string; amount: number; quantity?: string }[] } | none | What the call cost. The Usage switch shows when any item has a quantity. |
| currency | string | "GBP" | ISO 4217 code for every amount. |
| locale | string | "en-GB" | Number format for amounts. |
| disclosureGiven | boolean | none | false shows an amber notice. Leave out if you do not track it. |
| consentRecorded | boolean | none | false shows an amber notice. Leave out if you do not track it. |
| data | Record<string, string> | none | Fields the agent took from the call. |
| transcript | { id: string; speaker: "agent" | "caller"; text: string; time?: string }[] | none | A simple transcript. Evidence lines are marked when Show in transcript is pressed. |
| speakerLabels | { agent: string; caller: string } | Agent, Caller | Names for the two speakers. |
| onShowEvidence | (lineIds: string[]) => void | none | Called by Show in transcript, for example to seek your audio player. |
| actions | ReactNode | none | Extra header actions, such as Open recording. |
| className | string | none | Extra classes for the card. |
"Show code under the preview gives the code for the example on the stage."
In Figma
In Figma, one CallRecord switches all of this from its properties panel, across 20 variants. Each property sets the React prop beside it, so design and code use the same names.
| Figma property | React | Values |
|---|---|---|
| Status | status | Live, Completed, Failed, Voicemail, Transferred |
| Disclosure given | disclosureGiven | On or off |
| Consent recorded | consentRecorded | On or off |
| Title | title | Any text |
| StartedAt | startedAt | Any text |
| Duration | duration | Any text |
| EndedReason | endedReason | Any text |
Tokens
Change one of these and every part that uses it follows.
--surface--surface-sunken--border--warning-soft--warning-fg--danger--success-fg--lime--radius-card--radius-control--dur-base
Built in
- The status, the verdict and each check are written in words with an icon, never colour alone.
- Show in transcript marks the evidence lines in words and moves focus to the first one.
- Money and Usage is a radio group: arrow keys move between them.
- Cost is a real table with a hidden caption that says what it holds.
- The live dot stops pulsing under reduced motion, and the word Live stays.
What you need to do
- Write endedReason in plain words, such as Caller hung up, not a code like customer-ended-call.
- Pass disclosureGiven and consentRecorded from what really happened in the call, so the amber notice is true.
- If you link an audio player, pass onShowEvidence and move the player to the first evidence line.
Built toward WCAG 2.2 AA and checked automatically; no independent audit yet. Read the accessibility guide