Editor y toolbar: jerarquía, tarjetas legibles, foco seguro y autoPulsar estable

- Toolbar: «Nueva demo» primaria junto a la marca (N); Tema como icono;
  «Volver al ejemplo Café Aurora» (peligro) solo dentro del menú «⋯»;
  etiquetas de Nueva demo y Presentación visibles entre 900 y 1100 px.
- Tarjetas: flecha de dirección en el número (↙/↗), badge con icono
  (solo icono en editor estrecho), resumen en 2.ª línea al abrir, hueco
  de ↑/↓ reservado (sin saltos al pasar el ratón), container queries.
- Borrar (mensaje, botón, fila, tarjeta, respuesta) nunca deja el foco
  en otro botón ✕.
- autoPulsar sigue al elemento al mover/borrar/arrastrar; opción
  inexistente visible y aviso; casilla «Se pulsa sola» por elemento,
  chip «▶ auto» y select arriba del formulario.
- Deshacer/rehacer conservan el tema; el tema marca «Guardando…».
- Escenarios: siempre punto de deshacer, un único aviso con acción y
  foco al nombre de la cuenta; chips de tipos en el diálogo Demos,
  rejilla de 4 columnas en >= 1280 y sin nombre precargado.
- Paleta sin estado seleccionado, «+» en hover/foco, chip de destino
  y «+ Otro» solo tras el primer alta.
- Avisos abajo al centro sobre la vista previa; tel: válido en
  plantillas (máx. 1); interruptor «Mostrar cabecera» fijo (role=switch).
- Teclado: enlace «Saltar a la vista previa» y G / F6; atajos con ⌘ en
  Mac; etiqueta «Velocidad»; «Repetir desde el inicio».
