Estado inicial del mockup
This commit is contained in:
@@ -0,0 +1,425 @@
|
||||
# WhatsApp Business Platform (Cloud API) — Tipos de mensajes, payloads y límites
|
||||
|
||||
> Investigación sobre la documentación oficial de Meta (developers.facebook.com), 2026-09-26.
|
||||
> Nota: Meta migró la doc de `/docs/whatsapp/cloud-api/...` a `/documentation/business-messaging/whatsapp/...`.
|
||||
> Los tipos text/media/location/contacts siguen accesibles en las URLs legacy; interactive/templates ya
|
||||
> solo viven en la nueva ruta. Los datos citados provienen de las páginas listadas en "Fuentes".
|
||||
|
||||
## 1. Convención común de todos los mensajes
|
||||
|
||||
Endpoint: `POST https://graph.facebook.com/<API_VERSION>/<PHONE_NUMBER_ID>/messages`
|
||||
con header `Authorization: Bearer <TOKEN>` y `Content-Type: application/json`
|
||||
(Fuente: Message API reference — §Fuentes [17]).
|
||||
|
||||
Sobre (envelope) común a todo mensaje (BaseMessageProperties, [17]):
|
||||
|
||||
```json
|
||||
{
|
||||
"messaging_product": "whatsapp", // requerido, siempre "whatsapp"
|
||||
"recipient_type": "individual", // "individual" (o "group" para grupos)
|
||||
"to": "<número del usuario>", // requerido
|
||||
"type": "<text|image|video|audio|document|sticker|location|contacts|interactive|template|reaction>",
|
||||
"context": { "message_id": "wamid..." } // opcional: responde a un mensaje previo
|
||||
}
|
||||
```
|
||||
|
||||
Respuesta de éxito: `contacts[].input`, `contacts[].wa_id` y `messages[].id` (`wamid.HBgL...`);
|
||||
el `message_status` inicial puede ser `accepted` (también existen `held_for_quality_assessment` y `paused`) [17].
|
||||
|
||||
## 2. Text
|
||||
|
||||
Payload [1]:
|
||||
|
||||
```json
|
||||
{
|
||||
"messaging_product": "whatsapp",
|
||||
"recipient_type": "individual",
|
||||
"to": "16505551234",
|
||||
"type": "text",
|
||||
"text": {
|
||||
"preview_url": false,
|
||||
"body": "Hola mundo"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Campo | Descripción | Límite |
|
||||
|---|---|---|
|
||||
| `text.body` | Texto del mensaje (requerido). El cliente hipervincula URLs automáticamente | **4096 caracteres** |
|
||||
| `text.preview_url` | `true` = el cliente intenta renderizar preview del enlace | opcional |
|
||||
|
||||
Vista en el teléfono: burbuja de solo texto; con `preview_url: true` **solo el primer URL** del body
|
||||
recibe preview (requiere `http://` o `https://`); si no se puede obtener, queda como enlace clicable [1].
|
||||
El preview usa el Open Graph de la página: `og:title` (negrita, máx 2 líneas), `og:description`
|
||||
(~80 caracteres), `og:url` y `og:image` (thumbnail <600 KB, ≥300 px de ancho) renderizados encima
|
||||
del texto de la burbuja [22].
|
||||
|
||||
**Formato de texto** (`*negrita*`, `_cursiva_`, `~tachado~`, ` ```mono``` `):
|
||||
la página oficial actual de text-messages **ya no documenta la sintaxis** de formateo (verificado [1]);
|
||||
lo único oficial vigente leído es que el body/footer interactivos "soportan emojis y markdown" [17]
|
||||
y que el header de plantillas tipo TEXT **prohíbe** caracteres markdown [20]. La sintaxis con
|
||||
`*asteriscos*`, `_guiones bajos_`, `~tildes~` y triple acento grave es la estándar del cliente
|
||||
WhatsApp, pero su referencia oficial en el site de developers está retirada: dato NO verificable
|
||||
contra fuentes oficiales en esta investigación.
|
||||
|
||||
## 3. Media (image, video, audio, document, sticker)
|
||||
|
||||
Patrón común: el objeto de media admite `id` (asset subido vía Media API — recomendado por
|
||||
performance) **o** `link` (URL pública — "no recomendado"); se provee solo uno [2]–[6].
|
||||
|
||||
**Image** [2] — `type: "image"`, objeto `image`: `{ id | link, caption }`.
|
||||
Caption máx **1024 caracteres**. Formatos: JPEG (`image/jpeg`) y PNG (`image/png`),
|
||||
8-bit RGB/RGBA, máx **5 MB**.
|
||||
|
||||
**Video** [3] — `type: "video"`, objeto `video`: `{ id | link, caption }`.
|
||||
Caption máx **1024**. Solo códecs **H.264 (video) + AAC (audio)**, un solo stream de audio o ninguno;
|
||||
MP4 (`video/mp4`) y 3GP (`video/3gpp`), máx **16 MB**. H.264 "High" con B-frames no funciona en
|
||||
Android; usar Main/Baseline y `moov` antes de `mdat` (ffmpeg `-movflags faststart`).
|
||||
|
||||
**Audio** [4] — `type: "audio"`, objeto `audio`: `{ id | link, voice }`.
|
||||
`voice: true` = mensaje de voz (requiere OGG con codec OPUS, mono; el OGG base no es soportado).
|
||||
Formatos: AAC, AMR, MP3 (`audio/mpeg`), M4A (`audio/mp4`), OGG (`audio/ogg`); máx **16 MB**.
|
||||
Vista: archivos ≤512 KB muestran icono de play como mensaje de voz; los mayores muestran icono de descarga [4].
|
||||
|
||||
**Document** [5] — `type: "document"`, objeto `document`: `{ id | link, caption, filename }`.
|
||||
Caption máx **1024**; `filename` (con extensión) define el icono del tipo de archivo en el cliente.
|
||||
Tipos soportados (máx **100 MB**): TXT, XLS/XLSX, DOC/DOCX, PPT/PPTX, PDF. Otros tipos pueden
|
||||
enviarse pero no están soportados oficialmente.
|
||||
|
||||
**Sticker** [6] — `type: "sticker"`, objeto `sticker`: `{ id | link }` (sin caption).
|
||||
Formato **WebP** únicamente: animado máx **500 KB**, estático máx **100 KB**.
|
||||
Vista: se muestra como sticker (sin texto); error si el WebP no es soportado o excede el tamaño.
|
||||
|
||||
Vista general media: la burbuja muestra el recurso y, si aplica, el caption debajo; en document
|
||||
aparece icono por extensión + filename; en image/video el caption va bajo el recurso [2][3][5].
|
||||
|
||||
## 4. Location
|
||||
|
||||
Payload [7] — `type: "location"`, objeto `location`:
|
||||
|
||||
| Campo | Requerido | Ejemplo |
|
||||
|---|---|---|
|
||||
| `latitude` | sí | `"37.44216251868683"` (grados decimales) |
|
||||
| `longitude` | sí | `"-122.16153582049394"` |
|
||||
| `name` | no | `"Philz Coffee"` |
|
||||
| `address` | no | `"101 Forest Ave, Palo Alto, CA 94301"` |
|
||||
|
||||
Vista: tarjeta de mapa con las coordenadas; nombre y dirección se muestran como título/detalle.
|
||||
La página no especifica límites de caracteres ni renderizado adicional [7].
|
||||
|
||||
## 5. Contacts
|
||||
|
||||
Payload [8] — `type: "contacts"`, array `contacts[]` de objetos contacto.
|
||||
Cada mensaje puede incluir **hasta 257 contactos** (se recomienda menos por usabilidad).
|
||||
Único campo requerido por contacto: `name.formatted_name` (es lo que aparece en la burbuja
|
||||
junto al botón de flecha de perfil). Resto opcionales [8]:
|
||||
|
||||
- `name`: `formatted_name`, `first_name`, `last_name`, `middle_name`, `suffix`, `prefix`
|
||||
- `phones[]`: `phone`, `type` (CELL/MAIN/IPHONE/HOME/WORK), `wa_id` — si falta `wa_id`,
|
||||
el botón Message/Save se sustituye por **"Invite to WhatsApp"**
|
||||
- `emails[]`: `email`, `type` (PERSONAL/WORK)
|
||||
- `urls[]`: `url`, `type` (COMPANY/WORK/PERSONAL/FACEBOOK_PAGE/INSTAGRAM)
|
||||
- `org`: `company`, `department`, `title`
|
||||
- `addresses[]`: `street`, `city`, `state`, `zip`, `country`, `country_code` (ISO-2), `type`
|
||||
- `birthday`: formato `YYYY-MM-DD`
|
||||
|
||||
Vista: tarjeta de contacto con avatar, nombre formateado y filas por cada dato presente;
|
||||
algunos metadatos (direcciones, cumpleaños) pueden no mostrarse según el dispositivo del usuario [8].
|
||||
|
||||
## 6. Interactive
|
||||
|
||||
`type: "interactive"` + objeto `interactive` con `type` de: `button`, `list`, `cta_url`,
|
||||
`product`, `product_list`, `catalog_message`, `carousel`, `flow` (y `call_permission_request`) [17].
|
||||
Objetos internos: `header` (`HeaderObject`: text/image/video/document; requerido para `product_list`,
|
||||
**no permitido** en `product`), `body` (`text`, requerido — "emojis y markdown soportados"),
|
||||
`footer` (`text`, opcional — "emojis, markdown y links soportados"), `action` (estructura varía por tipo) [17].
|
||||
|
||||
### 6.1 Botones reply (quick replies) — `interactive.type: "button"` [10]
|
||||
|
||||
```json
|
||||
{ "type": "interactive",
|
||||
"interactive": {
|
||||
"type": "button",
|
||||
"header": { "type": "text", "text": "Detalles" },
|
||||
"body": { "text": "¿Confirmas tu cita?" },
|
||||
"footer": { "text": "Elige una opción" },
|
||||
"action": { "buttons": [
|
||||
{ "type": "reply", "reply": { "id": "id_si", "title": "Sí" } },
|
||||
{ "type": "reply", "reply": { "id": "id_no", "title": "No" } } ] } } }
|
||||
```
|
||||
|
||||
| Campo | Límite |
|
||||
|---|---|
|
||||
| Botones | **máx 3** |
|
||||
| `reply.title` | **20 caracteres**, único entre botones |
|
||||
| `reply.id` | **256 caracteres**, único por botón |
|
||||
| `body.text` | **1024 caracteres** (URLs se hipervinculan) |
|
||||
| `footer.text` | **60 caracteres** |
|
||||
| `header` | tipos text/image/video/document (límite de header text no declarado en esta página) [10] |
|
||||
|
||||
Vista: header arriba (media o texto), body, footer y los botones como filas-blanco fijas bajo la
|
||||
burbuja. Al tocar, webhook `messages` con `button_reply.id`/`title` + `context.id` del mensaje original [10].
|
||||
|
||||
### 6.2 Lista — `interactive.type: "list"` [9]
|
||||
|
||||
```json
|
||||
{ "type": "interactive",
|
||||
"interactive": {
|
||||
"type": "list",
|
||||
"header": { "type": "text", "text": "Menú" },
|
||||
"body": { "text": "Selecciona un producto" },
|
||||
"footer": { "text": "Catálogo 2026" },
|
||||
"action": { "button": "Ver opciones",
|
||||
"sections": [
|
||||
{ "title": "Bebidas",
|
||||
"rows": [ { "id": "r1", "title": "Café", "description": "Chico" } ] } ] } } }
|
||||
```
|
||||
|
||||
| Campo | Límite |
|
||||
|---|---|
|
||||
| Secciones | **mín 1, máx 10** |
|
||||
| Filas (total, sumando secciones) | **máx 10** |
|
||||
| `action.button` (etiqueta que despliega) | **20 caracteres** |
|
||||
| `header.text` | **60 caracteres** (solo type text) |
|
||||
| `body.text` | **4096 caracteres** |
|
||||
| `footer.text` | **60 caracteres** |
|
||||
| Título de sección | **24 caracteres** (requerido solo si hay >1 sección, [17]) |
|
||||
| `row.title` | **24 caracteres** |
|
||||
| `row.description` | opcional, **72 caracteres** |
|
||||
| `row.id` | **200 caracteres** |
|
||||
|
||||
Vista: burbuja con header/body/footer y **un único botón** (`action.button`) que abre la lista
|
||||
de opciones seleccionables a pantalla (las filas muestran title y description); el webhook devuelve
|
||||
`list_reply` con `id`, `title`, `description` + `context` [9].
|
||||
|
||||
### 6.3 CTA URL — `interactive.type: "cta_url"` [11]
|
||||
|
||||
```json
|
||||
"interactive": {
|
||||
"type": "cta_url",
|
||||
"header": { "type": "image", "image": { "link": "https://…/promo.jpg" } },
|
||||
"body": { "text": "Aprovecha la promo" },
|
||||
"footer": { "text": "Vence hoy" },
|
||||
"action": { "name": "cta_url",
|
||||
"parameters": { "display_text": "Abrir tienda", "url": "https://mitienda.com" } } }
|
||||
```
|
||||
|
||||
Límites: `display_text` **20 caracteres**; `body.text` **1024**; `footer.text` **60**;
|
||||
`header.text` **60**. Header opcional de tipo image/video/document/text. Un solo botón URL por
|
||||
acción; la doc menciona etiquetas únicas "si se usan múltiples botones" sin declarar máximo [11].
|
||||
Vista: media/texto del header, body, footer y un botón azul que abre el navegador con la URL [11].
|
||||
|
||||
### 6.4 Producto único — `interactive.type: "product"` [15]
|
||||
|
||||
```json
|
||||
"interactive": {
|
||||
"type": "product",
|
||||
"body": { "text": "Texto opcional" },
|
||||
"footer": { "text": "Texto opcional" },
|
||||
"action": { "catalog_id": "123456789", "product_retailer_id": "SKU-001" } }
|
||||
```
|
||||
|
||||
`action` requiere `catalog_id` + `product_retailer_id` (SKU del producto); `header` **no permitido**
|
||||
en este tipo [15][17]; body/footer opcionales. Sin límites de caracteres declarados en la página [15].
|
||||
Vista: tarjeta con imagen/nombre/precio actuales del producto; al tocar se abre una
|
||||
**Product Detail Page (PDP)** con los datos en tiempo real (solo imágenes; videos/GIF no se muestran);
|
||||
hay botón para escribir al negocio; reenviable, no puede enviarse como notificación [15].
|
||||
|
||||
### 6.5 Multi-producto — `interactive.type: "product_list"` [16]
|
||||
|
||||
```json
|
||||
"interactive": {
|
||||
"type": "product_list",
|
||||
"header": { "type": "text", "text": "Nuestra tienda" },
|
||||
"body": { "text": "Elige productos" },
|
||||
"footer": { "text": "Envío gratis" },
|
||||
"action": { "catalog_id": "123456789",
|
||||
"sections": [ { "title": "Cafés",
|
||||
"product_items": [ { "product_retailer_id": "SKU-001" } ] } ] } }
|
||||
```
|
||||
|
||||
Requeridos: header type **text**, body, `action.catalog_id` + `sections[]` (`title` +
|
||||
`product_items[].product_retailer_id`). Límite documentado: **hasta 30 productos** en secciones;
|
||||
máximo de secciones y límites de texto NO declarados en la página (el título de sección es el
|
||||
`SectionObject.title` de máx 24 chars según [17]). Si el SKU no existe se descarta y llega
|
||||
error pidiendo actualización de catálogo [16]. Vista: carrusel horizontal de productos que abre
|
||||
PDP y permite armar carrito por dispositivo (el carrito no sincroniza entre dispositivos) [16].
|
||||
|
||||
### 6.6 Catálogo — `interactive.type: "catalog_message"` [14]
|
||||
|
||||
```json
|
||||
"interactive": {
|
||||
"type": "catalog_message",
|
||||
"body": { "text": "Explora nuestro catálogo" },
|
||||
"action": { "name": "catalog_message",
|
||||
"parameters": { "thumbnail_product_retailer_id": "SKU-001" } },
|
||||
"footer": { "text": "Tienda oficial" } }
|
||||
```
|
||||
|
||||
`body.text` máx **1024**; `footer.text` máx **60**; `thumbnail_product_retailer_id` opcional
|
||||
(define la miniatura; si falta se usa la imagen del primer artículo del catálogo) [14].
|
||||
Vista: miniatura de producto, texto fijo de encabezado, body, footer y botón **"View catalog"**
|
||||
que abre el catálogo completo dentro de WhatsApp [14].
|
||||
|
||||
### 6.7 Carrusel de productos — `interactive.type: "carousel"` (cards tipo product) [13]
|
||||
|
||||
```json
|
||||
"interactive": {
|
||||
"type": "carousel",
|
||||
"body": { "text": "Lo más vendido" },
|
||||
"action": { "cards": [
|
||||
{ "card_index": 0, "type": "product",
|
||||
"action": { "product_retailer_id": "SKU-001", "catalog_id": "123456789" } } ] } }
|
||||
```
|
||||
|
||||
Límites: **2 a 10 cards**; `card_index` entero **0–9**, sin repetir; todas las cards deben
|
||||
referenciar el **mismo `catalog_id`**; `body.text` máx **1024**. **Sin header, footer ni botones**
|
||||
a nivel de mensaje [13]. Vista: tarjetas desplazables horizontalmente, cada una abre su PDP [13][15].
|
||||
|
||||
### 6.8 Carrusel de media — cards con header image/video [12]
|
||||
|
||||
```json
|
||||
"interactive": {
|
||||
"type": "carousel",
|
||||
"body": { "text": "Nuevos cursos" },
|
||||
"action": { "cards": [
|
||||
{ "card_index": 0,
|
||||
"header": { "type": "image", "image": { "link": "https://…/a.jpg" } },
|
||||
"body": { "text": "Curso A" },
|
||||
"action": { "name": "cta_url",
|
||||
"parameters": { "display_text": "Inscribirme", "url": "https://…" } } } ] } }
|
||||
```
|
||||
|
||||
Límites exactos [12]: **2–10 cards**; header por card **solo image o video** (`link` o `id`);
|
||||
body por card máx **160 caracteres y 2 saltos de línea**; body del mensaje máx **1024**;
|
||||
quick-reply `id` máx **256**, etiquetas (quick reply y URL) máx **20**; cada card lleva **un botón
|
||||
URL o uno o más quick replies**; tipos y cantidades de botones deben ser idénticos en todas las cards.
|
||||
Sin header/footer a nivel de mensaje. Vista: cards con media arriba, texto y botón, desplazables
|
||||
izquierda→derecha desde índice 0 [12].
|
||||
|
||||
## 7. Template messages
|
||||
|
||||
Único tipo enviable **fuera de la ventana de servicio** al cliente; se crean vía Template API o
|
||||
WhatsApp Manager y deben quedar `APPROVED` antes de enviarse [19]. Creación: `name` (máx 512,
|
||||
minúsculas/guiones bajos), `category` (AUTHENTICATION/MARKETING/UTILITY), `language`,
|
||||
`parameter_format` (`named` p.ej. `{{first_name}}`, o `positional` p.ej. `{{1}}`) y `components`
|
||||
[19]. Límites de cuenta: **250 plantillas/WABA** (6000 con portafolio verificado + display name
|
||||
aprobado), **100 plantillas creadas por hora** por WABA [19].
|
||||
|
||||
### 7.1 Envío por Cloud API [21]
|
||||
|
||||
```json
|
||||
{ "messaging_product": "whatsapp",
|
||||
"recipient_type": "individual",
|
||||
"to": "16505551234",
|
||||
"type": "template",
|
||||
"template": {
|
||||
"name": "reservation_confirmation",
|
||||
"language": { "code": "en_US" },
|
||||
"components": [
|
||||
{ "type": "header",
|
||||
"parameters": [ { "type": "image", "image": { "id": "2871834006348767" } } ] },
|
||||
{ "type": "body",
|
||||
"parameters": [ { "type": "text", "parameter_name": "day", "text": "Saturday" } ] },
|
||||
{ "type": "buttons",
|
||||
"sub_type": "URL", "index": 0,
|
||||
"parameters": [ { "type": "text", "text": "abc123" } ] } ] } }
|
||||
```
|
||||
|
||||
El header solo se envía si la plantilla usa header de media (image/video/document; los header
|
||||
text/location no llevan parámetros en el envío) [21]. En plantillas posicionales los parámetros
|
||||
van por orden, sin `parameter_name` [21]. En webhook los botones responden con
|
||||
`button_reply`/`list_reply`; COPY_CODE entrega el código y CATALOG/MPM abren catálogo (los
|
||||
sub_types de botón definidos por la API son: `CATALOG`, `COPY_CODE`, `FLOW`, `MPM`, `OTP`,
|
||||
`PHONE_NUMBER`, `QUICK_REPLY`, `URL` [18]).
|
||||
|
||||
### 7.2 Componentes y límites de caracteres (creación) [20]
|
||||
|
||||
| Componente | Formatos / tipos | Límites |
|
||||
|---|---|---|
|
||||
| **HEADER** (1 máx) | `format`: TEXT, IMAGE, VIDEO, DOCUMENT, LOCATION | TEXT: **60 caracteres**, sin markdown, admite 1 parámetro. Media: handle de Resumable Upload API (GIF mp4 ≤3.5 MB, solo Marketing). LOCATION: sin parámetros al crear; al enviar `latitude`, `longitude`, `name`, `address`; solo UTILITY/MARKETING |
|
||||
| **BODY** (requerido, 1) | texto | **1024 caracteres**; parámetros múltiples named/posicionales con ejemplos obligatorios |
|
||||
| **FOOTER** (opcional, 1) | texto | **60 caracteres** |
|
||||
| **BUTTONS** (array `buttons`) | ver abajo | **máx 10 botones en total** por plantilla |
|
||||
|
||||
Botones por tipo [20]:
|
||||
|
||||
- **QUICK_REPLY**: hasta **10**; etiqueta máx **25 caracteres**; deben agruparse (no intercalar
|
||||
`QR, URL, QR`); el orden en el teléfono lo define `index` al enviar.
|
||||
- **URL**: hasta **2**; etiqueta 25; `url` máx **2000 caracteres**, admite **1 variable** al final
|
||||
(requiere `example`; valores con caracteres especiales deben ir percent-encoded: `%20`, `%3A`,
|
||||
`%7C`… o el envío falla). El título corto del botón puede sobreescribirse (`tap-target-url-title-override`).
|
||||
- **PHONE_NUMBER**: solo **1**; `phone_number` máx **20 caracteres** (se recortan ceros a la
|
||||
izquierda tras el código de país); etiqueta 25.
|
||||
- **COPY_CODE**: solo **1**; código copiable en `example`, **máx 20 caracteres**.
|
||||
- **CATALOG**: abre el catálogo; **MPM** (multi-producto) muestra hasta **30 productos en hasta
|
||||
10 secciones**; ambos no personalizables.
|
||||
- **VOICE_CALL**: inicia llamada de WhatsApp al negocio; **OTP** (URL/ONE_TAP/ZERO_TAP) para
|
||||
plantillas de autenticación, con `autofill_text`, `package_name`, `signature_hash`.
|
||||
|
||||
Rendimiento en pantalla [20]: con **>3 botones** WhatsApp muestra 2 y un botón **"See all options"**
|
||||
que expande el resto; plantillas con **4+ botones**, o quick replies mezcladas con otros tipos,
|
||||
**no se ven en clientes de escritorio**. Vista general: header arriba del body; body con variables
|
||||
resaltadas; footer en gris pequeño; botones como filas fijas al pie de la burbuja [20].
|
||||
|
||||
### 7.3 Plantillas de carrusel (marketing)
|
||||
|
||||
Existen `media-card-carousel-templates` (cards de media) y `product-card-carousel-template-messages`
|
||||
[19]; su estructura de componentes en la Template API incluye `type: CAROUSEL` y
|
||||
`LIMITED_TIME_OFFER` [18]. Detalle no extraído en esta investigación (fuera del alcance directo).
|
||||
|
||||
## 8. Tabla resumen de límites clave
|
||||
|
||||
| Elemento | Límite | Fuente |
|
||||
|---|---|---|
|
||||
| `text.body` / body de lista | 4096 | [1][9] |
|
||||
| Caption de image/video/document | 1024 | [2][3][5] |
|
||||
| Tamaño image / video / audio / document | 5 MB / 16 MB / 16 MB / 100 MB | [2][3][4][5] |
|
||||
| Sticker WebP animado / estático | 500 KB / 100 KB | [6] |
|
||||
| Contactos por mensaje | 257 | [8] |
|
||||
| Botones reply / list rows / secciones | 3 / 10 / 10 | [10][9] |
|
||||
| Título botón (interactive) / display_text | 20 / 20 | [10][11][12] |
|
||||
| `reply.id` / `row.id` | 256 / 200 | [10][9] |
|
||||
| Header / footer interactivos | 60 / 60 | [9][11] |
|
||||
| Section title / row title / row description | 24 / 24 / 72 | [9][17] |
|
||||
| Body de card de carrusel de media | 160 (2 saltos) | [12] |
|
||||
| Cards de carrusel | 2–10 (índices 0–9) | [12][13] |
|
||||
| Productos por product_list / MPM | 30 (en ≤10 secciones) | [16][20] |
|
||||
| Plantilla: header TEXT / body / footer | 60 / 1024 / 60 | [20] |
|
||||
| Plantilla: botones totales / QR / URL / PHONE / COPY_CODE | 10 / 10 / 2 / 1 / 1 | [20] |
|
||||
| Plantilla: etiqueta botón / URL / phone / código | 25 / 2000 / 20 / 20 | [20] |
|
||||
| Plantillas por WABA / creación por hora | 250 (6000 verificada) / 100 | [19] |
|
||||
|
||||
## 9. Fuentes consultadas (oficiales, developers.facebook.com)
|
||||
|
||||
[1] https://developers.facebook.com/docs/whatsapp/cloud-api/messages/text-messages
|
||||
[2] https://developers.facebook.com/docs/whatsapp/cloud-api/messages/image-messages
|
||||
[3] https://developers.facebook.com/docs/whatsapp/cloud-api/messages/video-messages
|
||||
[4] https://developers.facebook.com/docs/whatsapp/cloud-api/messages/audio-messages
|
||||
[5] https://developers.facebook.com/docs/whatsapp/cloud-api/messages/document-messages
|
||||
[6] https://developers.facebook.com/docs/whatsapp/cloud-api/messages/sticker-messages
|
||||
[7] https://developers.facebook.com/docs/whatsapp/cloud-api/messages/location-messages
|
||||
[8] https://developers.facebook.com/docs/whatsapp/cloud-api/messages/contacts-messages
|
||||
[9] https://developers.facebook.com/documentation/business-messaging/whatsapp/messages/interactive-list-messages
|
||||
[10] https://developers.facebook.com/documentation/business-messaging/whatsapp/messages/interactive-reply-buttons-messages
|
||||
[11] https://developers.facebook.com/documentation/business-messaging/whatsapp/messages/interactive-cta-url-messages
|
||||
[12] https://developers.facebook.com/documentation/business-messaging/whatsapp/messages/interactive-media-carousel-messages.md
|
||||
[13] https://developers.facebook.com/documentation/business-messaging/whatsapp/catalogs/interactive-product-carousel-messages.md
|
||||
[14] https://developers.facebook.com/documentation/business-messaging/whatsapp/catalogs/catalog-messages.md
|
||||
[15] https://developers.facebook.com/documentation/business-messaging/whatsapp/catalogs/single-product-messages.md
|
||||
[16] https://developers.facebook.com/documentation/business-messaging/whatsapp/catalogs/multi-product-messages.md
|
||||
[17] https://developers.facebook.com/documentation/business-messaging/whatsapp/reference/whatsapp-business-phone-number/message-api.md
|
||||
[18] https://developers.facebook.com/documentation/business-messaging/whatsapp/reference/whatsapp-business-account/message-template-api.md
|
||||
[19] https://developers.facebook.com/documentation/business-messaging/whatsapp/templates/overview.md
|
||||
[20] https://developers.facebook.com/documentation/business-messaging/whatsapp/templates/components.md
|
||||
[21] https://developers.facebook.com/documentation/business-messaging/whatsapp/templates/utility-templates/utility-templates.md
|
||||
[22] https://developers.facebook.com/documentation/business-messaging/whatsapp/link-previews.md
|
||||
|
||||
**Declaraciones de cobertura**: (a) la sintaxis de formateo de texto (*bold*, _italic_, ~tachado~,
|
||||
mono) ya no está documentada en las páginas oficiales consultadas — solo consta la nota de que
|
||||
body/footer interactivos soportan markdown [17] y la prohibición de markdown en header TEXT de
|
||||
plantillas [20]; (b) límites no declarados: máximo de secciones en product_list, límites de texto
|
||||
en `product`, límite de header text en `interactive.type: button`, y máximo de botones en
|
||||
`cta_url` — se reportan como no documentados, no como valores asumidos; (c) varias páginas nuevas
|
||||
(carousel-messages, product-messages en su slug HTML) solo renderizan con JavaScript y se accedió
|
||||
a su contenido vía las versiones `.md` publicadas por Meta en el índice `llms.txt`.
|
||||
@@ -0,0 +1,324 @@
|
||||
# Research UI — WhatsApp Business/Cloud API renderizado en WhatsApp iOS
|
||||
|
||||
> Objetivo: especificación orientada a CSS para replicar cómo se ven los mensajes de la
|
||||
> Cloud API en la app de WhatsApp para iPhone (diseño unificado 2022+, con notas del
|
||||
> rediseño iOS 2024–2025). Valores en px sobre un layout de 393 pt de ancho.
|
||||
|
||||
## 0. Fiabilidad de las fuentes
|
||||
|
||||
Meta **no publica** hex oficiales del cliente móvil; su documentación describe estructura
|
||||
(orden de componentes, límites de caracteres) pero no colores. Los hex del cliente son
|
||||
**medidos por la comunidad** (Figma kits, clones de código abierto, WABetaInfo) y
|
||||
coinciden entre fuentes independientes, por lo que se consideran fiables. Marcado usado:
|
||||
|
||||
- `[META]` — confirmado en developers.facebook.com (estructura/límites, no hex).
|
||||
- `[COM]` — hex/medidas de comunidad (Múltiples kits Figma y clones coinciden).
|
||||
- `[WBI]` — WABetaInfo vía PocketNow (cambio de color de burbuja iOS, beta 2.21.200.11).
|
||||
- `[APL]` — Apple/screensizes.app (geometría del dispositivo).
|
||||
|
||||
---
|
||||
|
||||
## 1. Modo claro
|
||||
|
||||
```css
|
||||
.wa {
|
||||
/* Fondo del chat: beige con patrón doodle */
|
||||
--wa-bg-chat: #efeae2; /* [COM] variantes citadas: #efe7de / clásico #e5ddd5 */
|
||||
--wa-doodle-opacity: 0.045; /* [COM] doodles al ~4–6% sobre el fondo */
|
||||
|
||||
/* Burbujas */
|
||||
--wa-bubble-in: #ffffff; /* [COM] iOS entrante blanca; Web/Android #f0f0f0; clásico #ece5dd */
|
||||
--wa-bubble-out: #d9fdd3; /* [COM] saliente verde claro; clásico iOS #dcf8c6 */
|
||||
/* [WBI] beta iOS 2.21.200.11: #e1f6ca → #e2fdd5 (misma familia de verde) */
|
||||
|
||||
/* Texto */
|
||||
--wa-text: #111b21; /* [COM] texto de burbuja, casi negro */
|
||||
--wa-text-meta: #667781; /* [COM] hora, fechas, "escribiendo…", footer de plantilla */
|
||||
--wa-link: #027eb5; /* [COM] enlaces dentro de burbuja (azul WhatsApp, no iOS blue) */
|
||||
--wa-tick: #667781; /* [COM] ✓ enviado y ✓✓ entregado (mismo gris que la hora) */
|
||||
--wa-tick-read: #53bdeb; /* [COM] ✓✓ leído (celeste) — igual en claro y oscuro */
|
||||
|
||||
/* Chrome (header + barra inferior): iOS usa gris muy claro, no blanco puro */
|
||||
--wa-chrome: #f6f6f6; /* [COM] header y compose bar iOS; WhatsApp Web usa #f0f2f5 */
|
||||
--wa-chrome-text: #000000;
|
||||
--wa-compose-field: #ffffff; /* [COM] campo "Mensaje" blanco redondeado */
|
||||
--wa-separator: rgba(0,0,0,.08); /* [COM] hairlines */
|
||||
--wa-accent: #00a884; /* [COM] verde de acento actual (iconos, botones) */
|
||||
--wa-accent-deep: #008069; /* [COM] variante oscura del acento */
|
||||
}
|
||||
```
|
||||
|
||||
Brand histórico (único hex "oficial" publicado en paletas de marca) `[COM/Mobbin]`:
|
||||
`#075e54` teal header clásico · `#128c7e` teal secundario · `#25d366` verde marca.
|
||||
El teal de header desapareció del chat en el rediseño de 2022; solo sirve para
|
||||
ilustraciones de marca.
|
||||
|
||||
## 2. Modo oscuro
|
||||
|
||||
```css
|
||||
.wa.dark {
|
||||
--wa-bg-chat: #0b141a; /* [COM] Web/Android unificado; iOS AMOLED tiende a #000000 */
|
||||
--wa-doodle-opacity: 0.04;
|
||||
|
||||
--wa-bubble-in: #202c33; /* [COM] entrante; variante iOS citada #1f2c33 */
|
||||
--wa-bubble-out: #005c4b; /* [COM] saliente verde oscuro; [WBI] beta iOS: #204f46 */
|
||||
|
||||
--wa-text: #e9edef; /* [COM] casi blanco */
|
||||
--wa-text-meta: #8696a0; /* [COM] hora/meta en oscuro */
|
||||
--wa-link: #53bdeb; /* [COM] enlaces toman el celeste de acento en oscuro */
|
||||
--wa-tick: #8696a0;
|
||||
--wa-tick-read: #53bdeb;
|
||||
|
||||
--wa-chrome: #202c33; /* [COM] header/compose Web; iOS oscuro puro: #1c1c1e–#000000 */
|
||||
--wa-chrome-text: #e9edef;
|
||||
--wa-compose-field: #2a3942; /* [COM] campo "Mensaje" en oscuro */
|
||||
--wa-separator: rgba(255,255,255,.10);
|
||||
--wa-accent: #00a884;
|
||||
}
|
||||
```
|
||||
|
||||
Nota iOS 2024–2025: el rediseño de WhatsApp iOS usa fondo **negro puro** en oscuro y
|
||||
burbujas aún más redondeadas (guías de personalización WWeb; ithinkdiff sobre beta
|
||||
26.29.10.70). Si el mockup representa "iOS hoy": `--wa-bg-chat:#000`,
|
||||
`--wa-bubble-in:#1c1c1e`–`#202c33`, `--wa-bubble-out:#005c4b`, chrome `#000/#1c1c1e`.
|
||||
|
||||
## 3. Tipografía
|
||||
|
||||
```css
|
||||
.wa {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text",
|
||||
"Helvetica Neue", Helvetica, Arial, sans-serif; /* [APL/COM] stack iOS */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
.wa .bubble { font-size: 17px; line-height: 1.3; } /* 17 pt = .body de iOS [COM] */
|
||||
.wa .meta { font-size: 11px; line-height: 1; } /* hora + ticks dentro de burbuja */
|
||||
.wa .header-title { font-size: 17px; font-weight: 600; } /* nombre contacto, semibold */
|
||||
.wa .header-sub { font-size: 13px; font-weight: 400; } /* "en línea" / "escribiendo…" */
|
||||
.wa .btn-label { font-size: 17px; } /* botones de plantilla, texto centrado */
|
||||
.wa .template-footer { font-size: 12px; color: var(--wa-text-meta); }
|
||||
.wa .btn-domain { font-size: 12px; color: var(--wa-text-meta); } /* dominio del CTA URL */
|
||||
```
|
||||
|
||||
- Enlaces de burbuja sin subrayado; `color: var(--wa-link)`.
|
||||
- Hora y ticks van **dentro** de la burbuja, alineados abajo-derecha; el texto del
|
||||
mensaje se rellena con un espaciador para no pisarlos (ver §4).
|
||||
|
||||
## 4. Geometría de burbujas
|
||||
|
||||
```css
|
||||
.wa .row { display:flex; padding:1px 16px 0; } /* fila de mensaje */
|
||||
.wa .row + .row { margin-top:2px; } /* mismo emisor: 2–3px [COM] */
|
||||
.wa .row.new-group { margin-top:10px; } /* cambia emisor: 8–12px [COM] */
|
||||
.wa .row.out { justify-content:flex-end; }
|
||||
.wa .bubble {
|
||||
position:relative;
|
||||
max-width:78%; /* ~75–80% del ancho [COM] */
|
||||
padding:6px 9px 8px 7px; /* izq≠der por la cola [COM] */
|
||||
border-radius:18px; /* esquinas continuas (squircle) [COM] */
|
||||
background:var(--wa-bubble-in);
|
||||
}
|
||||
.wa .row.out .bubble { background:var(--wa-bubble-out); }
|
||||
|
||||
/* Cola: entrante arriba-izquierda, saliente arriba-derecha.
|
||||
La esquina del lado de la cola se afila; el rabito curvo se dibuja con ::before */
|
||||
.wa .row.in .bubble { border-top-left-radius:5px; }
|
||||
.wa .row.out .bubble { border-top-right-radius:5px; }
|
||||
|
||||
.wa .row.in .bubble::before { /* cola entrante */
|
||||
content:""; position:absolute; top:0; left:-8px;
|
||||
width:8px; height:13px; fill:var(--wa-bubble-in);
|
||||
/* clip-path con curva tipo cola; alternativa: SVG inline */
|
||||
clip-path: path("M8 0 H0 C4 4 6 8 8 13 Z");
|
||||
}
|
||||
.wa .row.out .bubble::before { /* cola saliente (espejo) */
|
||||
content:""; position:absolute; top:0; right:-8px;
|
||||
width:8px; height:13px; fill:var(--wa-bubble-out);
|
||||
clip-path: path("M0 0 H8 C4 4 2 8 0 13 Z");
|
||||
}
|
||||
```
|
||||
|
||||
- Rediseño iOS 2025: burbujas todavía más redondas (WABetaInfo/ithinkdiff) — para un
|
||||
look "última generación" usar `border-radius:20–22px` y esquina de cola `6px`.
|
||||
- Media (foto/vídeo) sin padding lateral: la imagen ocupa toda la burbuja
|
||||
(`padding:0`), esquinas redondeadas iguales, hora encima con gradiente inferior.
|
||||
|
||||
Hora + ticks dentro de la burbuja:
|
||||
|
||||
```css
|
||||
.wa .meta {
|
||||
display:flex; align-items:center; gap:2px;
|
||||
justify-content:flex-end;
|
||||
float:right; /* o grid: el texto envuelve alrededor */
|
||||
margin:6px 0 -2px 12px; /* el texto del mensaje reserva este hueco */
|
||||
color:var(--wa-text-meta); font-size:11px; user-select:none;
|
||||
}
|
||||
.wa .meta .tick-read { color:var(--wa-tick-read); }
|
||||
```
|
||||
|
||||
Estados de tick `[META/COM]`: reloj (pendiente) → `✓` enviado → `✓✓` gris entregado →
|
||||
`✓✓` celeste `#53bdeb` leído. El doble tick son dos marcas solapadas ~2px.
|
||||
|
||||
## 5. Chrome del chat
|
||||
|
||||
```css
|
||||
.wa .header {
|
||||
display:flex; align-items:center; gap:12px;
|
||||
padding:8px 12px; background:var(--wa-chrome);
|
||||
border-bottom:1px solid var(--wa-separator);
|
||||
/* con Dynamic Island el header arranca bajo la status bar (54pt) */
|
||||
}
|
||||
.wa .back-chevron { width:22px; } /* chevron fino, color acento azul iOS o gris */
|
||||
.wa .avatar { width:40px; height:40px; border-radius:50%; object-fit:cover; }
|
||||
.wa .header-title { flex:1; } /* nombre bold + subtítulo debajo */
|
||||
.wa .icon-video, .wa .icon-call { width:24px; margin-left:16px; } /* videollamada, llamada */
|
||||
```
|
||||
|
||||
- Subtítulo: "en línea" estático gris; "escribiendo…" en verde acento `[COM]`.
|
||||
- Barra inferior (compose):
|
||||
|
||||
```css
|
||||
.wa .compose {
|
||||
display:flex; align-items:center; gap:8px;
|
||||
padding:8px 12px calc(8px + env(safe-area-inset-bottom));
|
||||
background:var(--wa-chrome);
|
||||
}
|
||||
.wa .attach { width:28px; } /* + o clip: cámara/fotos/adjuntos */
|
||||
.wa .field {
|
||||
flex:1; display:flex; align-items:center; gap:8px;
|
||||
height:38px; padding:0 12px; border-radius:19px; /* píldora [COM] */
|
||||
background:var(--wa-compose-field);
|
||||
color:var(--wa-text-meta); /* placeholder "Mensaje" */
|
||||
}
|
||||
.wa .mic { width:26px; } /* micrófono cuando el campo está vacío */
|
||||
```
|
||||
|
||||
## 6. Renderizado de mensajes de la Cloud API `[META]` + observación `[COM]`
|
||||
|
||||
### 6.1 Botones de respuesta rápida (interactive `type:"button"`)
|
||||
- Estructura: header opcional + body (≤1024) + footer (≤60) + **hasta 3 botones**
|
||||
(título ≤20 caracteres `[META]`).
|
||||
- En iOS: **apilados verticalmente a todo el ancho del cuerpo**, dentro de una tarjeta
|
||||
continua con hairline entre ellos; texto **centrado** en verde acento
|
||||
(`--wa-accent` claro / `#53bdeb`-verde según versión en oscuro) `[COM]`.
|
||||
|
||||
```css
|
||||
.wa .qr-btns { display:flex; flex-direction:column; background:var(--wa-bubble-in);
|
||||
border-radius:14px; overflow:hidden; margin-top:8px; width:min(78%,340px); }
|
||||
.wa .qr-btn { padding:12px 8px; text-align:center; font-size:17px;
|
||||
color:var(--wa-accent); }
|
||||
.wa .qr-btn + .qr-btn { border-top:1px solid var(--wa-separator); }
|
||||
```
|
||||
|
||||
### 6.2 Botón CTA URL
|
||||
- Un botón tipo lista bajo la burbuja: icono de **enlace** (o teléfono) a la izquierda,
|
||||
etiqueta centrada ≤25 caracteres, **dominio en gris pequeño (12px) al pie del botón**
|
||||
`[COM]`; abre el navegador externo `[META]`.
|
||||
- Añadir un icono de enlace y en el borde inferior una fila de dominio:
|
||||
`.cta-domain { border-top:1px solid var(--wa-separator); font-size:12px; color:var(--wa-text-meta); text-align:center; }`
|
||||
|
||||
### 6.3 Mensajes de lista (`type:"list"`)
|
||||
- Burbuja con header (≤60, semibold), body (hasta 4096), footer (≤60) y **un único
|
||||
botón** (≤20 caracteres) `[META]`.
|
||||
- Al pulsarlo, iOS abre un **modal/sheet** con las secciones (≤10) y filas (≤10;
|
||||
título 24, descripción 72) — no filas inline `[META]`. En el mockup basta la burbuja
|
||||
con botón; el sheet es una vista modal con chevrons/grupo agrupado estilo iOS.
|
||||
|
||||
### 6.4 Plantillas (message templates)
|
||||
Orden renderizado `[META]`: **header → body → footer → botones**.
|
||||
|
||||
```css
|
||||
.wa .template { width:min(78%,340px); border-radius:14px; overflow:hidden;
|
||||
background:var(--wa-bubble-in); display:flex; flex-direction:column; }
|
||||
.wa .tpl-media { width:100%; aspect-ratio:16/9; object-fit:cover; } /* header media full-bleed */
|
||||
.wa .tpl-body { padding:8px 10px; font-size:15px; white-space:pre-wrap; } /* ≤1024 */
|
||||
.wa .tpl-footer { padding:0 10px 8px; font-size:12px; color:var(--wa-text-meta); }
|
||||
.wa .tpl-btns { border-top:1px solid var(--wa-separator); } /* reusar .qr-btns */
|
||||
```
|
||||
|
||||
- Header puede ser imagen/vídeo (16:9 recortado a ancho de burbuja), documento
|
||||
(icono + nombre), texto (≤60, semibold) o ubicación genérica `[META]`.
|
||||
- Footer gris pequeño (≤60) pegado al body.
|
||||
- Botones: quick replies (≤25 en plantillas) agrupados, URL ≤2, teléfono ≤1, total ≤10;
|
||||
si hay >3 botones, el resto se pliega en "See all options" `[META]`.
|
||||
|
||||
### 6.5 Carrusel (carousel template) `[META]`
|
||||
- 2–10 tarjetas, swipe horizontal con **scroll-snap**; cada tarjeta: media del header
|
||||
(recortada automática a proporción ancha según dispositivo) + body ≤160 + hasta
|
||||
2 botones; todas las tarjetas comparten componentes.
|
||||
- Tarjeta ~ 78% del ancho menos padding, con indicador de página (puntos) abajo `[COM]`.
|
||||
|
||||
```css
|
||||
.wa .carousel { display:flex; gap:8px; overflow-x:auto; scroll-snap-type:x mandatory;
|
||||
padding:2px 16px 8px; }
|
||||
.wa .card { flex:0 0 78%; scroll-snap-align:center; border-radius:14px; overflow:hidden;
|
||||
background:var(--wa-bubble-in); }
|
||||
```
|
||||
|
||||
### 6.6 Documento `[META]`
|
||||
Burbuja blanca/color entrante con: **icono de página coloreado según extensión** (el
|
||||
cliente elige el icono por extensión), nombre de archivo (`filename`) en negro/texto
|
||||
medio, extensión + nº páginas en gris pequeño, y botón circular de descarga a la
|
||||
derecha `[META: icono+nombre+tap para descargar; COM: disposición]`. Caption opcional
|
||||
(≤1024) debajo.
|
||||
|
||||
### 6.7 Audio / nota de voz `[META]`
|
||||
Burbuja con reproductor: botón play/pausa circular, **waveform** (barras verticales de
|
||||
~2px con huecos, altura variable), duración en gris y avatar del emisor en notas de voz
|
||||
propias `[COM: geometría del waveform]`. En la Cloud API se envía como `type:"audio"`
|
||||
(`audio`/`voice`), se renderiza igual que una nota de voz del usuario `[META]`.
|
||||
|
||||
### 6.8 Ubicación `[META]`
|
||||
Burbuja con **miniatura de mapa estático** (cuadrada redondeada arriba, con pin rojo
|
||||
centrado `[COM]`), nombre del sitio en semibold y dirección en gris debajo; tap abre
|
||||
mapa. Campos que llegan: `latitude`, `longitude`, `name`, `address` `[META]`.
|
||||
|
||||
### 6.9 Contacto `[META]`
|
||||
**Tarjeta** con iniciales/avatar redondo, nombre formateado en semibold y **flecha de
|
||||
perfil** (chevron); al pulsar abre vista de perfil estilo iOS con teléfonos, emails,
|
||||
direcciones, empresa, cumpleaños y webs, más botones "Message + Save contact" (con
|
||||
`wa_id`) o "Invite to WhatsApp" (sin `wa_id`) `[META]`.
|
||||
|
||||
## 7. Marco de iPhone moderno `[APL]` (iPhone 15/16 Pro base)
|
||||
|
||||
```css
|
||||
.iphone { width:393px; height:852px; border-radius:55px; background:#000;
|
||||
padding:0; position:relative; overflow:hidden; } /* 393×852pt, radio 55pt */
|
||||
.island { position:absolute; top:11px; left:50%; transform:translateX(-50%);
|
||||
width:126px; height:37px; border-radius:20px; background:#000; } /* [COM] */
|
||||
.statusbar { position:absolute; top:0; height:54px; width:100%;
|
||||
display:flex; justify-content:space-between; align-items:center;
|
||||
padding:18px 32px 0; color:#fff; font-size:15px; font-weight:600; }
|
||||
/* hora "9:41" a la izquierda; derecha: señal (4 barras), wifi, batería (iconos SF) */
|
||||
.home-indicator { position:absolute; bottom:8px; left:50%; transform:translateX(-50%);
|
||||
width:139px; height:5px; border-radius:3px; background:#fff; } /* [COM] 134–139 */
|
||||
```
|
||||
|
||||
- Status bar 54 pt de alto en modelos con Dynamic Island `[APL/useyourloaf]`; la hora
|
||||
"9:41" es la convención de Apple en marketing `[APL]`.
|
||||
- En modo claro la status bar del chat es **oscura** (texto negro sobre header claro);
|
||||
en oscuro, blanca.
|
||||
- El contenido del chat corre **debajo** del header con `backdrop-filter: blur` en iOS
|
||||
`[COM]` — opcional en mockup; los safe-area (59 pt arriba, 34 pt abajo) delimitan el
|
||||
header/compose reales.
|
||||
|
||||
## 8. Resumen de decisiones para el mockup
|
||||
|
||||
1. Usar el set 2022+ unificado (`#efeae2/#ffffff/#d9fdd3` claro, `#0b141a/#202c33/#005c4b`
|
||||
oscuro) como base; si el objetivo es "iOS 2025", fondo oscuro `#000` y burbujas 20–22px.
|
||||
2. Cola arriba (no abajo como WhatsApp Web): entrante `top-left`, saliente `top-right`.
|
||||
3. Hora+ticks flotan abajo-derecha dentro de la burbuja con espaciador de texto.
|
||||
4. Botones = tarjeta apilada con hairlines, texto centrado en acento verde.
|
||||
5. Los hex de cliente son mediciones de comunidad (Meta no publica token UI);
|
||||
documentar en el mockup como "aproximados".
|
||||
|
||||
## Fuentes consultadas
|
||||
|
||||
- Meta — Carousel templates: developers.facebook.com/docs/whatsapp/business-management-api/message-templates/carousel-templates
|
||||
- Meta — Template components (nueva ruta): developers.facebook.com/documentation/business-messaging/whatsapp/templates/components
|
||||
- Meta — Reply buttons: developers.facebook.com/documentation/business-messaging/whatsapp/messages/interactive-reply-buttons-messages
|
||||
- Meta — List messages: developers.facebook.com/documentation/business-messaging/whatsapp/messages/interactive-list-messages
|
||||
- Meta — Document / Location / Contacts messages: developers.facebook.com/documentation/business-messaging/whatsapp/messages/{document,location,contacts}-messages
|
||||
- PocketNow/WABetaInfo (hex burbuja iOS beta): pocketnow.com/whatsapp-redesigned-chat-bubble-iphone
|
||||
- Tokens de comunidad: ui.shreshtharora.com/components/bubble · whatsapp-components.crafter.run · styles.refero.design · gists github.com/13swat · nextwork.ai · codewithcurious.com · mobbin.com/colors/brand/whatsapp · color-hex.com/color-palette/110833
|
||||
- Dispositivo: screensizes.app/?model=iphone-15-pro · useyourloaf.com/blog/iphone-15-screen-sizes · behance.net/gallery/153642485 (Dynamic Island) · support.apple.com/en-us/111829
|
||||
- Rediseño iOS oscuro: wwebcustomizer.com/blog/how-to-make-whatsapp-web-look-like-an-iphone-2026 · ithinkdiff.com (burbujas más redondas, beta 26.29.10.70)
|
||||
Reference in New Issue
Block a user