Skip to main content
The ChatHeader component displays contact information at the top of the chat panel, including the contact’s avatar, online status, and action buttons for calls and options.

Location

components/chat/chat-header.tsx

Props

contact
Contact
required
The contact object containing name, avatar, and last seen information
isOnline
boolean
required
Whether the contact is currently online
onBack
() => void
Optional callback for the back button (displayed on mobile)

Features

Avatar with online indicator

The header displays a circular avatar with a small status indicator showing whether the contact is online (accent color) or offline (muted color).
components/chat/chat-header.tsx
<div className="relative">
  <Avatar className="h-11 w-11 border border-border/60">
    <AvatarImage src={contact.avatarUrl} alt={contact.name} />
    <AvatarFallback>{initials(contact.name)}</AvatarFallback>
  </Avatar>
  <span
    className={cn(
      "absolute -right-0.5 -bottom-0.5 h-2.5 w-2.5 rounded-full border-2 border-background",
      isOnline ? "bg-accent" : "bg-muted"
    )}
  />
</div>

Last seen status

When the contact is offline, the header displays a relative timestamp showing when they were last seen:
components/chat/chat-header.tsx
<p className="text-xs text-muted-foreground">
  {isOnline ? "Online" : `last seen ${formatDistanceToNow(new Date(contact.lastSeenAt), { addSuffix: true })}`}
</p>

Action buttons

The header provides three action buttons:
  • Voice call (Phone icon)
  • Video call (VideoCamera icon)
  • Options menu (DotsThreeVertical icon)
All buttons include screen reader labels for accessibility.

Mobile back button

When onBack is provided, a back button is displayed on the left side of the header, allowing users to return to the chat list on mobile devices.

Initials helper

The component includes an initials helper function that generates initials from a contact’s name:
components/chat/chat-header.tsx
function initials(value: string) {
  return value
    .split(" ")
    .filter(Boolean)
    .slice(0, 2)
    .map((part) => part[0]?.toUpperCase())
    .join("")
}
This takes the first letter of the first two words and converts them to uppercase.

Usage

import { ChatHeader } from "@/components/chat/chat-header"

function ChatPanel() {
  const contact = useChatStore((state) => state.contacts[contactId])
  const isMobile = useIsMobile()
  
  return (
    <div>
      <ChatHeader
        contact={contact}
        isOnline={contact.isOnline}
        onBack={isMobile ? handleBack : undefined}
      />
    </div>
  )
}
  • ChatPanel - Parent component that renders the header
  • ChatApp - Main container that manages contact state

Build docs developers (and LLMs) love