@mysios-labs-inc/whatsapp-mockup
v2.0.1
Published
Reusable iPhone + WhatsApp chat mockup components for React (Tailwind v4)
Readme
@mysios-labs-inc/whatsapp-mockup
Reusable iPhone device frame + WhatsApp chat mockup components for React (Tailwind v4). Drop a scripted WhatsApp conversation into a realistic iPhone frame for landing pages, demos, and pitch decks — no screenshots to keep up to date. Extracted from fudi-web.

Screenshots
Captured from the example app's component showcase — every screenshot below reflects real rendered output, not mockups of mockups.
| | |
| --- | --- |
| Chat list (home) screen | Calls tab |
|
|
|
| Media bubbles (photo/video/grid/document) | Rich bubbles (link/contact/poll previews) |
|
|
|
| Settings & Contact Info | WhatsAppButton variants |
|
|
|
A note on language
Chrome/UI labels — headers, tab bar text, button labels — are authored in English to match the components' exported defaults. Demo/example content — contact names, message text, and aria-labels on internal interactive elements like back/attach buttons — uses Spanish, reflecting the original Fudis restaurant-bot use case this library was extracted from. Contributors should preserve this split rather than "fixing" one language to match the other.
Table of contents
Install
npm install @mysios-labs-inc/whatsapp-mockupPeer dependencies: react and react-dom (>=18).
Setup (Tailwind v4)
Components use Tailwind utility classes, including a coral-* color scale. Import the bundled theme before your own styles:
@import "tailwindcss";
@import "@mysios-labs-inc/whatsapp-mockup/theme.css";If your app already defines coral-300..coral-600, import your theme after this one to override.
Quick start
import { Iphone17Pro, WhatsAppMockup } from '@mysios-labs-inc/whatsapp-mockup'
function Demo() {
return (
<Iphone17Pro width={370} height={740}>
<WhatsAppMockup contactName="Fudis" contactSubtitle="en línea" />
</Iphone17Pro>
)
}For a full working app with every component, see examples/basic.
Components
Iphone17Pro
Device frame rendered as inline SVG. Pass src for a static image, or children for arbitrary React/HTML content (rendered inside the screen via <foreignObject>). children takes precedence over src if both are given. Any extra prop is forwarded to the underlying <svg> element (e.g. className, style).
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| width | number | 200 | Rendered SVG width. |
| height | number | 400 | Rendered SVG height. |
| src | string | — | Image URL rendered inside the screen. Ignored if children is set. |
| children | ReactNode | — | Arbitrary content rendered inside the screen. |
<Iphone17Pro width={400} height={800} src="/screenshot.png" />WhatsAppMockup
Scripted restaurant-discovery-and-booking conversation demo. Render inside <Iphone17Pro> to get the full device frame.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| contactName | string | 'Fudis' | Name shown in the chat header. |
| contactSubtitle | string | 'en línea' | Subtitle shown under the contact name. |
| restaurants | RestaurantCard[] | 3 sample restaurants | Cards rendered in the restaurant-recommendation bubble. |
RestaurantCard shape:
type RestaurantCard = {
name: string
rating: number
location: string
priceRange: string
highlights: string[]
}WhatsAppChatMockup / WhatsAppChatScrollable
Static reference chat demo with no props — useful as a lightweight placeholder or design reference. WhatsAppChatMockup renders a fixed, non-scrolling message list; WhatsAppChatScrollable renders the same content in a scrollable container, auto-scrolled to the latest message on mount.
<Iphone17Pro width={400} height={800}>
<WhatsAppChatScrollable />
</Iphone17Pro>WhatsAppButton
Inline "message on WhatsApp" button — same wa.me link logic as WhatsAppStickyCTA, but rendered in normal document flow instead of fixed to the viewport. Use this for hero CTAs, cards, or anywhere a regular button belongs; use WhatsAppStickyCTA for a floating button.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| contactName | string | — | Required. Used in the aria-label and default message templates. |
| phone | string \| null | — | Required. Direct phone number for this contact, if known. Any format — non-digits are stripped. Pass null to fall back to fallbackPhoneNumber. |
| fallbackPhoneNumber | string | — | Required. Used when phone is null/empty. |
| ctaLabel | string | 'Reservar' | Button label. Ignored for variant="icon-only". |
| variant | 'solid' \| 'outline' \| 'icon-only' | 'solid' | Visual style. |
| size | 'sm' \| 'md' \| 'lg' | 'md' | Button size. |
| buildMessageWithPhone | (contactName: string) => string | Spanish order message | Message template used when phone is provided. |
| buildFallbackMessage | (contactName: string) => string | Spanish order message + "Vi su menú en Fudis." | Message template used when falling back to fallbackPhoneNumber. |
| onClick | (info: { hasDirectPhone: boolean }) => void | — | Fired on click, before the WhatsApp link opens. Wire up your own analytics here. |
| className | string | — | Extra classes merged onto the button. |
<WhatsAppButton
contactName="Punto Azul"
phone={restaurant.phone}
fallbackPhoneNumber="51999999999"
variant="outline"
size="sm"
/>WhatsAppStickyCTA
Floating "message on WhatsApp" CTA button, fixed to the bottom of the viewport and fading in after the user scrolls. Client-only component ('use client').
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| contactName | string | — | Required. Used in the aria-label and default message templates. |
| phone | string \| null | — | Required. Direct phone number for this contact, if known. Any format — non-digits are stripped. Pass null to fall back to fallbackPhoneNumber. |
| fallbackPhoneNumber | string | — | Required. Used when phone is null/empty. |
| ctaLabel | string | 'Reservar' | Button label. |
| buildMessageWithPhone | (contactName: string) => string | Spanish order message | Message template used when phone is provided. |
| buildFallbackMessage | (contactName: string) => string | Spanish order message + "Vi su menú en Fudis." | Message template used when falling back to fallbackPhoneNumber. |
| showAfterScrollPx | number | 200 | Scroll offset (px) after which the CTA becomes visible. |
| onClick | (info: { hasDirectPhone: boolean }) => void | — | Fired on click, before the WhatsApp link opens. Wire up your own analytics here. |
| className | string | — | Extra classes merged onto the wrapper. |
<WhatsAppStickyCTA
contactName="Punto Azul"
phone={restaurant.phone}
fallbackPhoneNumber="51999999999"
onClick={({ hasDirectPhone }) => track('whatsapp_clicked', { hasDirectPhone })}
/>WhatsAppIcon
Standalone WhatsApp brand icon SVG (24x24 viewBox, defaults to h-5 w-5).
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| className | string | 'h-5 w-5' | Fully replaces the default size when provided — include your own sizing classes. |
Chat primitives
Lower-level building blocks exported from parts.tsx, useful for composing custom conversations instead of using WhatsAppMockup as-is:
BubbleMe/BubbleFriend— chat bubbles for each side of the conversation.DateChip— centered date separator (e.g. "Hoy").LocationBubble— WhatsApp-style shared-location bubble.RestaurantCardsBubble— carousel ofRestaurantCarditems inside a bubble.StatusBar— iOS status bar (time/signal/battery).ChatHeader— WhatsApp conversation header (avatar, name, subtitle).InputBar— the message composer bar at the bottom of the screen.ChatMessages— the fixed message list used byWhatsAppChatMockup/WhatsAppChatScrollable.DESIGN_WIDTH/DESIGN_HEIGHT— the design canvas size (393 x 852) all mockups are laid out against.
Example app
A runnable Vite + React + Tailwind v4 app lives in examples/basic — a component showcase covering every export: the three chat mockups, WhatsAppIcon, WhatsAppButton (all variants/sizes), and a live WhatsAppStickyCTA. It consumes this package via a local file:../.. dependency, so no publish is required to try it:
npm run build # build the package itself first (dist/ output)
cd examples/basic
npm install
npm run dev # or: npm run build && npm run previewPublishing
Published to the public npm registry. Push a v* tag to trigger the GitHub Actions publish workflow (requires an NPM_TOKEN repo secret with publish rights on the @mysios-labs-inc npm org):
npm version patch
git push --follow-tagsLicense
MIT © Mysios Labs — see LICENSE.