- Demo vacía: herramientas ocultas y pista dentro del chat.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
urieljareth
2026-09-27 21:32:22 -06:00
co-authored by Claude Opus 5.5
parent 9a5f21badf
commit 3509a77d62
6 changed files with 762 additions and 134 deletions
+38 -23
View File
@@ -16,6 +16,9 @@
</head>
<body data-tema="claro">
<!-- Teclado: salta las tarjetas del editor directo al teléfono (atajo G / F6) -->
<a id="saltar-vista" class="wam-saltar" href="#chat-cuerpo">Saltar a la vista previa</a>
<div id="app">
<!-- ============ Barra superior de la app (shell A) ============ -->
@@ -28,6 +31,12 @@
<h1>WhatsApp Cloud API</h1>
<span class="toolbar-subtitulo">Mockup visual · demo estática</span>
</div>
<!-- Punto de partida del consultor: escenarios por industria y demos guardadas -->
<button id="btn-demos" class="tb-btn tb-btn-primario" type="button" title="Nueva demo: escenarios por industria y demos guardadas (N)" aria-keyshortcuts="N">
<svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3.5" y="3.5" width="7" height="7" rx="1.6"/><rect x="13.5" y="3.5" width="7" height="7" rx="1.6"/><rect x="3.5" y="13.5" width="7" height="7" rx="1.6"/><path d="M17 14v6M14 17h6"/></svg>
<span>Nueva demo</span>
<kbd class="tb-kbd" aria-hidden="true">N</kbd>
</button>
<!-- Estado del guardado local (lo pinta js/ux.js) -->
<span id="estado-guardado" class="tb-guardado" data-estado="ok" title="Guardado en este navegador">
<span class="tb-guardado-punto" aria-hidden="true"></span>
@@ -44,24 +53,18 @@
<svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 14 5-5-5-5"/><path d="M20 9H9.5a5.5 5.5 0 0 0 0 11H13"/></svg>
</button>
<span class="tb-separador" aria-hidden="true"></span>
<button id="btn-tema" class="tb-btn" type="button" title="Alternar tema claro / oscuro (T)" aria-label="Tema oscuro" aria-pressed="false">
<svg viewBox="0 0 24 24" width="17" height="17" fill="currentColor" aria-hidden="true"><path d="M12 2.6a9.4 9.4 0 1 0 0 18.8 9.4 9.4 0 0 0 0-18.8zm0 16.9V4.5a7.5 7.5 0 0 1 0 15z"/></svg>
<span>Tema</span>
</button>
<button id="btn-presentacion" class="tb-btn" type="button" title="Modo presentación: oculta el editor (P · Esc para salir)" aria-pressed="false">
<svg viewBox="0 0 24 24" width="17" height="17" fill="currentColor" fill-rule="evenodd" aria-hidden="true"><path d="M3 4.5h18a1 1 0 0 1 1 1V16a1 1 0 0 1-1 1h-6.4v2.1h1.9a.9.9 0 1 1 0 1.8H7.5a.9.9 0 1 1 0-1.8h1.9V17H3a1 1 0 0 1-1-1V5.5a1 1 0 0 1 1-1zm8 3.4v5.7l4.6-2.85z"/></svg>
<span>Presentación</span>
</button>
<span class="tb-separador tb-sep-sec" aria-hidden="true"></span>
<!-- «⋯»: en ventana estrecha agrupa las acciones secundarias -->
<button id="btn-mas" class="tb-btn tb-btn-icono" type="button" aria-label="Más acciones" aria-expanded="false" aria-controls="tb-menu" title="Más acciones">
<svg viewBox="0 0 24 24" width="17" height="17" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.9"/><circle cx="12" cy="12" r="1.9"/><circle cx="19" cy="12" r="1.9"/></svg>
<button id="btn-tema" class="tb-btn tb-btn-icono" type="button" title="Alternar tema claro / oscuro (T)" aria-label="Tema oscuro" aria-pressed="false">
<svg viewBox="0 0 24 24" width="17" height="17" fill="currentColor" aria-hidden="true"><path d="M12 2.6a9.4 9.4 0 1 0 0 18.8 9.4 9.4 0 0 0 0-18.8zm0 16.9V4.5a7.5 7.5 0 0 1 0 15z"/></svg>
</button>
<span class="tb-separador tb-sep-sec" aria-hidden="true"></span>
<!-- Acciones secundarias: en línea en escritorio; en ventana estrecha
forman el menú «⋯». «Volver al ejemplo» (destructiva) vive siempre
dentro del menú «⋯», al final y con estilo de peligro. -->
<div id="tb-menu" class="tb-grupo-sec">
<button id="btn-demos" class="tb-btn" type="button" title="Nueva demo: escenarios por industria y demos guardadas (N)">
<svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3.5" y="3.5" width="7" height="7" rx="1.6"/><rect x="13.5" y="3.5" width="7" height="7" rx="1.6"/><rect x="3.5" y="13.5" width="7" height="7" rx="1.6"/><path d="M17 14v6M14 17h6"/></svg>
<span>Demos</span>
</button>
<button id="btn-exportar" class="tb-btn" type="button" title="Exportar la demo a JSON (Ctrl+S)">
<svg viewBox="0 0 24 24" width="17" height="17" fill="currentColor" aria-hidden="true"><path d="M12 3.2c.5 0 .9.4.9.9v8.2l2.7-2.7a.9.9 0 1 1 1.3 1.3l-4.2 4.2a.9.9 0 0 1-1.3 0L7.2 11a.9.9 0 1 1 1.3-1.3l2.7 2.7V4.1c0-.5.4-.9.9-.9zM4.9 18.5h14.2a.9.9 0 1 1 0 1.8H4.9a.9.9 0 1 1 0-1.8z"/></svg>
<span>Exportar</span>
@@ -71,15 +74,19 @@
<span>Importar</span>
</button>
<input type="file" id="importar-archivo" accept="application/json,.json" hidden>
<button id="btn-reset" class="tb-btn" type="button" title="Restablecer la demo de ejemplo (pide confirmación)">
<svg viewBox="0 0 24 24" width="17" height="17" fill="currentColor" aria-hidden="true"><path d="M12 5V2.8a.7.7 0 0 0-1.13-.55L6.9 5.2a.7.7 0 0 0 0 1.1l3.97 2.95A.7.7 0 0 0 12 8.7V6.5a5.5 5.5 0 1 1-5.5 5.5H4.75A7.25 7.25 0 1 0 12 5z"/></svg>
<span>Restablecer</span>
</button>
<button id="btn-atajos" class="tb-btn tb-btn-icono" type="button" title="Atajos de teclado (?)" aria-label="Atajos de teclado">
<svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="2.5" y="6" width="19" height="12" rx="2.2"/><path d="M6 10h.01M10 10h.01M14 10h.01M18 10h.01M7.5 14h9"/></svg>
<span class="tb-solo-menu">Atajos</span>
</button>
<span class="tb-menu-sep" aria-hidden="true"></span>
<button id="btn-reset" class="tb-btn tb-btn-peligro" type="button" title="Sustituye la demo actual por el ejemplo Café Aurora (pide confirmación y se puede deshacer)">
<svg viewBox="0 0 24 24" width="17" height="17" fill="currentColor" aria-hidden="true"><path d="M12 5V2.8a.7.7 0 0 0-1.13-.55L6.9 5.2a.7.7 0 0 0 0 1.1l3.97 2.95A.7.7 0 0 0 12 8.7V6.5a5.5 5.5 0 1 1-5.5 5.5H4.75A7.25 7.25 0 1 0 12 5z"/></svg>
<span>Volver al ejemplo Café Aurora</span>
</button>
</div>
<button id="btn-mas" class="tb-btn tb-btn-icono" type="button" aria-label="Más acciones" aria-expanded="false" aria-controls="tb-menu" title="Más acciones">
<svg viewBox="0 0 24 24" width="17" height="17" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.9"/><circle cx="12" cy="12" r="1.9"/><circle cx="19" cy="12" r="1.9"/></svg>
</button>
</div>
</header>
@@ -103,19 +110,20 @@
<div class="wam-alta">
<!-- Paleta de los 13 tipos (la rellena js/editor.js): un clic AÑADE el mensaje.
El último tipo usado queda en #nuevo-tipo-valor (hidden) y en data-valor. -->
<div id="nuevo-tipo" class="ed-paleta" role="toolbar" aria-label="Añadir un mensaje: elige el tipo"></div>
<div id="nuevo-tipo" class="ed-paleta" role="toolbar" aria-label="Añadir un mensaje: cada tipo añade uno"></div>
<input type="hidden" id="nuevo-tipo-valor" value="text">
<div class="ed-alta-pie">
<span id="ed-destino-alta" class="ed-destino-alta" aria-live="polite"></span>
<button id="btn-anadir" class="wam-btn-anadir" type="button">+ Otro «Texto»</button>
<!-- «Repetir último»: aparece tras el primer alta de la sesión -->
<button id="btn-anadir" class="wam-btn-anadir" type="button" hidden>+ Otro «Texto»</button>
</div>
</div>
<div class="ed-lista-herr">
<div class="ed-lista-herr" id="ed-lista-herr">
<button type="button" class="ed-btn ed-btn-mini" data-acc="horas-secuencia" title="Reparte las horas desde la del primer mensaje, +1 min por mensaje">Horas en secuencia</button>
<button type="button" class="ed-btn ed-btn-mini" data-acc="plegar-todo">Plegar todo</button>
</div>
<!-- Una tarjeta colapsable por mensaje la pinta js/editor.js (C) -->
<div id="lista-mensajes"></div>
<div id="lista-mensajes" tabindex="-1" aria-label="Tarjetas de mensajes"></div>
</section>
<!-- Solo en ventana estrecha: salta a la vista previa del mensaje en edición -->
@@ -130,12 +138,19 @@
<div id="barra-movil">
<span class="barra-titulo">Vista previa</span>
<div class="barra-acciones">
<select id="sel-velocidad" title="Velocidad de la reproducción" aria-label="Velocidad de la reproducción">
<label class="barra-etq" for="sel-velocidad" title="Velocidad de la reproducción">
<svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><circle cx="12" cy="13" r="8"/><path d="M12 13V9M10 2.8h4"/></svg>
<span class="barra-etq-txt">Velocidad</span>
</label>
<select id="sel-velocidad" title="Velocidad de la reproducción">
<option value="0.5">0,5x</option>
<option value="1" selected>1x</option>
<option value="2">2x</option>
</select>
<button id="btn-reiniciar" type="button" title="Descartar lo pulsado y escrito en el teléfono y volver al guion">Reiniciar chat</button>
<button id="btn-reiniciar" type="button" title="Descarta lo pulsado y escrito en el teléfono y vuelve al guion desde el primer mensaje">
<svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3.5 12a8.5 8.5 0 1 0 2.6-6.1"/><path d="M3.5 4v4.5H8"/></svg>
<span>Repetir desde el inicio</span>
</button>
<button id="btn-reproducir" type="button" title="Reproducir la demo paso a paso (clic de nuevo para detener)">
<svg viewBox="0 0 24 24" width="15" height="15" fill="currentColor" aria-hidden="true"><path d="M8.4 5.6v12.8c0 .8.9 1.3 1.6.9l10-6.4c.6-.4.6-1.4 0-1.8l-10-6.4c-.7-.4-1.6.1-1.6.9z"/></svg>
<span>Reproducir demo</span>
@@ -199,7 +214,7 @@
</header>
<!-- Scroll de mensajes (estructura A · filas li.wa-row de B) -->
<ul id="chat-cuerpo" aria-live="polite"></ul>
<ul id="chat-cuerpo" aria-live="polite" tabindex="-1" aria-label="Conversación"></ul>
<!-- Indicador "escribiendo…" (estructura A · contenido y animación de B) -->
<div id="chat-escribiendo"></div>