Skip to main content

frontend-dashboard-patterns

Patrones completos para dashboards frontend vanilla JS: cliente API robusto, orquestación de carga, error boundaries, tabs con navegación, persistencia, fechas, colores, sparklines, Web Workers y debugging. Todo lo que necesitas para construir dashboards resilientes sin bundler.

الانتقال إلى التثبيت

معلومات المصدر

المستودع
Ntizar/NtizarBrainMasterMind
آخر نشاط في المصدر
١ يوليو ٢٠٢٦ في ٠٦:٥٥
لغة SKILL.md المكتشفة
الإسبانية
النجوم
٢
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
53 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
frontend-dashboard-patterns
description
Patrones completos para dashboards frontend vanilla JS: cliente API robusto, orquestación de carga, error boundaries, tabs con navegación, persistencia, fechas, colores, sparklines, Web Workers y debugging. Todo lo que necesitas para construir dashboards resilientes sin bundler.
version
1.5.0
author
Hermes Agent
tags
["frontend","dashboard","patterns","vanilla-js","resilience","geodatos","leaflet","choropleth"]
# Frontend Dashboard Patterns — Colección Completa Patrones reutilizables para dashboards frontend vanilla JS sin bundler. Inspirados en ESIOS Dashboard y Ntizar Aurora. ## Tabla de Contenidos 1. [Cliente API Robusto](#1-cliente-api-robusto) — reintentos, circuit breaker, timeouts 2. [Orquestación de Carga](#2-orquestación-de-carga) — Promise.allSettled, anti-doble-carga, cache fallback 3. [Error Boundaries](#3-error-boundaries) — overlay global, errores por sección, retry 4. [Tabs con Navegación](#4-tabs-con-navegación) — hash navigation, lazy-loading, deep-linking 5. [Persistencia de Estado](#5-persistencia-de-estado) — localStorage con validación, expiración, corrupción 6. [Manejo de Fechas](#6-manejo-de-fechas) — UTC→local, zonas horarias, DST 7. [Sistema de Colores](#7-sistema-de-colores) — tokens CSS, modo oscuro, variables semánticas 8. [Sparklines con Plotly](#8-sparklines-con-plotly) — mini gráficos inline optimizados 9. [Web Workers + Comlink](#9-web-workers--comlink) — cálculos pesados sin bloquear UI 10. [Debugging Patterns](#10-debugging-patterns) — scope, lifecycle, DOM integrity, paréntesis desbalanceados, checklist página en blanco 11. [Aurora Design System](#11-aurora-design-system) — CSS puro, 11 packs opt-in, namespaced .nz, 5 skins 12. [Geodatos Choropleth](#12-geodatos-choropleth) — Leaflet + Canvas, TopoJSON, lazy loading geodatos 13. [GTFS Browser Parser](#13-gtfs-browser-parser) — parsing GTFS en navegador sin servidor 14. [Three.js 3D Scenes](#14-threejs-3d-scenes) — escenas 3D interactivas con texturas procedurales, partículas con identidad, zoom a partícula individual, raycasting, labels flotantes, WebSocket sync, deep linking 15. [Three.js Escenarios JSON](references/threejs-scenario-loading.md) — patrón para cargar escenarios desde JSON con validación de schema, normalización y conversión de parámetros a wave params del shader 16. [ESLint v10 Flat Config](#16-eslint-v10-flat-config) — flat config, globals, ignores 17. [Vite HTML Script Processing](#17-vite-html-script-processing) — IIFEs, post-build, rutas relativas 18. [Full-Stack SPA Audit Pattern](#18-full-stack-spa-audit-pattern) — auditar SPA con backend + frontend (Express + vanilla JS) 19. [Toast Notifications](#19-toast-notifications) — sistema de feedback UX con queue, animaciones y auto-dismiss 20. [Conservative Vanilla JS Modernization](#20-conservative-vanilla-js-modernization) — refactorizar ES5→ES6 en 6 fases sin frameworks, sin romper nada 21. [Data Integrity & Graceful Degradation](#21-data-integrity--graceful-degradation) — nunca inventar datos, fallback chains, empty states honestos, limitaciones de contenedores 22. [Hero Redesign Pattern](references/hero-redesign-pattern.md) — primera pantalla con datos reales + acciones rápidas, no hero vacío 23. [NaN Deploy Cache Pattern](references/nan-deploy-cache-pattern.md) — verificación de deploy, cache de Cloudflare, debugging "no cargan datos" 24. [switchTab Pattern — onclick + event listener](references/switchtab-pattern.md) — función switchTab para onclick inline + event listener, hero placement, quick panel en tab correcta 25. [Tab System con Sidebar](references/tab-system-sidebar-pattern.md) — Sistema completo de tabs con sidebar de navegación, hero, lazy-loading, persistencia de estado y toast notifications 25. [Vanilla JS SPA Module Extension](#25-vanilla-js-spa-module-extension) — añadir nuevos módulos a un dashboard SPA existente 26. [Single-File SPA con Aurora](#26-single-file-spa-con-aurora) — patrón completo de dashboard en un solo HTML: sidebar + tabs + hero + lazy-loading + localStorage + toasts. Base para proyectos como ContrataPúblico. 27. [Single-File SPA con datos grandes](#27-single-file-spa-con-datos-grandes) — patrón para embeber datasets grandes (JSON de cientos de KB) en SPAs de un solo archivo sin romper el deploy. 28. [Debugging `typeof LEY_DATA === 'undefined'`](references/single-file-spa-large-data.md) — checklist de 4 causas: `</script>` collision, strings con newlines, Content-Type, CSP. 29. [Migración Completa a Aurora](references/aurora-migration-pattern.md) — patrón de 5 fases para migrar un HTML existente con CSS custom propio al Aurora Design System (auditoría → packs → componentes → CSS mínimo → JS dinámico). Incluye mapeo de componentes, pitfalls de mesh/orbs/gradientes, y métricas objetivo. 30. [Three.js Particle Systems](#30-threejs-particle-systems) — sistemas de partículas con Three.js: pool reciclado, shaders custom, espuma, spray, humo, fuego. Partículas con vida limitada, tamaño variable, blending additive. --- ## 1. Cliente API Robusto Clase `ApiClient` con reintentos exponenciales (backoff + jitter), circuit breaker por endpoint, timeouts por operación, y clasificación de errores HTTP. **Reglas clave:** - No reintentar 4xx (excepto 429) - Circuit breaker: N fallos → abrir circuito T segundos → half-open → cerrar/reabrir - Timeout por request con AbortController - Integrar con `Promise.allSettled` para carga paralela tolerante a fallos **Ver:** `references/api-client-pattern.md` para código completo. --- ## 2. Orquestación de Carga Clase `DataOrchestrator` para cargar múltiples endpoints en paralelo con: - Anti-doble-carga (mínimo 3s entre cargas) - Estados de loading por sección - Fallback a datos cacheados - `Promise.allSettled` para tolerancia parcial **Ver:** `references/orquestacion-carga-pattern.md` para código completo. --- ## 3. Error Boundaries Patrón de resiliencia: - Overlay global cuando todo falla (network, 5xx) - Errores por sección para fallos parciales - `safeRender()` wrapper para que un error de render no rompa el resto - Timeout en servidor con `withTimeout()` wrapper - Clasificación de errores: 404, 502, 503, network, timeout → mensajes distintos **Ver:** `references/error-boundaries-pattern.md` para código completo. --- ## 4. Tabs con Navegación Clase `TabController` para: - Navegación por hash (`#demanda`) con deep-linking - Lazy-loading de contenido - Persistencia de última tab en localStorage - Navegación por teclado (ArrowLeft/ArrowRight) - Accesibilidad: `role="tab"`, `aria-selected` **Ver:** `references/tabs-navigation-pattern.md` para código completo. --- ## 5. Persistencia de Estado Clase `PersistStore` para localStorage con: - Validación de integridad al leer - Expiración automática (TTL configurable) - Control de tamaño (truncar arrays si exceden límite) - Manejo de `QuotaExceededError` - Recuperación ante datos corruptos - Opcional: `HybridStore` con sessionStorage + localStorage **Ver:** `references/persistence-pattern.md` para código completo. --- ## 6. Manejo de Fechas Patrones para fechas consistentes: - **NUNCA usar `new Date('YYYY-MM-DD')`** → se interpreta como UTC - Usar `new Date(year, month, day)` para fechas locales - `toLocaleString('es-ES')` para formateo con zona horaria del navegador - Detección de DST con `Intl.DateTimeFormat().resolvedOptions().timeZone` - Normalización de inputs de fecha - **Hora por defecto en `<input type="time">`**: siempre rellenar con la hora actual de la zona horaria del usuario, no dejar vacío: ```javascript el.value = new Date().toLocaleTimeString('es-ES', { hour:'2-digit', minute:'2-digit', timeZone:'Europe/Madrid', hour12:false }); ``` **Ver:** `references/dates-timezone-pattern.md` para código completo. ### 6.2 Retroactive Date Entry — Registro en días pasados Patrón para formularios de registro que permitan al usuario elegir **cualquier fecha**, no solo hoy. Necesario en apps de seguimiento (dieta, fitness, hábitos) donde el usuario puede olvidar registrar un día y necesita retroceder la fecha. **Implementación resumida (ver reference para código completo):** 1. **HTML** — añadir `<input type="date">` a cada tarjeta de registro, pre-rellenado con `today()` (helper `new Date().toLocaleDateString('sv-SE')`) 2. **Orden UX** — input date va **primero** en el layout (antes del valor), para que el usuario cambie primero el día 3. **JS** — la función de registro lee `inputFecha.value || ''` y lo pasa en el body del fetch 4. **Edición estimada** — añadir también input date en la caja de edición (comida y ejercicio estimados) 5. **Backend** — patrón `fecha || hoy()`: aceptar `fecha` opcional, usarla si viene, fallback a hoy si no 6. **UPSERT** — para tablas con lógica upsert por día (ej: pasos), usar la fecha recibida en el lookup, no `hoy()` ```javascript // Backend — patrón clave const { fecha, ... } = req.body; sql_run('INSERT INTO ... fecha VALUES ?', [req.userId, fecha || hoy(), ...]); // UPSERT — lookup con la fecha recibida const f = fecha || hoy(); const existing = sql_get('SELECT id FROM pasos WHERE usuario_id = ? AND fecha = ?', [req.userId, f]); ``` **Pitfalls específicos:** - El helper `today()` debe estar definido ANTES de construir los HTML templates. Ponerlo al inicio del script. - `sv-SE` locale es el que entienden los inputs `date` nativos. `toISOString().slice(0,10)` también funciona pero puede tener offset UTC. - La clave de todo el patrón es el backend con `fecha || hoy()` — sin eso, clientes viejos que no envían `fecha` se rompen. - Para pasos (UPSERT por día): si no se usa `f` en el `SELECT`, los pasos de ayer se actualizarían sobre los de hoy. **Ver:** `references/retroactive-date-entry.md` para código completo con todos los formularios, estimaciones editables y server-side. --- ## 7. Sistema de Colores Patrón de diseño centralizado: - Variables CSS semánticas (`--color-success`, `--color-danger`) - Variables de gráfico fijas (`--color-chart-1`...) para consistencia - Modo oscuro con `[data-theme="dark"]` - Toggle con localStorage + `prefers-color-scheme` fallback - Un solo archivo de configuración → cambios globales en un lugar **Ver:** `references/color-system-pattern.md` para código completo. --- ## 8. Sparklines con Plotly Mini gráficos inline optimizados: - Reducir datos a 50 puntos máx. antes de renderizar - Sin hover, sin ejes, sin leyenda → rendimiento máximo - `Plotly.purge()` al destruir para liberar memoria - Color condicional (verde si sube, rojo si baja) - Punto final destacado con marker más grande **Ver:** `references/sparklines-pattern.md` para código completo. --- ## 9. Web Workers + Comlink Cálculos pesados sin bloquear UI: - Spatial hashing para ray-casting eficiente - Precomputación + cache - `Comlink.transfer()` para arrays grandes (ArrayBuffer) - `visitToken` vs `Set` para evitar allocation por frame - Batch calculations para terrazas grandes **Ver:** `references/web-workers-pattern.md` para código completo. --- ### 🔥 REGEX-based removal de bloques de código es INFIABLE **2026-06-13 (MasterFit dieta):** Intenté eliminar código de dark mode con `re.sub` y un patrón regex que buscaba desde un comentario hasta `})();`. El regex eliminó el botón HTML pero **dejó fragmentos del IIFE abierto** (bloque `try { localStorage.getItem(DARK_MODE_KEY) ... } catch(e) {}`), lo que rompió la ejecución JS. `loadData()` quedó definida pero nunca llamada porque el bloque IIFE abierto cortaba el script. **Síntomas:** - HTML carga, CSS aplica, pero `typeof loadData === 'undefined'` - No hay errores en consola (el parser JS no falla, solo las funciones después del bloque roto no se definen) - Los datos existen en `database.json` pero no se muestran - Hero vacío, botones de navegación sin efecto **Causa:** Los bloques IIFE con `try { ... } catch(e) {}` anidados son difíciles de delimitar con regex. `re.sub(r'from_comment_to_closing', '', content)` deja fragmentos huérfanos que el parser JS ignora pero que cortan la ejecución. **Fix seguro — 3 pasos:** 1. **Identificar el bloque completo** — buscar el comentario que inicia (`// === DARK MODE TOGGLE ===`) y el cierre (`})();`) 2. **Eliminar con `content[:start] + content[end:]`** — NO usar `re.sub` 3. **Verificar que no queda ningún fragmento** — grep por `DARK_MODE_KEY`, `darkModeToggle`, `toggleDarkMode`, `nz-btn--secondary`, `mf-dark`, `data-nz-theme` **Regla:** Cuando elimines bloques de código, SIEMPRE verifica que no quedan fragmentos huérfanos. Los fragmentos de JS sueltos son bugs silenciosos: el parser no falla, pero las funciones después del fragmento no se definen. **Pitfall adicional:** Después de eliminar bloques grandes con `content[:start] + content[end:]`, verificar que el archivo no se truncó. Un archivo HTML de 120KB que queda en 28KB está **truncado** — se perdió todo el JS y la mayor parte del HTML. Siempre verificar `</html>` y `</body>` están presentes. **Verificación post-fix:** ```python with open('dashboard.html', 'r') as f: content = f.read() for term in ['darkModeToggle', 'DARK_MODE_KEY', 'toggleDarkMode', 'nz-btn--secondary', 'mf-dark', 'data-nz-theme']: if term in content: print(f"⚠️ {term} aún presente") # Verificar integridad del archivo assert '</html>' in content, "Archivo truncado — falta </html>" assert '</body>' in content, "Archivo truncado — falta </body>" assert 'function loadData()' in content, "loadData() eliminada" assert 'function renderDashboard' in content, "renderDashboard eliminada" ``` --- ### 🔥 Hero vacío en primera pantalla — UX crítica **2026-06-13 (MasterFit dieta):** El hero solo mostraba branding ("MasterFit", "Objetivo: 88 kg", avatar) sin ningún dato ni acción. El usuario dice "no se ve información relevante" — la primera pantalla DEBE mostrar: 1. **Datos reales** — peso actual, kg perdidos, ritmo semanal (o "sin datos" si no hay) 2. **Acciones rápidas** — botones para "Registrar" y "Hablar con IA" (las 2 acciones principales) **Patrón de hero correcto:** ```html <section class="nz-hero nz-hero--centered"> <div class="nz-hero__inner"> <div class="nz-hero__eyebrow">Dashboard de seguimiento</div> <h1 class="nz-hero__title nz-gradient-text">🏋️ MasterFit</h1> <p class="nz-hero__sub">Objetivo: <strong>88 kg</strong></p> <!-- Quick Status con datos reales --> <div id="heroQuickStatus"> <div class="nz-surface nz-surface--glass-soft"> <div>⚖️ Peso</div> <div id="heroPeso">--</div> </div> <div class="nz-surface nz-surface--glass-soft"> <div>📉 Perdido</div> <div id="heroPerdido">--</div> </div> <div class="nz-surface nz-surface--glass-soft"> <div>🔥 Ritmo</div> <div id="heroRitmo">--</div> </div> </div> <!-- Acciones rápidas --> <div class="nz-hero__cta"> <a class="nz-btn nz-btn--glass-liquid-brand" onclick="switchTab('registrar')">➕ Registrar</a> <a class="nz-btn nz-btn--glass-liquid-accent" onclick="switchTab('ia')">🤖 Hablar con IA</a> </div> </div> </section> ```
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub