Callouts de documentación que no te traicionan: variables CSS, modo oscuro y disciplina operativa

¿Te fue útil?

Lanzas un rediseño de la documentación un viernes. El lunes, tu rotación on-call está leyendo un cuadro “PELIGRO” que en modo oscuro parece un CONSEJO amistoso, y alguien pega un token de producción en el lugar equivocado. Eso no es “solo CSS”. Es un incidente operativo con una tipografía elegante.

Los callouts (NOTA/CONSEJO/ADVERTENCIA/PELIGRO) son pequeños componentes de UI con consecuencias desproporcionadas. Comprimen riesgo en un color, un borde y unas pocas palabras. Si tu tematización es descuidada, entrenas a los usuarios para ignorar los recuadros —y luego te preguntas por qué no se sigue el runbook.

Qué hacen realmente los callouts (y por qué a operaciones le debería importar)

En la documentación, las admoniciones son el equivalente en UI a las barandillas de seguridad. No son decoración; son superficies de control. Una NOTA dice “no te sorprendas”. Un CONSEJO dice “haz esto para ir más rápido”. Una ADVERTENCIA dice “puedes hacerte daño”. Un PELIGRO dice “puedes dañar a los demás”.

Esa es la intención. La realidad es más fea: la mayoría de los callouts se implementan como una extensión de Markdown que mapea a una clase CSS, luego se tematizan según lo que estuviera en el sistema de diseño esa semana. En modo claro se ven bien; en modo oscuro se vuelven una masa de bajo contraste o, peor, se invierte la jerarquía de severidad. Los usuarios dejan de confiar en lo visual y leen por encima del texto. Cuando la gente no confía en la interfaz, hace lo que hacen los operadores cansados: adivinan.

ADVERTENCIA

Si tus estados ADVERTENCIA y PELIGRO no son claramente distinguibles en modo oscuro, estás ejecutando un bug de fiabilidad de documentación. Trátalo como tal.

Las variables CSS (propiedades personalizadas) son la mejor herramienta que tenemos para hacer los callouts consistentes entre marcos, páginas y modos. No porque sean tendencia, sino porque te ofrecen:

  • Un lugar para definir significado (tokens), muchos lugares para consumirlo (componentes).
  • Cambio en tiempo de ejecución (modo oscuro, alto contraste) sin recompilar CSS.
  • Fallbacks seguros cuando falta un token o lo sobreescribe algún paquete de tema “útil”.

Hay una mentalidad de fiabilidad aquí: tu UI de documentación debe degradarse de forma segura. Si falta una variable, quieres un valor por defecto aburrido, no un borde invisible y texto gris sobre gris.

NOTA

“La documentación es estática.” Vale. También lo son los mensajes de error en tu arreglo de almacenamiento—hasta que provocan una caída.

Una idea para tener presente: Idea parafraseada: “Todo falla; diseña para que falle de forma segura.” — atribuido al pensamiento sobre fiabilidad de John Allspaw

Chiste #1: El modo oscuro es como RAID—todo el mundo lo quiere, y alguien igual lo configurará mal.

Hechos e historia que puedes usar en reuniones

Esto no es trivia por el gusto de la trivia. Es munición para las conversaciones de “¿por qué invertimos tiempo en la tematización de callouts?”.

  1. El marcado de “admonición” antecede a la mayoría de herramientas modernas de docs. Sphinx popularizó directivas como .. note:: años antes de que las pilas modernas basadas en Markdown las normalizaran.
  2. Markdown con sabor a GitHub no estandarizó las admoniciones. Muchos ecosistemas implementaron su propia sintaxis, por eso la portabilidad sigue siendo un lío.
  3. Las propiedades personalizadas de CSS se adoptaron ampliamente en navegadores alrededor de 2017. Eso importa porque “no podemos fiarnos de variables” suele ser memoria institucional desactualizada.
  4. prefers-color-scheme se volvió práctico solo tras la adopción del modo oscuro a nivel de SO. Antes de eso, muchos sitios usaban un interruptor manual y hacks de persistencia por cookie.
  5. Los primeros temas oscuros a menudo invertían colores. La inversión rompe los colores semánticos: los amarillos de advertencia quedan ilegibles, los azules se vuelven neón y los grises se comportan raro. El theming moderno ajusta la luminancia, no solo el matiz.
  6. La guía WCAG sobre contraste trata de la legibilidad del texto, no del estilo de marca. “Se ve bien en mi MacBook” no es una estrategia de contraste.
  7. Los colores de callout tienen equipaje cultural. El rojo señala peligro en muchos lugares, pero no en todos. Por eso la iconografía y las etiquetas importan.
  8. Los design tokens surgieron de sistemas UI a gran escala multi-plataforma. El objetivo era coherencia en web/iOS/Android, no solo “CSS más limpio”.

