Contact Bubble
wa-ui/contact-bubbleFreeComponent
WhatsApp-style contact card — single or multiple contacts with name, phone, avatar, and action buttons.
Live preview
live · rendered by the registry
Rendered by wa-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://ui.meta-cloud-api.site/r/contact-bubble.jsonSource
1"use client";23import * as React from "react";4import { Button } from "@base-ui/react/button";5import { cn } from "@/lib/utils";6import { type MessageStatus, MessageStatusIcon } from "./message-status";7import "@/components/ui/whatsapp/styles/whatsapp.css";89export interface ContactItem {10 /** Formatted display name */11 name: string;12 phones?: string[];13 avatar?: string;14 company?: string;15}1617export interface ContactBubbleProps extends React.HTMLAttributes<HTMLDivElement> {18 variant?: "incoming" | "outgoing";19 contacts: ContactItem[];20 timestamp?: string;21 status?: MessageStatus;22 showTail?: boolean;23 onMessageContact?: (contact: ContactItem) => void;24 onAddContact?: (contact: ContactItem) => void;25}2627const AVATAR_COLORS = [28 "#dba685","#53a6fd","#25d366","#fc9775",29 "#ff72a1","#a791ff","#fb5061","#53bdeb",30 "#42c7b8","#ffd279",31];3233function getAvatarColor(name: string) {34 let hash = 0;35 for (let i = 0; i < name.length; i++) hash = name.charCodeAt(i) + ((hash << 5) - hash);36 return AVATAR_COLORS[Math.abs(hash) % AVATAR_COLORS.length];37}3839function getInitials(name: string) {40 return name.split(" ").map(w => w[0]).slice(0, 2).join("").toUpperCase();41}4243function ContactRow({ contact }: { contact: ContactItem }) {44 return (45 <div className="flex items-center gap-3 px-[9px] py-[10px]">46 <div47 className="flex h-[40px] w-[40px] shrink-0 items-center justify-center rounded-full text-[15px] font-semibold text-white"48 style={{ backgroundColor: contact.avatar ? undefined : getAvatarColor(contact.name) }}49 >50 {contact.avatar51 ? <img src={contact.avatar} alt={contact.name} className="h-full w-full rounded-full object-cover" />52 : getInitials(contact.name)53 }54 </div>55 <div className="min-w-0">56 <p className="text-[14.2px] font-medium leading-[19px] text-wa-text-primary">{contact.name}</p>57 {contact.company && (58 <p className="text-[12px] leading-[16px] text-wa-text-secondary">{contact.company}</p>59 )}60 {contact.phones?.[0] && (61 <p className="text-[12px] leading-[16px] text-wa-text-secondary">{contact.phones[0]}</p>62 )}63 </div>64 </div>65 );66}6768const ContactBubble = React.forwardRef<HTMLDivElement, ContactBubbleProps>(69 (70 {71 className,72 variant = "incoming",73 contacts,74 timestamp,75 status,76 showTail = false,77 onMessageContact,78 onAddContact,79 ...props80 },81 ref82// … truncated
What it pulls in
npm packages
Files it writes
More from wa-ui
All 29 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Action Buttonaction-button | wa-ui | Components | Free | 1 dep · 2 files | |
| Call Permissioncall-permission | wa-ui | Components | Free | 1 dep · 2 files | |
| Carousel Templatecarousel-template | wa-ui | Components | Free | 1 dep · 3 files | |
| Chat Bubblechat-bubble | wa-ui | Components | Free | no deps · 2 files | |
| Chat Headerchat-header | wa-ui | Components | Free | no deps · 2 files | |
| Chat List Itemchat-list-item | wa-ui | Components | Free | no deps · 2 files | |
| Chat Menuchat-menu | wa-ui | Components | Free | 1 dep · 2 files | |
| CTA URL Bubblecta-url-bubble | wa-ui | Components | Free | 1 dep · 3 files |
