Los incidentes en producción rara vez comienzan con un único gran error. Empiezan con miles de pequeños cortes: un comando copiado con una nueva línea oculta, una insignia que implica “seguro”, una etiqueta que miente, un atajo de teclado mostrado incorrectamente, código en línea que parece prosa. El lector hace lo que usted le indicó. Su interfaz enseñó a la gente a confiar en ella.
Si publicas posts técnicos, documentación, runbooks o playbooks internos, estos micro componentes no son decoración. Son parte del plano de control. Trátalos como tratas tu monitorización: valores predeterminados opinados, resultados medibles y tolerancia cero a estados ambiguos.
Por qué importan estos micro componentes (y cómo fallan)
En el mundo SRE, nos obsesionamos con los presupuestos de errores porque obligan a ser honestos. Los micro componentes de UI necesitan la misma energía. Si tu sitio de documentación tiene un botón de copiar que a veces copia prompts extra, has creado un presupuesto de error para el tiempo de tus lectores, y lo estás gastando sin medirlo.
Los micro componentes son “APIs de comportamiento”
Cada componente enseña al usuario un comportamiento:
<kbd>enseña “pulsa esta secuencia de teclas exacta”. Si está mal, rompes flujos y accesibilidad.- Código en línea enseña “este token es exacto”. Si se estiliza como texto normal, pasa a ser “opcional”.
- Insignias enseñan “esto es seguro/oficial/estable”. Si las usas como decoración, creas garantías implícitas.
- Etiquetas enseñan “este contenido pertenece a un clúster de significado”. Si las etiquetas son inconsistentes, la búsqueda se vuelve folklore.
- Botones de copiar enseñan “puedes confiar en lo copiado”. Si esa confianza se rompe una vez, se rompe para siempre.
Modos de fallo que deberías asumir que ocurrirán
Esto no es teórico. He visto cada caso costar tiempo real en incidentes:
- Contaminación de prompt: el botón de copiar incluye
cr0x@server:~$en el prompt; se pega en un script; el script falla; el on-call pierde 20 minutos. - Caracteres invisibles: espacio no separable en un token de código en línea; copiar/pegar falla; el usuario culpa a la herramienta.
- Mala interpretación de insignias: una insignia “Recomendado” interpretada como “Soportado”; equipos la despliegan; seguridad luego dice “nosotros no aprobamos eso”.
- Desajuste de teclado: mostrar
Ctrlpara macOS; los lectores presionan mal; suponen que la función está rota. - Deriva de fuente de código: el código en línea usa una fuente proporcional;
l,Iy1se vuelven un juego de adivinanza.
Idea parafraseada de Ben Treynor Sloss de Google SRE: la fiabilidad es una característica, y tienes que priorizarla
. Tu UI de documentación es parte de la fiabilidad, porque determina si los humanos pueden ejecutar las acciones correctas bajo presión.
Broma #1: Un botón de copiar que copia el prompt es como un cinturón de seguridad que a veces se convierte en bufanda. Técnicamente es tela, prácticamente caos.
Playbook de diagnóstico rápido: encuentra el cuello de botella en minutos
Tienes quejas: “copiar no funciona”, “kbd se ve raro”, “las insignias confunden”. No abras Figma aún. Diagnostica como un SRE.
Primero: confirma la falla real
- Reproduce con una ruta de usuario real: mobile Safari + desktop Chrome + una pasada con lector de pantalla.
- Captura la carga útil copiada: confirma si se incluyen caracteres invisibles, prompts o nuevas líneas.
- Revisa la semántica del DOM: ¿estás usando el verdadero
<kbd>y<code>, o un<span class="code">de utilería?
Segundo: identifica si es un problema de CSS/JS/build
- Problema de CSS: el componente se renderiza pero se ve mal; el comportamiento funciona. Revisa estilos calculados, modo oscuro, carga de fuentes y guerras de especificidad.
- Problema de JS: el botón de copiar no copia, copia contenido obsoleto, o falla bajo CSP. Revisa errores en consola, permisos y ruta de fallback.
- Problema de build/contenido: el renderer de markdown envuelve prompts, escapa o normaliza espacios en blanco. Revisa la pipeline y los sanitizadores.
Tercero: decide la clase de arreglo
- Hotfix cuando los usuarios copian comandos equivocados: añade eliminación de prompts, actualiza la lógica de portapapeles, despliega ahora.
- Endurecimiento cuando es mayormente estético pero causa confusión: unifica tokens, añade tests, aplica linting.
- Rediseño cuando la semántica es incorrecta: cambia a elementos HTML nativos y patrones accesibles.
El <kbd> elemento: suero de la verdad para teclado
<kbd> es uno de esos elementos HTML que la gente redescubre cada pocos años, como una herramienta que ya posees pero que de alguna manera sigues rentando. Úsalo siempre que indiques pulsaciones de teclas. Es semántico, estilizable y compatible con lectores de pantalla cuando se usa correctamente.
Cuándo usar <kbd> vs código en línea
- Usa
<kbd>para teclas y atajos: Ctrl + C, Shift + ?. - Usa
<code>para tokens literales:systemctl,--help,/etc/ssh/sshd_config. - No uses código en línea para teclas. Los lectores interpretan el código como texto para copiar, no como acciones para presionar.
Cómo falla <kbd> en documentación real
- Desajuste de plataforma: mostrar Ctrl en macOS donde la gente espera ⌘ (Command). Solución: renderizado condicional o muestra dual.
- Atajos anidados:
<kbd>Ctrl + C</kbd>es menos accesible que teclas separadas. Mejor: Ctrl+C. - Sobrestilizado: añades sombras fuertes y degradados; parece un botón clicable; los usuarios lo clican y no pasa nada.
Reglas opinadas
- Mantén el estilo de kbd sutil: borde, fondo, relleno pequeño, tipografía monoespaciada opcional.
- Usa separadores consistentes: prefiero
+sin espacios alrededor para compactar: Ctrl+C. - No inventes nombres de teclas: usa Esc en lugar de “Escape Key”. Usa Enter y no “Return” a menos que sea específico de la plataforma.
Código en línea: tipografía, semántica y seguridad al copiar
El código en línea es donde la redacción técnica gana o pierde confianza. Le dice al lector: “esta cadena exacta importa”. Si tu código en línea es visualmente débil, se lee como énfasis. Si es visualmente estridente, se lee como error. Apunta a “preciso y sereno”.
El código en línea debe comportarse como un checksum
El lector debería poder mirar un token en línea y saber que es exacto. Eso significa:
- Una fuente monoespaciada con glifos claros (
1vslvsI). - Fondo y borde consistentes que funcionen en modo oscuro.
- Sin saltos de línea dentro de tokens salvo que permitas envoltura deliberadamente (entonces añade reglas de
word-break).
Fallo típico: “puntuación inteligente” y motores tipográficos
Muchas pipelines aplican sustituciones tipográficas: comillas curvas, guiones largos, espacios no separables. En prosa está bien. En comandos, es sabotaje. Tu renderer debería:
- Desactivar puntuación inteligente dentro de
<code>y<pre>. - Preservar caracteres ASCII exactamente.
- Normalizar finales de línea (LF) si tu botón de copiar apunta a terminales.
Insignias: estado, riesgo y el peligro de las promesas implícitas
Las insignias son etiquetas pequeñas con autoridad desmesurada. Parecen oficiales incluso cuando no lo son. Por eso marketing las adora—y por eso los equipos de operaciones deberían desconfiar.
Las buenas insignias responden a una sola pregunta
- Estado: Stable, Beta, Deprecated.
- Ámbito: Linux-only, macOS-only, Kubernetes.
- Riesgo: Destructive, Requires root.
- Cumplimiento: Approved, Needs review (cuidado: implica gobernanza).
Insignias que deberías evitar
- Insignias de sensaciones: “Awesome,” “Hot,” “Trending.” Eso pertenece a redes sociales, no a runbooks.
- Insignias ambiguas: “Recommended” sin una política detrás. ¿Recomendado por quién, bajo qué condiciones, con qué plan de rollback?
- Sólo semántica por color: rojo/verde sin texto. Accesibilidad y usuarios internacionales te castigarán en silencio.
Haz la significación de la insignia verificable
Una insignia debe mapear a una regla que puedas probar. Ejemplo: “Deprecated” significa que la página incluye un enlace de reemplazo y una fecha (o al menos versión). “Destructive” significa que el bloque de comandos incluye una línea de “qué cambia” y una alternativa de dry-run.
Hechos y contexto histórico que realmente puedes usar
- HTML ha tenido
<kbd>desde las primeras especificaciones, destinado a ejemplos de entrada del usuario; no es una invención moderna, sólo algo que se ignora con frecuencia. - “Copiar al portapapeles” solía ser un truco de la era Flash en muchos sitios; la moderna Clipboard API reemplazó un montón de soluciones inseguras.
- Las fuentes monoespaciadas varían mucho en claridad de glifos; algunas fuentes populares de desarrolladores todavía hacen que
Oy0sean demasiado similares, lo que importa en código en línea. - Los terminales normalizaron la idea de prompts (
$para usuario,#para root), pero no hay un formato universal de prompt, así que eliminar prompts es inherentemente heurístico. - Los espacios no separables se introdujeron para tipografía, no para código; rutinariamente se filtran en código en línea vía editores WYSIWYG y pueden romper el parsing del shell.
- Los bloques de código de Markdown popularizaron el patrón de “snippet copiable”, pero los renderers de Markdown difieren en preservación de whitespace y escape de HTML.
- Las insignias explotaron en popularidad con la cultura README; con el tiempo pasaron de señales de estado a decoración, reduciendo la confianza en la señal.
- La notación de atajos de teclado es culturalmente inconsistente: macOS usa símbolos (⌘, ⌥), Windows usa palabras (Ctrl, Alt). Tus docs necesitan una política, no esperanza.
Tres mini-historias corporativas (cómo esto sale mal en la vida real)
1) Incidente causado por una suposición incorrecta: “copiar copia el comando”
Una empresa SaaS de tamaño medio lanzó un nuevo portal interno de runbooks. Tenía un componente de bloque de código con copy button y un estilo de prompt “shell”. El liderazgo de ingeniería estaba contento: menos typos, mitigación más rápida, menos tiempo de entrenamiento.
La suposición errónea fue sutil: el equipo de UI asumió que el prompt era “presentación”, así que lo pusieron directamente en el texto del bloque de código. Se renderizaba de forma hermosa. Y el botón de copiar copió todo el bloque, prompts incluidos.
Durante un incidente, un ingeniero on-call copió un comando de mitigación en un shell root en un host de producción. La línea pegada empezaba con cr0x@server:~$, que el shell interpretó como un nombre de comando. La mitigación falló. Intentaron de nuevo, obtuvieron el mismo fallo y empezaron a debuggear el servicio en lugar del runbook.
Mientras tanto, el temporizador del incidente no perdonó. El equipo perdió minutos valiosos, escaló innecesariamente y sólo más tarde notó la basura del prompt en el historial del terminal. El postmortem fue incómodo porque nadie quería admitir “la UI de docs rompió producción”. Pero lo hizo.
La corrección fue aburrida e inmediata: los prompts pasaron a pseudo-elementos CSS; la carga útil de copia pasó a ser sólo el texto bruto del comando; y cada bloque de código ganó una línea “Tested on: bash”. La corrección mayor fue cultural: la UI de runbooks empezó a tratarse como un sistema de producción con tests de regresión.
2) Optimización que salió mal: “enviar menos bytes, enviar menos confianza”
Una gran plataforma de documentación empresarial decidió optimizar rendimiento. Reemplazaron bloques de código renderizados en servidor por un componente cliente que se hidrataba después de la carga. Objetivo: HTML más pequeño, pinta inicial más rápida, bloques de código interactivos con insignias y acciones de copia.
Se veía bien en pruebas sintéticas. El problema fue la realidad del usuario: navegadores corporativos con políticas estrictas de Content Security Policy, permisos de portapapeles bloqueados y bloqueadores de scripts agresivos. La hidratación fallaba o se retrasaba con frecuencia.
Los usuarios veían bloques de código sin botones de copiar, luego los botones aparecían tarde, luego desaparecían al navegar porque el router SPA reutilizaba nodos incorrectamente. Algunos usuarios copiaron comandos obsoletos de una página anterior porque el manejador de copia referenciaba un id DOM antiguo. Ese es el tipo de bug que no aparece en tests unitarios; aparece en “por qué ejecutamos ese comando en el clúster equivocado”.
Finalmente la plataforma volvió a bloques de código renderizados en servidor con mejora progresiva: el código siempre está presente, siempre seleccionable, y el botón de copiar es una mejora, no una dependencia. La “optimización” ahorró kilobytes y gastó credibilidad. No es un trade-off que puedas ganar.
3) Práctica aburrida pero correcta que salvó el día: reglas de lint y tests dorados
Un equipo más pequeño mantenía runbooks para una plataforma de almacenamiento. No eran sofisticados. La UI era simple. Pero tenían una pipeline implacable: cada PR ejecutaba un linter que rechazaba código en línea con whitespace no ASCII y rechazaba bloques de código que comenzaran con prompts a menos que se marcaran explícitamente como “terminal transcript”.
La gente se quejó al principio. Los escritores querían pegar desde terminales. Los ingenieros querían moverse rápido. El linter era el amigo molesto que siempre revisa tu trabajo.
Luego llegó un incidente real: una caída generalizada con docenas de respondedores en distintas zonas horarias. Estaban copiando comandos de mitigación bajo estrés. Los runbooks se comportaron: los botones de copiar copiaron exactamente los comandos, sin prompts, sin sorpresas de formato, sin “por qué insertó una comilla curva”.
El equipo luego se dio cuenta de que habían evitado toda una clase de fallos no porque fueran más listos, sino porque tenían guardarraíles. La práctica era aburrida. También era correcta. En operaciones, lo aburrido es un logro.
Tareas prácticas: 14 verificaciones con comandos, salidas y decisiones
Estas tareas asumen que ejecutas un sitio de docs o blog en producción (generador de sitio estático, CDN, quizá un servicio Node). El punto no es la pila exacta. El punto es: puedes verificar el comportamiento de micro componentes de la misma forma que verificas latencia de almacenamiento—observando artefactos reales.
Task 1: Confirmar que la carga útil de copia no contiene marcadores de prompt
cr0x@server:~$ node -e 'const s="cr0x@server:~$ sudo systemctl restart nginx\n"; console.log(s.replace(/^.*\$\s+/gm,""))'
sudo systemctl restart nginx
Qué significa la salida: La regex de eliminación de prompt removió todo hasta $ al inicio de la línea.
Decisión: Si tu UI incluye prompts en el texto de código, implementa una política fiable de “strip on copy” o deja de incrustar prompts en la fuente copiables.
Task 2: Detectar espacios no separables en HTML exportado
cr0x@server:~$ grep -RIn --binary-files=without-match $'\xC2\xA0' public/ | head
public/posts/storage-runbook/index.html:842:Use zpool status before changes.
Qué significa la salida: La salida muestra un espacio no separable en un token de código en línea.
Decisión: Arregla la pipeline de contenido: reemplaza NBSP por espacio ASCII dentro de código, y añade una puerta de build que falle con este patrón.
Task 3: Verificar que el código en línea es realmente elementos <code>
cr0x@server:~$ rg -n "kubectl get pods
Qué significa la salida: Tu renderer está produciendo spans de código falsos.
Decisión: Cambia a la semántica <code> para que herramientas de accesibilidad y CSS puedan tratarlo correctamente. Los spans de utilería son donde nacen las inconsistencias.
Task 4: Asegurar que los bloques de código mantienen exactamente el whitespace
cr0x@server:~$ python3 - <<'PY'
s = "echo one\n\tprintf 'two'\n"
print(repr(s))
PY
"echo one\n\tprintf 'two'\n"
Qué significa la salida: Tabs y nuevas líneas son explícitos. Tu componente de bloque de código debe preservarlos; algunos renderers colapsan tabs en espacios de forma inconsistente.
Decisión: Si ves tabs en muestras de código, o bien impones espacios o aseguras que tu renderer y lógica de copia preserven tabs exactamente.
Task 5: Comprobar comillas curvas y guiones largos en muestras de código
cr0x@server:~$ rg -n "[\u2018\u2019\u201C\u201D\u2013\u2014]" content/ | head
content/posts/ssh-hardening.md:57:Run: `ssh –V` and verify output
Qué significa la salida: Ese dash es un en-dash, no un guion. Las flags del shell fallarán.
Decisión: Añade una regla de linter: rechaza puntuación inteligente dentro de backticks y bloques fenceados. Corrige el contenido fuente.
Task 6: Validar que los botones de copiar existen sólo donde se pretende
cr0x@server:~$ rg -n "data-copy-button" public/ | wc -l
128
Qué significa la salida: Tienes 128 instancias. Ese es tu inventario.
Decisión: Si ese número salta inesperadamente en una release, probablemente cambiaste una plantilla y estás adjuntando botones de copiar a snippets no comanda (fragmentos JSON, trazas de stack, etc.). Decide si eso es deseable.
Task 7: Confirmar que el uso de Clipboard API está detrás de un gesto de usuario
cr0x@server:~$ rg -n "navigator\.clipboard\.writeText" assets/ | head
assets/js/copy.js:41:await navigator.clipboard.writeText(text)
Qué significa la salida: Encontraste el sitio de llamada.
Decisión: Inspecciona ese manejador: debe estar en un callback de click/tap. Si está dentro de un evento load, tendrás fallos y posibles advertencias de seguridad.
Task 8: Comprobar los encabezados CSP para compatibilidad con clipboard y scripts inline
cr0x@server:~$ curl -sI https://docs.example.internal | sed -n '1,20p'
HTTP/2 200
content-security-policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'
content-type: text/html; charset=utf-8
Qué significa la salida: Los scripts sólo pueden cargarse desde self. Los scripts inline serán bloqueados a menos que uses nonces/hashes.
Decisión: Si tu botón de copiar depende de JS inline, fallará en este entorno. Publica la lógica de copia como archivo externo o usa nonces CSP.
Task 9: Verificar que tu sitio sirve los assets de fuentes de código correctos (y no 404)
cr0x@server:~$ curl -sI https://docs.example.internal/assets/fonts/JetBrainsMono.woff2 | head -n 5
HTTP/2 200
content-type: font/woff2
cache-control: public, max-age=31536000, immutable
Qué significa la salida: La fuente carga y es cacheable.
Decisión: Si ves 404 o tipos MIME incorrectos, tu código en línea caerá a fuentes del sistema de forma impredecible. Arregla la build o la configuración del CDN.
Task 10: Medir si tu script de copia es un ancla de rendimiento
cr0x@server:~$ ls -lh public/assets/js/ | rg "copy|code|highlight"
-rw-r--r-- 1 cr0x cr0x 3.2K Jan 10 12:11 copy.js
-rw-r--r-- 1 cr0x cr0x 188K Jan 10 12:11 highlight.js
Qué significa la salida: El highlighting pesa 188K; la lógica de copia 3.2K.
Decisión: No empaquetes la lógica de copia en un runtime grande de highlight si puedes evitarlo. Publica copia como mejora progresiva y carga el resaltado sólo cuando sea necesario.
Task 11: Detectar etiquetas duplicadas o inconsistentes en tu taxonomía
cr0x@server:~$ jq -r '.posts[].tags[]' public/search-index.json | sort | uniq -c | sort -nr | head
42 kubernetes troubleshooting
17 k8s troubleshooting
11 Kubernetes troubleshooting
Qué significa la salida: Tienes tres variantes para el mismo concepto, incluyendo diferencias de mayúsculas.
Decisión: Canonicaliza etiquetas en tiempo de build. Elige una forma (minúsculas, etiquetas multi-palabra tipo consulta) y reescribe las demás.
Task 12: Confirmar que las insignias mapean a estados conocidos (no texto libre)
cr0x@server:~$ jq -r '.posts[].badges[]?' public/search-index.json | sort | uniq -c | sort -nr
59 stable
14 beta
7 recommended
3 Stable
2 hot
Qué significa la salida: “Stable” duplica “stable”, y tienes “hot”, que no es un estado, es un humor.
Decisión: Bloquea los valores de insignia en un enum. Si alguien quiere una insignia nueva, que la proponga como cambio de esquema, no como un tweet.
Task 13: Verificar que los bloques de transcripción de terminal estén etiquetados y no sean copiables por defecto
cr0x@server:~$ rg -n "terminal-transcript" public/ | head public/posts/mysql-recovery/index.html:411:cr0x@server:~$ tail -n 50 /var/log/mysql/error.log ...Qué significa la salida: Los bloques de transcripción están clasificados.
Decisión: Si es una transcripción, considera deshabilitar la copia o copiar sólo las líneas de comando (no la salida). Haz la UI explícita.
Task 14: Detectar cadenas de prompt dentro de bloques de código que se declaran copiables
cr0x@server:~$ rg -n "^\w+@[^:]+:.*\\$ " content/ | head content/runbooks/restart-nginx.md:12:cr0x@server:~$ sudo systemctl restart nginxQué significa la salida: El runbook incluye una línea de prompt literal en el contenido fuente.
Decisión: Conviértelo a código sin prompt (preferible) o marca el bloque como transcripción y ajusta el comportamiento de copia. No lo dejes ambiguo.
Errores comunes: síntoma → causa raíz → solución
1) Síntoma: los usuarios pegan comandos y obtienen “command not found” con su nombre de usuario
Causa raíz: El texto del prompt se incluye en la carga copiada (porque los prompts son texto literal o porque se copian números de línea).
Solución: Renderiza prompts vía pseudo-elementos CSS, o elimina prompts al copiar con reglas conservadoras. Añade un test que simule copiar y aserte que la carga útil comienza con el comando.
2) Síntoma: copiar funciona en Chrome pero no en navegadores corporativos bloqueados
Causa raíz: CSP bloquea scripts inline o llamadas al clipboard; o los permisos del portapapeles requieren HTTPS y gesto de usuario.
Solución: Publica la lógica de copia como JS externo permitido por CSP; asegura que la copia se dispare solo con click; implementa fallback: seleccionar todo + instruir al usuario a presionar Ctrl+C.
3) Síntoma: flags en línea como --max-time se renderizan como –max–time
Causa raíz: El motor de puntuación inteligente transforma guiones en en-dashes y doble guion en em-dash en ciertos editores.
Solución: Desactiva sustituciones tipográficas dentro de spans de código y fences; añade reglas de linter que rechacen caracteres Unicode de guion en contextos de código.
4) Síntoma: atajos de teclado se malinterpretan entre OS
Causa raíz: Se usa una notación de atajo universal; usuarios macOS esperan símbolos, Windows/Linux esperan palabras.
Solución: Proporciona renderizado específico por OS o notación dual: Ctrl (Windows/Linux) / ⌘ (macOS). Si no puedes, al menos etiqueta la plataforma explícitamente.
5) Síntoma: las insignias crean bucles de escalado (“seguridad aprobó esto, ¿verdad?”)
Causa raíz: Las insignias implican gobernanza sin políticas de respaldo. Los lectores interpretan la autoridad de la UI como autoridad organizacional.
Solución: Usa insignias sólo para estados que puedas hacer cumplir y explicar. Añade un tooltip o leyenda que defina cada insignia en lenguaje llano.
6) Síntoma: las etiquetas no mejoran el descubrimiento; lo fragmentan
Causa raíz: Etiquetas libres, mayúsculas inconsistentes, sinónimos y casi-duplicados.
Solución: Diccionario canónico de etiquetas, aplicado en build; migra etiquetas antiguas; trata cambios de taxonomía como migraciones de esquema.
7) Síntoma: copiar comandos multilínea falla porque se pierden continuaciones de línea
Causa raíz: El renderer envuelve líneas visualmente pero altera whitespace, o copia artefactos de soft-wrap, o inserta saltos de línea en medio de tokens.
Solución: Asegura que <pre> use nuevas líneas reales; evita insertar <br> dentro de código; copia desde el textContent del elemento <code>, no desde un clon estilizado.
8) Síntoma: el modo oscuro hace ilegible el código en línea
Causa raíz: Colores de fondo/borde de código en línea afinados sólo para tema claro; contraste falla.
Solución: Define tokens de tema para fondo, borde y texto del código; ejecuta checks de contraste; mantén el código en línea sutil pero legible.
Listas de verificación / plan paso a paso
Paso a paso: lanza “bloques de código confiables” en una semana
- Elige una política para prompts: no prompts en la fuente copiables (recomendado) o strip-on-copy (aceptable con tests).
- Estandariza la semántica: tokens en línea usan
<code>; atajos usan<kbd>; bloques de código usan<pre><code>. - Implementa comportamiento de copia:
- Copiar desde el raw
textContentdel elemento<code>. - Normalizar finales de línea a
\n. - Opcionalmente recortar una sola nueva línea final (sé consistente).
- Copiar desde el raw
- Añade una ayuda visual: botón “Copiar” con estado “Copiado” que no desplaza el layout y con retroalimentación aria-live.
- Añade un fallback: comportamiento seleccionar-todo o instrucción mostrando Ctrl+C / ⌘+C.
- Telemetría, pero no invasiva: registra “copy attempted”, “copy succeeded”, “copy failed” por página y id de bloque—no el contenido del comando.
- Lint de contenido:
- Rechazar NBSP y comillas/guiones inteligentes dentro de contextos de código.
- Rechazar prompts en fences de código no marcados como transcripción.
- Tests de regresión: tests dorados sobre HTML renderizado para páginas representativas; un test de navegador que haga click en copiar y aserte la carga del portapapeles.
- Escribe una leyenda para insignias y política de etiquetas: qué significa cada insignia, quién la posee y qué requiere “Deprecated”.
Lista de verificación: insignias y etiquetas defendibles en un postmortem
- Cada valor de insignia está en una lista controlada.
- Cada insignia tiene un significado definido y un responsable.
- “Deprecated” requiere referencia de reemplazo y una declaración de cronograma.
- Las etiquetas están canonicalizadas (case, espaciado) y mapeadas desde sinónimos.
- El conjunto de etiquetas es lo suficientemente pequeño como para que un humano reconozca duplicados.
Lista de verificación: comprobaciones de accesibilidad
<kbd>no se usa para cosas que no son teclas.- El botón de copiar es accesible por teclado y tiene estado de foco visible.
- La confirmación de copia se anuncia vía aria-live y no depende sólo del color.
- Las insignias no comunican solo por color; incluyen texto.
- El código en línea tiene contraste suficiente en modos claro y oscuro.
Preguntas frecuentes
1) ¿Debo usar <kbd> para teclas sueltas y atajos?
Sí. Usa <kbd> para teclas, y compón atajos con múltiples elementos <kbd>: Ctrl+C. Es más claro y accesible.
2) ¿Está bien mostrar prompts en bloques de código?
Sólo si tratas el bloque como una transcripción y lo etiquetas así. Para snippets copiables, los prompts deben ser presentación (CSS) o eliminarse al copiar con tests.
3) ¿Por qué no siempre eliminar prompts al copiar?
Porque los formatos de prompt varían y las heurísticas acabarán comiéndose un comando legítimo (especialmente cuando comandos empiezan con $ en ejemplos, o cuando la salida contiene patrones similares). Si puedes evitar prompts en la fuente, hazlo.
4) ¿El código en línea debe envolver en pantallas pequeñas?
A veces. Rutas y flags largos pueden desbordar. Usa CSS para permitir envoltura segura para tokens largos mientras preservas la corrección al copiar. Si la envoltura puede romper el significado, mantenlo sin envolver y permite scroll horizontal.
5) ¿Los botones de copiar necesitan telemetría?
Si te importa la fiabilidad, sí. Registra intentos/éxitos/errores por página y bloque. No registres la cadena copiada. Quieres tasas y modos de fallo, no contenido.
6) ¿Cuál es el carácter invisible más común que rompe comandos?
El espacio no separable. Parece un espacio, pero los shells no lo tratan como separador. Los guiones inteligentes y comillas curvas son otros candidatos cercanos.
7) ¿Cuántas insignias son demasiadas?
Si una página tiene más de dos o tres insignias, probablemente estás codificando un párrafo de matices en confetti. Pon los matices en texto; reserva insignias para estados de alta señal.
8) ¿Siguen valiendo las etiquetas cuando existe búsqueda de texto completo?
Sí, si las gobiernas. Las etiquetas son un índice opinado; la búsqueda es una conjetura. Las etiquetas ayudan a los usuarios a acotar ámbito (“comandos solo para linux”) y a encontrar contextos operacionales relacionados.
9) ¿Necesito notación de atajos diferente para macOS?
Idealmente, sí. Como mínimo, etiqueta la plataforma. Lo mejor es notación dual o renderizado dependiente del OS para que el usuario no tenga que traducir en su cabeza.
10) ¿Debo usar resaltado de sintaxis en todas partes?
No. El resaltado es costoso y a menudo inútil para comandos de una sola línea. Úsalo donde aporte significado (configs, código) y mantén los comandos shell limpios y seguros para copiar.
Conclusión: próximos pasos que puedes desplegar esta semana
Los micro componentes no parecen “producción”, lo que es exactamente por lo que silenciosamente causan problemas en producción. Arreglarlos no es un proyecto de rediseño. Es trabajo de fiabilidad: aprieta la semántica, elimina la ambigüedad, añade guardarraíles, mide resultados.
- Audita el comportamiento de copia en tus 20 páginas principales: confirma que la carga del portapapeles está libre de prompts y con whitespace correcto.
- Aplica linting de contenido para NBSP y puntuación inteligente en contextos de código. Haz que falle builds. Sí, la gente se quejará. Déjalos que se quejen ahora en lugar de durante un incidente.
- Define gobernanza de insignias y etiquetas: vocabularios controlados, responsables y significados. Si no puedes definir el significado, elimina la insignia.
- Haz la accesibilidad no opcional: verdadero
<kbd>, verdadero<code>, botones de copiar operables por teclado y estados de foco visibles. - Añade un test de navegador que haga click en copiar y aserte la cadena del portapapeles. Es el seguro más barato que comprarás este trimestre.
Haz eso y tu documentación dejará de ser “texto bonito en internet” y empezará a ser lo que debe ser: un panel operativo que no miente cuando la sala está en llamas.