Carousel Template
wa-ui/carousel-templateFreeComponent
WhatsApp Business carousel template with horizontal scrollable cards using @base-ui/react ScrollArea.
Install it
npx shadcn@latest add https://ui.meta-cloud-api.site/r/carousel-template.jsonSource
1"use client";23import * as React from "react";4import { Button } from "@base-ui/react/button";5import { ScrollArea } from "@base-ui/react/scroll-area";6import { cn } from "@/lib/utils";7import "@/components/ui/whatsapp/styles/whatsapp.css";8import { TemplateButton } from "./template-bubble";910export interface CarouselCard {11 imageUrl?: string;12 body: string;13 buttons?: TemplateButton[];14}1516export interface CarouselTemplateProps extends React.HTMLAttributes<HTMLDivElement> {17 body?: string;18 cards: CarouselCard[];19 timestamp?: string;20 /** Override the default `<a>` element for URL/phone buttons (e.g. Next.js Link) */21 renderAction?: (props: { href: string; children: React.ReactNode; className: string; target?: string; rel?: string }) => React.ReactElement;22}2324function CardButton({ button, renderAction }: { button: TemplateButton; renderAction?: CarouselTemplateProps["renderAction"] }) {25 const base = "flex w-full items-center justify-center gap-1.5 py-[9px] text-[13px] font-medium text-wa-emerald-500";26 const label = button.type === "call_permission" ? `Call ${button.bizName}` : button.type === "copy_code" ? (button.label ?? "Copy offer code") : "label" in button ? button.label : "";2728 const buttonContent = (29 <>30 {button.type === "url" && (31 <img src="/wa-icon-url.png" width={14} height={14} alt="" style={{ filter: "var(--wa-btn-icon-filter)" }} />32 )}33 {button.type === "flow" && (34 <img src="/wa-icon-flow.png" width={14} height={14} alt="" style={{ filter: "var(--wa-btn-icon-filter)" }} />35 )}36 {label}37 </>38 );3940 const href = button.type === "url" && button.url ? button.url41 : button.type === "phone_number" && button.phone_number ? `tel:${button.phone_number}`42 : undefined;4344 if (renderAction && href) {45 return renderAction({46 href,47 children: buttonContent,48 className: base,49 ...(button.type === "url" ? { target: "_blank", rel: "noopener noreferrer" } : {}),50 });51 }5253 const renderEl = button.type === "url" && button.url54 ? <a href={button.url} target="_blank" rel="noopener noreferrer" />55 : button.type === "phone_number" && button.phone_number56 ? <a href={`tel:${button.phone_number}`} />57 : undefined;5859 return (60 <Button render={renderEl} nativeButton={renderEl == null} className={base}>61 {buttonContent}62 </Button>63 );64}6566const CarouselTemplate = React.forwardRef<HTMLDivElement, CarouselTemplateProps>(67// … 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 | |
| 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 | |
| CTA URL Bubblecta-url-bubble | wa-ui | Components | Free | 1 dep · 3 files |