Tokens de diseño con variables CSS: el enfoque sensato

Deja de pensar en los callouts como “un recuadro azul” o “un recuadro amarillo”. Piensa en tokens: acento, fondo, borde y, a veces, color del icono. Los tokens representan significado, no implementación.

Jerarquía de tokens que realmente quieres

Una jerarquía fiable previene “guerras de sobrescritura aleatoria”:

  • Tokens base globales: --bg, --fg, --border.
  • Tokens semánticos: --note-accent, --warn-bg, etc.
  • Tokens de componente: --callout-accent, --callout-border establecidos por la clase del componente.

Esto importa porque los componentes deberían consumir tokens semánticos, no valores hex crudos. Cuando cambias el color de advertencia una vez, todo el sitio debería actualizarse. El CSS de arriba hace exactamente eso al mapear .callout.warn a --warn-*.

CONSEJO

Mantén los nombres de los tokens aburridos. Si nombras un token --sunset-glow-500, terminarás enviando un PELIGRO “sunset”. Los usuarios estarán encantados hasta que borren el clúster equivocado.

Fallbacks: ¿qué ocurre cuando falta el token?

En sistemas de producción, planificas dependencias faltantes. Aquí igual. Usa fallbacks agresivamente:

  • border: 1px solid var(--callout-border, var(--border)); significa “si falta el borde del callout, usa el borde global”.
  • Nunca confíes solo en background para comunicar significado. Bordes y títulos sobreviven más colisiones de tema.
  • Haz que el texto de la etiqueta (“ADVERTENCIA”, “PELIGRO”) sea un elemento UI de primera clase, no un pseudo-elemento que se pierde con cambios de fuente.

Dónde deberían vivir los tokens

Pon los tokens lo más cerca posible de la raíz del documento (:root). Si tu framework scopea estilos, asegúrate de que los tokens sigan siendo accesibles globalmente, o scoped intencionalmente por área de docs. Mezclar modelos de scope es la forma de obtener callouts que se muestran distinto en la barra lateral y el contenido principal.

Severidad Tokens semánticos Consumo por componente Objetivo operativo
NOTA --note-accent, --note-bg, --note-border .callout.note establece --callout-* Informar, no distraer
CONSEJO --tip-accent, --tip-bg, --tip-border Mismo patrón Fomentar buenas prácticas
ADVERTENCIA --warn-accent, --warn-bg, --warn-border Mismo patrón Prevenir errores
PELIGRO --danger-accent, --danger-bg, --danger-border Mismo patrón Detener acciones inseguras

Modo oscuro sin mentiras visuales

El theming del modo oscuro no es “invertir y esperar”. Tus ojos se adaptan de forma distinta en baja luz, y los colores se comportan distinto sobre fondos casi negros. El modo de fallo principal: mantienes los mismos colores de acento pero bajas el fondo a una tinta de baja opacidad, y de repente la etiqueta es lo único legible. Los usuarios interpretan todo el recuadro como “prioridad baja” porque visualmente retrocede.

Usa color-scheme y deja que la plataforma ayude

Establece color-scheme: light dark en la raíz. Esto indica a controles de formulario y barras de desplazamiento que coincidan. También reduce la probabilidad de que un control nativo dentro de un callout parezca teletransportado desde 2009.

Elige una estrategia: tintar fondos, luego corregir bordes y texto

En modo oscuro, los fondos deberían generalmente tintarse (alpha baja) y los bordes deberían ser más fuertes de lo que crees. Los bordes definen la forma cuando todo lo demás es oscuro. Por eso el CSS de ejemplo usa:

  • --*-bg: rgba(...,.10) para rellenos suaves
  • --*-border: rgba(...,.35) para forma y señales de severidad
PELIGRO

Si tu PELIGRO en modo oscuro parece más tranquilo que tu NOTA en modo claro, tu escalera de severidad está invertida. Los usuarios seguirán la escalera que renderizas, no la que pretendías.

No confíes en tu monitor. Instrumenta tu tema.

Sí, debes hacer QA visual. Pero también debes tratar las variables CSS como configuración y verificarlas en CI. Si tu paquete de tema se actualiza y cambia silenciosamente --warn-accent, quieres un diff que falle la build, no una queja de un cliente de que “las cajas de advertencia se ven… tranquilas”.

Chiste #2: Lo único más oscuro que el modo oscuro es el alma de la persona que fusionó “arreglo rápido de contraste” directamente en main.

Patrones de implementación para admoniciones

Tu generador de docs puede ser Markdown, MDX, AsciiDoc, reStructuredText o algo internamente maldito. Los patrones abajo sobreviven el cambio de herramientas.

