CallCard
Voice-call overlay for ringing, connecting, connected, and ended states.
Quick Preview
Composition
CallCard is the in-product surface shown while a voice call is ringing,
connecting, connected, or just ended. It owns shape, elevation, and per-size
layout, and exposes size/state through context so its parts size and colour
themselves. Wiring — mute, hang up, accept — is yours; pass handlers to the
action parts.
CallCardOverlay (only for size="full")
└── CallCard (size, state)
├── CallCardAvatar
├── CallCardIdentity › CallCardName · CallCardStatus
└── CallCardActions
├── CallCardWindowControl
├── CallCardMuteButton | CallCardIgnoreButton
└── CallCardEndCallButton | CallCardAcceptButtonWrap the full window in CallCardOverlay for its dimmed, blurred scrim; the
minimized bar docks inline and needs none. state is the sole driver of the
status-dot colour and of whether End Call retires to a neutral tone.
Usage
<CallCardOverlay>
<CallCard size="full" state="in-call">
<CallCardAvatar src={contact.photo} alt={contact.name} />
<CallCardIdentity>
<CallCardName>{contact.name}</CallCardName>
<CallCardStatus>In call · 04:32</CallCardStatus>
</CallCardIdentity>
<CallCardActions>
<CallCardWindowControl onClick={dock} />
<CallCardMuteButton muted={isMuted} onClick={toggleMute} />
<CallCardEndCallButton onClick={hangUp} />
</CallCardActions>
</CallCard>
</CallCardOverlay>Examples
In call
The full window for an active outbound call. The status dot turns success-green
once connected; CallCardMuteButton is a reversible toggle that stays neutral,
so it never competes with the destructive End Call.
Incoming
Set state="incoming" to swap the action row to Ignore + Accept. The card takes
role="alert" and aria-live="assertive" in this state so an arriving call is
announced.
Minimize and expand
size="minimized" docks the call as a horizontal bar. Drive size from state
and toggle it from CallCardWindowControl to move between the full window and the
docked bar. One structure serves both sizes: the window control self-positions
(pinned top-right when full, leading the bar when minimized) and swaps its glyph
and label on size, so a single control transforms the card.
Props
| Prop/API | Type | Default | Description |
|---|---|---|---|
size on CallCard | "full" | "minimized" | "full" | Full window vs docked bar. |
state on CallCard | "ringing" | "calling" | "in-call" | "call-ended" | "incoming" | - | Required. Drives the status-dot colour and End Call tone. |
src / alt / fallback on CallCardAvatar | string / string / ReactNode | - | Contact photo; the glyph is a fallback. |
muted on CallCardMuteButton | boolean | false | Swaps the glyph and the accessible label. |
tone on CallCardAction | "tertiary" | "danger" | "primary" | "tertiary" | Surface emphasis for a custom action. |
className | string | - | Local layout or spacing overrides. |
| native/root props | React component props | - | Passed through to the underlying element. |
Accessibility
statecarries the call's status through the dot's colour and the copy inCallCardStatus— never encode it in colour alone.- The
incomingstate announces itself viarole="alert"/aria-live="assertive"; other states use a politestatuslive region. - Every action is a real button with a sensible default
aria-label;CallCardMuteButtonalso togglesaria-pressed. - Never leave
CallCardActionsempty — an overlay with no controls traps the user in a live call. - Preserve the documented composition so the card's
size/statecontext reaches the avatar, identity, and action parts.