CreaRack-SL

ADR: Toggle "Tamaño global" — override de variables --text-* de Tailwind v4 en scope body (s56 round 3)

Contexto

El panel de preferencias de usuario (/prefs) expone un toggle “Tamaño global” con cuatro niveles (sm | md | lg | xl). El objetivo es que el usuario pueda ampliar o reducir la tipografía de la aplicación sin alterar el espaciado, los tamaños de layout ni los márgenes.

La implementación correcta requirió tres iteraciones en la sesión s56 (11-05-2026) antes de llegar a un diseño estable.


Problema original

Tailwind v4 genera sus utility classes text-xs, text-sm, text-base, text-lg, text-xl usando custom properties CSS internas (--text-xs, --text-sm, etc.) que no dependen del font-size del <body> sino del root <html>. Adicionalmente, padding, gap, margin y width/height también se expresan en rem, calculados desde html { font-size }.


Iteraciones (historial)

Round 1 — solo body[data-font-size]

body[data-font-size="sm"] { font-size: 0.85rem; }

Resultado: no funcionaba. Las utility classes Tailwind usaban rem desde <html>, ignorando el font-size del <body>. Los componentes Tasks, Notes, KanbanMini no escalaban.

Round 2 — html[data-font-size] + body[data-font-size]

html[data-font-size="sm"] { font-size: 13.5px; }
body[data-font-size="sm"] { font-size: 0.85rem; }

prefs.ts:applyPrefsToBody también aplicaba el atributo al <html>.

Resultado: funcionaba para tipografía, pero todo lo expresado en rem escalaba (padding, gap, border-radius, iconos, layouts) → el toggle se convertía en un zoom de página completo, no en un toggle tipográfico.

Round 3 — override de --text-* en scope body ✅ (solución definitiva)

Se revirtió el setAttribute sobre <html> en prefs.ts. Solo el <body> recibe data-font-size. En globals.css se sobreescriben las custom properties que Tailwind usa internamente para las utility classes de texto:

body[data-font-size="sm"] {
  --text-xs:   0.7rem;
  --text-sm:   0.8125rem;
  --text-base: 0.9375rem;
  --text-lg:   1.05rem;
  --text-xl:   1.2rem;
  font-size: 0.85rem;   /* legado — componentes sin class Tailwind */
}
/* ídem para md (defaults Tailwind), lg y xl */

Resultado: las utility classes text-sm, text-base, etc. recogen el override. padding, gap y demás rem permanecen invariantes porque el font-size del <html> no cambia.


Decisión adoptada

No modificar nunca el font-size del elemento <html> para cambiar el tamaño tipográfico de preferencias. Hacerlo actúa como un zoom de página completo porque Tailwind v4 usa rem para todo el sistema de espaciado.

La técnica correcta es redefinir las custom properties --text-* dentro del scope body[data-font-size="<nivel>"].

Consecuencia: los literales rem no responden

Componentes que usen fontSize: '0.875rem' como literal hardcoded (inline style) no responden al toggle. Para que un componente responda al toggle de tamaño, debe usar fontSize: 'var(--text-sm)' (o la utility class Tailwind equivalente).

Como parte de este fix se migraron los literales de KanbanMini.tsx:

AntesDespués
'0.875rem''var(--text-sm)'
'0.84rem''var(--text-sm)'
'0.97rem''var(--text-base)'
'0.94rem''var(--text-base)'

Archivos clave

ArchivoRol
src/lib/prefs.ts → applyPrefsToBody()Aplica data-font-size solo al <body>, NO al <html>
src/styles/globals.css → sección FONT SIZEDefine los cuatro bloques body[data-font-size="*"] con override de --text-*
src/components/widgets/KanbanMini.tsxEjemplo de componente migrado a var(--text-*)

Regla de desarrollo

Cualquier nuevo componente que deba respetar el toggle “Tamaño global” debe usar var(--text-xs|sm|base|lg|xl) en sus estilos inline, o la utility class Tailwind equivalente (text-sm, text-base…). Nunca valores rem literales.


Véase también

  • [[crearack—conceptos—interfaz-general]]
  • [[workspace—que-es-workspace]]