Patrón A: HTML semántico + clases

Renderiza las admoniciones como un elemento real con título. Evita pseudo-elementos para texto crítico; son frágiles para herramientas de accesibilidad y traducción.

cr0x@server:~$ cat ./callout-example.html
<div class="callout warn" role="note" aria-label="Warning callout">
  <div class="icon" aria-hidden="true"></div>
  <div>
    <div class="title">WARNING</div>
    <p>Do not run this command against production.</p>
  </div>
</div>

Decisión: si tu pipeline no puede emitir HTML semántico así, arregla el pipeline. El estilado es la parte fácil; la estructura fiable es la parte difícil.

Patrón B: atributos data para severidad

Cuando la documentación se genera desde contenido, los atributos data pueden reducir la proliferación de clases:

  • <aside class="callout" data-kind="warn">
  • CSS: .callout[data-kind="warn"] { ... }

Esto también facilita consultarlos en pruebas.

Patrón C: un componente callout, muchos temas

Si tienes múltiples productos o “espacios”, no bifurques el CSS del callout. Mantén un componente. Sobrescribe tokens por espacio.

Enfoque de ejemplo:

  • :root[data-space="storage"] { --note-accent: ... }
  • :root[data-space="compute"] { --note-accent: ... }

Operativamente, así evitas la espiral de tickets de soporte “ADVERTENCIA se ve diferente en producto A”.

Patrón D: soporte forced-color y alto contraste

El modo forced-colors de Windows ignorará tu paleta bonita. Bien. Quieres que el SO gane. Añade reglas mínimas:

  • @media (forced-colors: active) { .callout { border: 1px solid CanvasText; } }
  • Asegura que los títulos sigan visibles sin depender del fondo.

Accesibilidad: contraste, semántica y “no te fíes solo del color”

La accesibilidad no es un impuesto de cumplimiento; es cómo mantienes el significado intacto en condiciones hostiles: monitores baratos, luz solar intensa, modo migraña o alguien leyendo a las 03:00 en un portátil atenuado mientras atiende un incidente.

Contraste: prueba el texto, no la vibra

Para callouts, enfócate en:

  • Contraste del título contra el fondo del callout.
  • Contraste del texto del cuerpo contra el fondo del callout.
  • Visibilidad del borde contra el fondo de la página.

Una trampa común: cumples contraste en el título pero lo fallas en los enlaces dentro del callout porque el color de enlace es global. Por eso los tokens deben considerar también el contraste de los enlaces (o al menos evitar tintes de fondo ultra claros que los laven).

Semántica: mantiene la etiqueta y la severidad legibles por máquina

Usa una etiqueta visible y considera aria-label. Un lector de pantalla no debería tener que inferir que un borde es amarillo. Los humanos tampoco.

No codifiques la severidad solo por color

Usa al menos dos señales:

  • Texto de etiqueta: NOTA/CONSEJO/ADVERTENCIA/PELIGRO.
  • Forma del icono (aunque sea simple).
  • Grosor o patrón del borde (sutil pero útil).
NOTA

Si tus callouts solo se diferencian por matiz, estás construyendo una UI que falla la primera vez que alguien imprime la página o usa una pantalla de tinta electrónica en escala de grises.

Tres mini-historias corporativas desde las trincheras de la tematización

Mini-historia #1: un incidente causado por una suposición errónea

Una empresa mediana migró su documentación interna a un nuevo generador de sitios estáticos. Los responsables de contenido estaban felices: builds más rápidas, páginas más bonitas, un interruptor de modo oscuro. Liderazgo de ingeniería lo aprobó porque “es documentación, no producción”.

La migración incluyó admoniciones. El sistema antiguo rendereaba ADVERTENCIA y PELIGRO con iconos distintos y bordes muy diferenciados. El nuevo sistema usó el mismo icono para ambos, y el autor del tema asumió que el fondo tintado rojo sería “obviamente peligro”. En modo claro, en su mayoría lo era. En modo oscuro, los fondos eran tintes de baja opacidad y el fondo de página era casi negro que se tragaba la diferencia.

Un mes después, alguien siguió un runbook para rotar credenciales de una integración compartida. Había un callout PELIGRO: “Este paso invalida tokens para todos los entornos; coordinar.” En modo oscuro, parecía una advertencia leve, la persona asumió que era impacto local y procedió en solitario.

Resultado: múltiples servicios perdieron autenticación en minutos. El incidente no fue causado por un mal diseño de autenticación; fue causado por una suposición errónea sobre cómo una UI comunica riesgo. La corrección post-incidente no fue “entrenar a los ingenieros a leer mejor”. Fue: hacer cumplir la diferenciación de severidad vía tokens, añadir checks automáticos de contraste y requerir iconos únicos para ADVERTENCIA vs PELIGRO.

