File Attachment Bubble
wa-ui/file-attachment-bubbleFreeComponent
WhatsApp-style file bubble with type-based color icon badge, file name/size, download progress via @base-ui/react Progress, and read receipts.
Install it
npx shadcn@latest add https://ui.meta-cloud-api.site/r/file-attachment-bubble.jsonSource
1"use client";23import * as React from "react";4import { Button } from "@base-ui/react/button";5import { Progress } from "@base-ui/react/progress";6import { cn } from "@/lib/utils";7import "@/components/ui/whatsapp/styles/whatsapp.css";8import { type MessageStatus, MessageStatusIcon } from "./message-status";910type DownloadStatus = "idle" | "downloading" | "done";1112interface FileAttachmentBubbleProps extends React.HTMLAttributes<HTMLDivElement> {13 variant?: "incoming" | "outgoing";14 fileName: string;15 fileSize?: string;16 fileType?: string;17 caption?: string;18 timestamp?: string;19 status?: MessageStatus;20 downloadStatus?: DownloadStatus;21 downloadProgress?: number;22 showTail?: boolean;23 /** Direct download URL — renders button as <a download> for native browser download */24 downloadUrl?: string;25 onDownload?: () => void;26}2728// File type → WDS color token29const FILE_TYPE_COLORS: Record<string, string> = {30 pdf: "#ea0038", // WDS red — PDF always red31 doc: "var(--wa-attachment-document)",32 docx: "var(--wa-attachment-document)",33 xls: "var(--wa-attachment-poll)",34 xlsx: "var(--wa-attachment-poll)",35 ppt: "var(--wa-attachment-camera)",36 pptx: "var(--wa-attachment-camera)",37 mp3: "var(--wa-attachment-audio)",38 wav: "var(--wa-attachment-audio)",39 m4a: "var(--wa-attachment-audio)",40 mp4: "var(--wa-attachment-photo)",41 mov: "var(--wa-attachment-photo)",42 jpg: "var(--wa-gray-400)",43 jpeg: "var(--wa-gray-400)",44 png: "var(--wa-attachment-contact)",45 gif: "var(--wa-attachment-sticker)",46 zip: "var(--wa-gray-600)",47 rar: "var(--wa-gray-600)",48 hwp: "var(--wa-gray-500)",49};5051function getFileColor(fileType?: string): string {52 return FILE_TYPE_COLORS[fileType?.toLowerCase() ?? ""] ?? "var(--wa-gray-500)";53}5455function FileTypeIcon({ fileType }: { fileType?: string }) {56 const color = getFileColor(fileType);57 const label = (fileType ?? "FILE").toUpperCase().slice(0, 4);58 return (59 <div60 className="flex h-[46px] w-[46px] shrink-0 flex-col items-center justify-center rounded-lg"61 style={{ backgroundColor: color }}62 >63 <svg viewBox="0 0 24 24" width="18" height="18" fill="white" className="opacity-90">64 <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6zm-1 7V3.5L18.5 9H13z" />65 </svg>66 <span className="mt-[1px] text-[8px] font-bold leading-none text-white opacity-90">67 {label}68 </span>69 </div>70 );71}7273function DownloadButton({74 onClick,75// … 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 | |
| Contact Bubblecontact-bubble | wa-ui | Components | Free | 1 dep · 3 files |
