Reemplazar filter/backdrop-filter de Shine por tokens CSS dinámicos
Contexto
Fecha: 06-08-2026
Decisor: Edu (con Claude Code)
Impacto: Frontend UI, rendimiento, arquitectura CSS
Issue relacionada: #211 (Iniciativa UI — migración a tokens)
La característica Shine (aclarado/brillo de la interfaz) se implementó originalmente en v1.66.0+ usando un overlay <div> con backdrop-filter: brightness(…). Post-deploy, Edu reportó un problema grave: Shine hundía el rendimiento cuando el fondo animado (Asteroids) estaba activo.
Problema observado
-
Framerate collapse: Con
backdrop-filteractivo, el navegador re-calculaba el área filtrada en cada frame del fondo animado (120+ FPS). En laptops/tablets de gama media, caía a 20-30 FPS. -
Deformación del fondo: El overlay overlay con
filterse vuelve containing block de todo elementoposition:fixed(spec CSS Filter Effects). El fondo Asteroids, medido contra el documento entero en lugar del viewport, se reescalaba y deformaba. -
Incapacidad de revert rápido: No había forma de desactivar Shine sin un cambio de versión; el impacto era del lado del usuario final (no era un bug visible sin tener Shine activado).
Opciones consideradas
Opción A: Optimizar el backdrop-filter (rechazada)
backdrop-filter: brightness(1.1)conwill-change→ rendimiento aún malo- Mover el overlay a un z-index intermedio → no soluciona
position:fixed - Rechazo: La spec CSS hace que
filtersiempre sea un containing block. No es optimizable.
Opción B: Usar SVG filter (rechazada)
- Más eficiente que CSS filter en algunos navegadores
- Aún re-calcula en cada frame
- Complejidad adicional sin resolver el problema de anclaje
- Rechazo: Similar rendimiento, complejidad innecesaria
Opción C: Tokens CSS dinámicos (ELEGIDA ✅)
document.documentElement.dataset.shine = "1" | "2"- CSS con selectores
:root[data-shine="1"]redefine ~9 tokens:--bg-color,--card-bg,--border-color,--text-secondary, etc. - Coste: ~0ms (solo CSS variables, sin repaint forzado)
- Perjuicio: Cobertura inicial ~70% (solo superficies ya tokenizadas)
Decisión tomada
Migrar Shine a tokens CSS dinámicos. Aceptar cobertura parcial inicial.
Justificación
- Rendimiento: Cero overhead. La animación del fondo permanece fluida.
- Anclaje:
position:fixedno se afecta (no hayfilteren un ancestor) - Sostenibilidad: Alienta la migración completa a tokens (Iniciativa UI #211). Cada hex que se tokeniza = Shine llega allá
- Reversibilidad: Fácil de cambiar (solo CSS + atributo DOM)
Compromisos
- Cobertura inicial limitada: ~70-80% de superficies responden a Shine. El ~20-30% restante (valores hex heredados) no brillan hasta que se tokenicen.
- “Patchiness” visual: Algunos paneles heredados pueden verse desemparejados en Shine nivel 2. Aceptable porque:
- Es obvio dónde aún quedan hex legacy
- Motiva la adopción de tokens
- No es una regresión (antes tenían Shine incorrectamente aplicado via filter, ahora tienen la versión correcta que escalará)
Implementación
Archivos modificados:
static/js/base.js— funciónapplyShine(level, idx)cambia de overlay + filter a dataset.shinestatic/css/variables.css— añade selectores:root[data-shine="1"]y:root[data-shine="2"]con overrides de ~9 tokens
Versión: v1.66.3
Riesgos mitigados
| Riesgo | Mitigación |
|---|---|
| Usuarios ven Shine incompleto | ✅ Documentado en RELEASE_NOTES; explicación de cobertura |
| Cambio introduce nuevos bugs | ✅ Lógica simple (CSS vars + dataset); no hay cálculos |
| Es difícil debuggear Shine | ✅ Inspeccionable en DevTools: $0.dataset.shine |
Seguimiento
- ✅ Validación post-deploy: Edu hizo click-test manual (JS/CSS sin CI). Brillo fluido,
position:fixedcorrecto. - 🔄 Roadmap: Cada migración de hex → token en #211 incrementa la cobertura de Shine automáticamente.
- 📊 Métrica: Monitorear % de tokens vs. hex en
variables.cssy plantillas.
Véase también
- [[feature—ui—shine-tokens-v1663]]
- [[concept—crearack-tech—design-system]]
- [[concept—crearack-tech—performance]]
- [[feature—ui—iniciativa-ui-fase-2]]
- [[entity—static—css—shine-tokens]]