Mini-historia #2: una optimización que salió mal

Otra organización decidió que su bundle CSS era demasiado grande. Alguien propuso “optimizar” eliminando tokens semánticos y dejando que el pipeline incrustara hex directamente en el CSS de componente. Menos variables, menos bytes, páginas más rápidas. El panel de rendimiento mejoró un poco, que es cómo estas ideas se promueven.

Luego ocurrió un refresh de marca. El sistema de diseño actualizó colores de acento. La mayoría de los componentes adoptaron la nueva paleta porque usaban tokens. Pero las admoniciones ahora estaban hardcodeadas en CSS compilado. La mitad de las páginas tenían colores viejos y la otra mitad los nuevos. En modo oscuro, la nueva paleta funcionó; la antigua no. Los usuarios empezaron a reportar que las cajas ADVERTENCIA eran ilegibles—solo en ciertas secciones de la doc.

El equipo pasó días persiguiendo “problemas de cache” y “propagación del CDN”. La realidad fue más embarazosa: la optimización eliminó el punto único de verdad. La solución fue restaurar variables CSS, aceptar un archivo CSS ligeramente más grande y poner presupuestos reales: medir el tamaño del bundle, pero no micro-optimizar la mantenibilidad.

También aprendieron la lección dura: un CSS más pequeño no es “más rápido” si provoca más tiempo humano y más errores en producción. La latencia no se mide solo en milisegundos.

Mini-historia #3: una práctica aburrida pero correcta que salvó el día

Un equipo empresarial grande mantenía docs para una plataforma de almacenamiento con muchos comandos “puedes borrar todo”. Sus docs se trataban como parte del producto, lo que significaba que los cambios pasaban por CI con pruebas. No es llamativo. Muy efectivo.

Tenían una regla: los tokens para callouts viven en un archivo, y cada cambio a ese archivo dispara una ejecución de regresión visual más una prueba simple de “presencia de tokens”. También mantenían una página pequeña llamada “ladder de severidad” que renderizaba los cuatro callouts, con enlaces y bloques de código, en ambos modos.

Un día una actualización de dependencia cambió un token base de fondo. No fue malintencionado; fue un refactor. Los callouts seguían renderizando, pero el contraste del borde ADVERTENCIA bajó y el fondo de PELIGRO se volvió demasiado sutil. El trabajo de regresión visual lo marcó antes del merge.

Sin drama, sin rollback nocturno. La corrección fue un pequeño ajuste al alpha del borde en modo oscuro. Esto es lo que compra la “corrección aburrida”: detectas regresiones semánticas temprano y tus docs no enseñan calladamente a la gente la información equivocada.

Tareas prácticas: comandos, salidas y decisiones

Los problemas de tematización en docs se depuran mejor como cualquier otro problema de producción: reproducir, medir, aislar, arreglar, verificar y prevenir regresiones. Estas tareas asumen un repo típico de docs estáticos con un directorio de salida de build (por ejemplo build/ o dist/), assets CSS y un servidor de desarrollo local.

Tarea 1: Encuentra dónde se renderizan las admoniciones en el HTML de salida

cr0x@server:~$ rg -n "callout|admon|alert|data-kind" build/ -S | head
build/ops/runbook/index.html:214:<div class="callout warn" role="note" aria-label="Warning callout">
build/ops/security/index.html:88:<aside class="callout" data-kind="danger">
build/styles/main.css:1023:.callout.warn{--callout-accent:var(--warn-accent);}

Qué significa: Ahora conoces la forma real del DOM y los selectores usados en la salida de producción.

Decisión: Si la salida varía por página (div vs aside), estandarízala. El marcado inconsistente garantiza estilos y pruebas inconsistentes.

Tarea 2: Localiza las definiciones de tokens y confirma que no estén duplicadas

