Mapas de calor
Componentes: CalendarHeatmap y MatrixHeatmap en src/components/ui/heatmap.tsx. Estilos .sgd-heat* en src/app/globals.css. Demostración con datos de ejemplo en /design-system/componentes (solo desarrollo, heatmap-showcase.tsx). Todavía no están en el dashboard ni conectados al backend.
Cuándo usarlos
- Calendario de actividad: cuánto hubo cada día del año (documentos emitidos, recibidos o atendidos). Una columna por semana, una fila por día (lunes a domingo). Sirve para ver ritmo de trabajo, picos y días sin movimiento.
- Matriz: cruza dos categorías (persona u oficina por semana; tipo de documento por oficina; oficina por antigüedad de pendientes). Sirve para comparar y encontrar dónde mirar.
- No usarlos para valores exactos que haya que leer con precisión: para eso, tabla. El mapa de calor responde «dónde está lo anormal»; la tabla, «cuánto exactamente».
Quién ve qué (alcance por rol)
| Rol | Ve | Filas de la matriz |
|---|---|---|
| Trabajador | Solo sus propias métricas | Una sola fila (él) |
| Jefatura | Las suyas, las de toda su oficina y las de cada persona de su oficina (por persona) | Una fila por persona de su oficina; con «Por persona», solo esa persona |
| Alta dirección | Todas las oficinas o una oficina concreta (y su personal), para decidir | Una fila por oficina; con «Por oficina», una fila por persona de esa oficina |
El alcance lo decide el servidor según el permiso del usuario (report:read_own, report:read_office y uno institucional por definir). El cliente nunca elige qué datos recibe; los selectores «Rol» y «Ver» de la demo existen solo para mostrar las tres vistas. Una jefatura alterna entre «Mis métricas», «Mi oficina» y «Por persona» (nunca ve otras oficinas); la alta dirección alterna entre «Todas las oficinas» y «Por oficina»; un trabajador no tiene ese control. Bajada de nivel: un clic (o Enter) en una fila baja al nivel siguiente (oficina → persona en la jefatura; oficina → su personal en la alta dirección), equivalente a elegirla en el selector. Las celdas del trabajador no son accionables.
Uso para decidir (alta dirección y jefaturas)
- Cada matriz responde una pregunta que termina en una decisión: a qué oficina reforzar (pendientes por antigüedad), qué trámite rediseñar (días promedio por tipo), dónde pedir explicaciones (pendientes de más de 10 días).
- Medidas «malas» (retraso, pendientes) con
tone="destructive"; medidas neutras (volumen) con el tono primario; medidas «buenas» o de logro (ahorro, impacto ambiental) contone="success". No mezclar tonos en una misma pantalla sin leyenda. - Si el dashboard muestra un umbral (plazo en días hábiles), el umbral debe venir del backend o de la norma, no de una constante de pantalla.
- La celda debe llevar a algo:
onSelectabre el detalle (bandeja filtrada por fecha, oficina o antigüedad). Un mapa sin salida solo informa.
Impacto ambiental
Demo en heatmap-environment-showcase.tsx: el ahorro de papel y de CO₂ se calcula a partir de los documentos digitales (como la pestaña actual del dashboard) y se reparte con tone="success": calendario por día y matriz oficina (o persona) por mes, con selector de métrica (hojas, kg de papel, CO₂). Mismo alcance por rol (heatmap-scope.tsx) y bajada de nivel por clic. Los factores son ilustrativos (5 hojas por documento, 5 g por hoja, 4,5 kg de CO₂ por kg de papel, 8 500 hojas por árbol): deben validarse y publicarse con su fuente antes de mostrarlos a la alta dirección. Idea pendiente que depende de datos: avance de adopción digital por oficina (documentos firmados digitalmente frente a impresos), solo si el sistema los distingue.
Accesibilidad
- Cuadrícula ARIA (
grid,row,rowheader,columnheader,gridcell) con nombre accesible obligatorio (label). - Un solo Tab entra a la cuadrícula; flechas recorren las celdas; Inicio/Fin saltan al extremo de la fila; Ctrl+Inicio/Fin a las esquinas; Enter o Espacio activan
onSelect. - Cada celda se lee completa: «2 de junio de 2026, martes: 181 documentos». Las celdas sin dato dicen «sin dato» y se ven rayadas.
- El color nunca es lo único: el valor está en el
aria-label, en el globo (mouse o foco) y, conshowValues, dentro de la celda. - El número dentro de la celda (negro o blanco) se elige por contraste real (WCAG 2.2 AA, 4,5:1) tras resolver los colores del tema activo; se recalcula al cambiar tema o modo.
- El globo con el valor aparece al instante (a diferencia de los tooltips de íconos, que esperan 1 s) y se oculta al salir, al perder el foco o al desplazar.
Colores
La escala sale del color primario del tema activo mezclado con la superficie vacía (--heat-empty), así que sigue los tres temas y el modo oscuro sin colores fijos. tone="destructive" usa --destructive y tone="success" usa --success. Los números se muestran como en el resto del sistema («47 350», «236,8») con formatHeatNumber. En el calendario hay cinco pasos (0 y cuatro niveles proporcionales al máximo); en la matriz la mezcla es continua entre el mínimo y el máximo.
No verificado todavía
Lector de pantalla real, Firefox y Safari, pantallas táctiles y grandes volúmenes (más de 365 celdas en el calendario o más de unas 40 filas en la matriz). Tampoco hay endpoint de agregados: hoy el backend solo tiene /reports/summary y los listados.