CreaRack-SL

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

  1. Framerate collapse: Con backdrop-filter activo, 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.

  2. Deformación del fondo: El overlay overlay con filter se vuelve containing block de todo elemento position:fixed (spec CSS Filter Effects). El fondo Asteroids, medido contra el documento entero en lugar del viewport, se reescalaba y deformaba.

  3. 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) con will-change → rendimiento aún malo
  • Mover el overlay a un z-index intermedio → no soluciona position:fixed
  • Rechazo: La spec CSS hace que filter siempre 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:fixed no se afecta (no hay filter en 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:
    1. Es obvio dónde aún quedan hex legacy
    2. Motiva la adopción de tokens
    3. 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ón applyShine(level, idx) cambia de overlay + filter a dataset.shine
  • static/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

RiesgoMitigació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:fixed correcto.
  • 🔄 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.css y 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]]