cr0x@server:~$ rg -n --hidden --glob '!**/node_modules/**' ":root|--note-accent|--warn-accent|--danger-accent" .
./src/styles/tokens.css:1::root{
./src/styles/tokens.css:22:  --note-accent: #2563eb;
./src/styles/tokens.css:30:  --warn-accent: #b45309;
./src/styles/tokens.css:38:  --danger-accent: #dc2626;
./src/styles/theme-overrides.css:11::root{ --warn-accent: #a16207; }

Qué significa: Tienes múltiples definiciones; la última gana en tiempo de ejecución.

Decisión: Consolida tokens o documenta la precedencia de overrides. Si no puedes explicar la precedencia en una frase, no la controlas.

Tarea 3: Verifica que el modo oscuro esté impulsado por prefers-color-scheme y no por un toggle frágil de clase

cr0x@server:~$ rg -n "prefers-color-scheme|data-theme=|class=.*dark" src/styles -S
src/styles/tokens.css:45:@media (prefers-color-scheme: dark){
src/styles/app.css:12:html[data-theme="dark"] .sidebar{ background: #0b1020; }

Qué significa: Estás mezclando modo oscuro automático y manual.

Decisión: Elige una fuente de verdad. Si soportas un toggle manual, debe sobreescribir prefers-color-scheme intencionalmente (y de forma consistente).

Tarea 4: Arranca un servidor local y reproduce en ambos modos

cr0x@server:~$ npm run dev
> docs@1.0.0 dev
> vite

  VITE v5.4.0  ready in 430 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: http://192.168.1.20:5173/

Qué significa: Tienes un entorno de reproducción fiable.

Decisión: Si no puedes reproducir localmente, no “arregles” el CSS en producción. Primero alinea entornos de build (versión de Node, lockfile, CI).

Tarea 5: Confirma las variables computadas finales en el CSS construido

cr0x@server:~$ rg -n --no-heading --fixed-strings "--warn-bg" build/assets/*.css | head -n 5
build/assets/main-9a8c1.css:1:...--warn-bg:#fffbeb;--warn-border:#fde68a;...
build/assets/main-9a8c1.css:1:...@media (prefers-color-scheme:dark){:root{--warn-bg:rgba(251,191,36,.1);--warn-border:rgba(251,191,36,.35)}}

Qué significa: Los tokens existen en la salida y tienen valores para claro y oscuro.

Decisión: Si faltan overrides para oscuro, tu build de CSS puede estar tree-shakeando o scopeando bloques media. Arregla la configuración del bundler antes de retocar colores.

Tarea 6: Comprueba si el selector de callout se está sobrescribiendo más adelante en el orden de CSS

cr0x@server:~$ rg -n "\.callout\.warn|\[data-kind=\"warn\"\]" build/assets/*.css | head -n 20
build/assets/main-9a8c1.css:1023:.callout.warn{--callout-accent:var(--warn-accent);--callout-bg:var(--warn-bg);--callout-border:var(--warn-border)}
build/assets/vendor-a12ff.css:887:.callout{border:1px solid transparent;background:transparent}

Qué significa: El CSS de vendor puede estar reseteando tu componente callout después de tus propias reglas, dependiendo del orden de carga.

Decisión: Arregla el orden de carga o aumenta la especificidad con cuidado. No comiences una carrera de especificidad; la perderás y te lo merecerás.

Tarea 7: Comprobar tokens faltantes usando un grep rápido

cr0x@server:~$ rg -o --no-filename "var\\(--[a-z0-9-]+\\)" -S src/styles | sort | uniq | head -n 20
var(--bg)
var(--border)
var(--callout-accent)
var(--callout-bg)
var(--callout-border)
var(--danger-accent)
var(--danger-bg)
var(--danger-border)
var(--fg)
var(--link)
var(--muted)
var(--note-accent)
var(--note-bg)
var(--note-border)
var(--tip-accent)
var(--tip-bg)
var(--tip-border)
var(--warn-accent)
var(--warn-bg)
var(--warn-border)

Qué significa: Tienes un inventario de variables referenciadas.

Decisión: Compara esto con lo que defines en :root. Las definiciones faltantes deben tratarse como fallos de build, no como “parece estar bien”.

Tarea 8: Detectar variables indefinidas buscando fallbacks ausentes

cr0x@server:~$ rg -n "var\\(--(note|tip|warn|danger)-[a-z-]+\\)" src/styles | head
src/styles/callouts.css:14:background: var(--warn-bg);
src/styles/callouts.css:15:border-color: var(--warn-border);

Qué significa: Estas referencias no tienen fallback. Si los tokens faltan o están fuera de scope, obtienes visuales rotos.

Decisión: Para semánticas críticas (ADVERTENCIA/PELIGRO), añade fallbacks o exige la presencia de tokens vía tests (mejor los tests).

Tarea 9: Verifica que el HTML incluya etiquetas y no solo iconos

cr0x@server:~$ rg -n "WARNING|DANGER|TIP|NOTE" build/ops -S | head
build/ops/runbook/index.html:216:<div class="title">WARNING</div>
build/ops/runbook/index.html:301:<div class="title">DANGER</div>

Qué significa: La severidad está presente como texto en el DOM.

Decisión: Si faltan etiquetas, agrégalas en tiempo de render. El estilo puede cambiar; el texto es duradero.

Tarea 10: Crea una página “ladder de severidad” y asegúrate de que se compile

cr0x@server:~$ ls -la src/pages/severity-ladder.md
-rw-r--r-- 1 cr0x cr0x 1482 Dec 28 10:22 src/pages/severity-ladder.md

Qué significa: Tienes una página única que renderiza todos los estados de callout para QA y regresión visual.

Decisión: Si no tienes esta página, créala. Es la canaria para regresiones de tematización.

Tarea 11: Confirma que CI construye la misma salida localmente (sanidad del lockfile)

cr0x@server:~$ node --version
v22.11.0

Qué significa: La versión de Node está explícita.

Decisión: Fija versiones de Node en CI. Las diferencias de salida CSS por versiones de herramientas son reales, y son una forma estúpida de desperdiciar un miércoles.

Tarea 12: Inspecciona la composición del bundle para ver dónde cae el CSS de callouts

cr0x@server:~$ ls -lh build/assets | head
total 1.6M
-rw-r--r-- 1 cr0x cr0x  92K Dec 28 10:35 main-9a8c1.css
-rw-r--r-- 1 cr0x cr0x 610K Dec 28 10:35 vendor-a12ff.css
-rw-r--r-- 1 cr0x cr0x 120K Dec 28 10:35 main-9a8c1.js
-rw-r--r-- 1 cr0x cr0x 740K Dec 28 10:35 vendor-a12ff.js

Qué significa: El CSS está dividido; el orden de carga importa.

Decisión: Asegura que las definiciones de tokens carguen antes que los componentes, y los componentes antes que los overrides. Si tu bundler reordena, necesitas imports explícitos.

Tarea 13: Detecta duplicación accidental del CSS de callouts entre bundles

cr0x@server:~$ for f in build/assets/*.css; do echo "== $f"; rg -n "\.callout(\.|\[)" "$f" | head -n 3; done
== build/assets/main-9a8c1.css
1023:.callout.warn{--callout-accent:var(--warn-accent);--callout-bg:var(--warn-bg);--callout-border:var(--warn-border)}
1030:.callout.danger{--callout-accent:var(--danger-accent);--callout-bg:var(--danger-bg);--callout-border:var(--danger-border)}
== build/assets/vendor-a12ff.css
887:.callout{border:1px solid transparent;background:transparent}

Qué significa: Tienes estilos base de callout en vendor y mapeo de severidad en main.

Decisión: Eso puede estar bien, pero documéntalo. Si vendor cambia, el comportamiento del componente cambia. Considera mover estilos base a tu propio bundle para estabilidad.

Tarea 14: Verifica que los colores de enlace dentro de los callouts sigan siendo legibles en ambos modos

cr0x@server:~$ rg -n "a\\{|--link" src/styles -S
src/styles/tokens.css:14:  --link: #0b5fff;
src/styles/tokens.css:15:  --link-visited: #6a2cff;
src/styles/app.css:66:a{ color: var(--link); }

Qué significa: Los enlaces usan tokens, así que puedes afinarlos globalmente si cambian los fondos de callout.

Decisión: Si los enlaces están hardcodeados, muévelos a tokens. Los callouts son donde la gente hace clic en “Aprender más” justo antes de hacer lo arriesgado.

Guion de diagnóstico rápido

Cuando alguien reporta “los callouts están mal en modo oscuro”, quieres encontrar el cuello de botella rápido. No elegantemente. Rápido.

Primero: confirma que el síntoma es semántico, no estético

  • ¿Son ADVERTENCIA y PELIGRO distinguibles a simple vista?
  • ¿La etiqueta es visible?
  • ¿El texto del cuerpo es legible sin hacer zoom?

Por qué: Si la semántica está intacta, puedes programar un fix de pulido. Si la semántica está rota, trátalo como defecto de alta prioridad.

Segundo: identifica la fuente de verdad para el estado de tema

  • ¿El modo oscuro está impulsado por prefers-color-scheme?
  • ¿Hay un toggle manual (data-theme, una clase en html)?
  • ¿Ambos están activos y compitiendo?

Por qué: “El modo oscuro está mal” suele ser “tenemos dos modos oscuros”.

Tercero: verifica la presencia de tokens y el orden de overrides

  • ¿Están definidos --warn-* y --danger-* en :root?
  • ¿Existen los overrides de modo oscuro en el CSS final?
  • ¿El CSS de vendor está reseteando el componente después de tus reglas?

Por qué: Si los tokens son correctos pero el componente se sobrescribe después, tu fix es el orden, no la selección de color.

Cuarto: busca bugs de scope

  • ¿Los tokens están definidos bajo un contenedor que no incluye el contenido de docs?
  • ¿Las admoniciones se renderizan en un iframe o shadow root?

Por qué: Las variables CSS heredan. Si tus callouts no están dentro del scope, no obtienen valores.

Quinto: ejecuta una regresión visual focalizada en la página ladder de severidad

  • Compara capturas claro vs oscuro
  • Diff del archivo de tokens CSS

Por qué: Las regresiones visuales son fáciles de discutir. Los diffs no lo son.

Errores comunes: síntoma → causa raíz → solución

1) Síntoma: PELIGRO se ve como NOTA en modo oscuro

Causa raíz: En modo oscuro se usan tintes de baja opacidad para todos los callouts, pero los acentos son demasiado similares en luminancia. O el alpha del borde es muy bajo para leerse contra el fondo de la página.

Solución: Aumenta el contraste del borde para severidades más altas. Haz el borde de PELIGRO más fuerte que el de ADVERTENCIA. Considera añadir un borde izquierdo sutil o un borde más grueso solo para PELIGRO.

2) Síntoma: el fondo del callout desaparece en algunas páginas

Causa raíz: Los tokens están scopeados a un contenedor que no está presente en esas páginas (por ejemplo, tokens en .docs-layout pero las páginas de aterrizaje usan .marketing-layout).

Solución: Mueve los tokens semánticos a :root o asegura que ambos layouts hereden de un wrapper raíz compartido.

3) Síntoma: los bordes son transparentes aunque el CSS los defina

Causa raíz: Otra hoja de estilos más tarde en la cascada establece .callout { border-color: transparent; } o resetea bordes.

Solución: Arregla el orden de importación. Si no puedes, haz la regla del componente más específica de forma controlada (por ejemplo main .callout), no con !important por todas partes.

4) Síntoma: solo el icono está coloreado; todo lo demás está gris

Causa raíz: El componente solo aplica --callout-accent y no los tokens de fondo/borde, o falta el mapeo desde la clase de severidad a tokens.

Solución: Mapea cada severidad a los tres tokens: accent, background, border. El theming parcial es como obtienes UI ambigua.

5) Síntoma: los enlaces en callouts son ilegibles en modo oscuro

Causa raíz: Los tokens globales de enlace se diseñaron para el fondo de la página, no para fondos tintados de callout; el contraste cae dentro de los callouts.

Solución: O afina los tokens globales de enlace o establece un token de enlace específico para callouts, p. ej. .callout a{ color: var(--callout-link, var(--link)); }, con overrides por severidad si hace falta.

6) Síntoma: la impresión/PDF pierde las distinciones de severidad

Causa raíz: Dependencia de tintes de fondo y significado solo por color; los estilos de impresión a menudo deshabilitan fondos.

Solución: Añade CSS para impresión: conserva bordes y etiquetas, y considera bordes con patrón (sólido vs doble) para severidad alta.

7) Síntoma: las admoniciones se ven distintas entre páginas MDX y markdown

Causa raíz: Renderizadores distintos emiten HTML distinto, así que tus selectores coinciden con uno y no con el otro.

Solución: Normaliza la salida en la capa del renderer, o escribe selectores que cubran ambas estructuras intencionalmente (y pruébalos).

8) Síntoma: el toggle de modo oscuro funciona, pero los callouts no cambian

Causa raíz: Los tokens solo se establecen en @media (prefers-color-scheme: dark), pero tu toggle usa html[data-theme="dark"].

Solución: Refleja los overrides bajo ambos mecanismos, o mejor: unifica en un método. Si debes soportar ambos, implementa: “el toggle gana sobre la media query”.

Listas de verificación / plan paso a paso

Paso a paso: construir callouts que sobrevivan al cambio de temas

  1. Estandariza el marcado: una forma de DOM para todas las admoniciones (incluyendo la etiqueta de título) en todos los tipos de contenido.
  2. Define tokens base en :root: fondo, primer plano, bordes, colores de enlace.
  3. Define tokens semánticos de severidad: --note-*, --tip-*, --warn-*, --danger-*.
  4. Mapea severidad a tokens de componente en el componente callout: establece --callout-accent, --callout-bg, --callout-border.
  5. Implementa fallbacks en el punto de consumo del componente (bordes, fondo) para que los tokens faltantes degraden con seguridad.
  6. Soporta modo oscuro con overrides explícitos bajo @media (prefers-color-scheme: dark) y/o tu mecanismo de toggle elegido.
  7. Añade una página ladder de severidad que renderice todas las severidades con enlaces y bloques de código.
  8. Añade una comprobación de “presencia de tokens” en CI: parsea CSS o grep la salida construida en busca de tokens requeridos.
  9. Añade pruebas de regresión visual para la página ladder en modo claro y oscuro.
  10. Define reglas de revisión: cualquier cambio a tokens requiere un diff de capturas y verificación de contraste.

Checklist operativo: antes de fusionar un cambio de tema

  • ADVERTENCIA y PELIGRO son visualmente distintos en ambos modos sin leer el texto del cuerpo.
  • Las etiquetas están presentes y legibles.
  • Los enlaces dentro de callouts siguen siendo legibles y claramente enlaces.
  • Los estilos de impresión preservan bordes y etiquetas.
  • Las actualizaciones de CSS de vendor no pueden sobrescribir tokens silenciosamente (orden de importación verificado).
  • El estado de modo oscuro tiene una fuente de verdad (o una regla de precedencia documentada).
  • La página ladder de severidad pasa las pruebas de regresión visual.
ADVERTENCIA

Si tu “definición de hecho” para la tematización de docs es “se ve bien en mi portátil”, no tienes una definición de hecho. Tienes vibes.

Preguntas frecuentes

1) ¿Deberían los callouts usar <aside> o <div>?

Usa <aside> cuando el contenido sea tangencial al flujo principal (lo que muchas admoniciones son). Usa <div> si tu generador no puede emitir confiablemente <aside>. La consistencia importa más que la perfección semántica.

2) ¿Debería tematizar callouts con colores hex o HSL?

Usa lo que tu equipo pueda mantener. HSL puede facilitar ajustes de luminancia para modo oscuro, pero solo si tu equipo realmente lo usa. Los tokens son lo importante, no el formato del color.

3) ¿Es suficiente prefers-color-scheme o necesito un toggle manual?

Para docs públicas, prefers-color-scheme es un buen defecto. Un toggle manual es útil cuando la gente trabaja en entornos mixtos (presentaciones, compartir pantalla) o cuando la configuración del SO está bloqueada. Si añades un toggle, haz que sobreescriba la media query de forma predecible.

4) ¿Cómo prevengo que una actualización de dependencia rompa colores de callout?

Dos controles: (1) mantén tus tokens en tu repo, no dentro de un tema vendor que no controlas; (2) añade regresiones visuales y comprobaciones de presencia de tokens en CI. Trata los cambios de tokens como cambios de API.

5) ¿Por qué no usar simplemente !important para evitar overrides?

Porque ganarás la batalla y perderás la guerra. !important escala mal y rompe la extensibilidad de temas. Arregla orden y scope primero. Si debes usarlo, aplícalo a tokens en la raíz, no a cada propiedad en cada componente.

6) ¿Los callouts necesitan iconos distintos por severidad?

Sí, si quieres que los usuarios diferencien la severidad rápidamente. Como mínimo, ADVERTENCIA y PELIGRO no deberían compartir icono. Combina icono + etiqueta + color para redundancia.

7) ¿Cuál es la cobertura mínima de pruebas para callouts?

Al menos una página que renderice todas las severidades, en modo claro y oscuro, bajo regresión visual. Añade una comprobación rápida basada en texto que verifique que los tokens existen en el CSS construido. Es barato y detecta la clase de fallos “archivo de tokens no importado”.

8) ¿Cómo manejo callouts dentro de contenedores anidados (pestañas, acordiones, barras laterales)?

Asegura que las variables estén definidas en :root o heredadas en esos contenedores. Evita scopear tokens a un wrapper de layout que algunas páginas no usan. Si un contenedor cambia deliberadamente el fondo, considera ajustes específicos del contenedor via tokens adicionales (pero mantiene el mapeo de severidad consistente).

9) ¿Son obligatorios los fondos tintados para los callouts?

No. Los bordes más una etiqueta fuerte pueden ser suficientes, y a menudo imprimen mejor. Los fondos tintados son una ayuda de legibilidad, no la señal primaria de severidad.

10) ¿Cómo mantengo callouts consistentes entre múltiples sitios de docs?

Envía un único CSS de componente callout y un archivo de tokens. Permite que cada sitio sobrescriba tokens, no reglas de componente. Así obtienes flexibilidad de marca sin deriva semántica.

Conclusión: próximos pasos que perduran

Si quieres callouts que no te traicionen, trátalos como una interfaz operativa, no como una decoración. Estás codificando riesgo. Haz que esa codificación sea estable.

  1. Normaliza el marcado de admoniciones para que tus selectores no anden adivinando.
  2. Mueve los colores de severidad a variables CSS (tokens semánticos), y mapea todo en un único componente callout.
  3. Implementa el modo oscuro como overrides explícitos de tokens, no como efectos colaterales accidentales.
  4. Añade una página ladder de severidad y hazla parte del CI con un diff visual.
  5. Adopta una regla aburrida: los cambios de token requieren revisión como cambios de código, porque lo son.

Cuando tu UI de docs comunica el riesgo correctamente, los usuarios adivinan menos. Menos adivinanzas significa menos incidentes. La cuenta es dura pero consistente.

← Anterior
PostgreSQL vs OpenSearch: la configuración de búsqueda híbrida que realmente funciona
Siguiente →
Preparación del dominio de correo: plan práctico para evitar marcas de spam instantáneas

Deja un comentario