Communitygithub.com

TLucas97/tarcsweb

Estilo interno para explicaciones visuales dibujadas con mcp__visual__render_ui (diagramas, flujos, gráficos pequeños, animaciones explicativas). Léelo una vez por sesión antes de la primera llamada a render_ui explicativa. No es para prototipos de componentes; esos siguen el diseño que el usuario indique.

¿Qué es tarcsweb?

Esta habilidad establece un estilo visual riguroso y de alta legibilidad para crear explicaciones gráficas (diagramas de flujo, secuencias, gráficos pequeños y animaciones) mediante `mcp__visual__render_ui`. Su objetivo principal es garantizar que la imagen final —que es el único fotograma visible— sea comprensible por sí sola, sin depender de la animación. El estilo se basa en un esquema de color minimalista con fondo blanco, tinta oscura, un solo acento verde y tipografía Atkinson Hyperlegible para máxima claridad. Incluye reglas estrictas de espaciado, tamaños de texto (nunca menor de 16px), una paleta de colores tokenizada, pautas de layout (flujo de izquierda a derecha, máximo dos filas) y especificaciones de animación suave con GSAP u otras librerías. También proporciona un esqueleto HTML/CSS/JS listo para usar, con enlaces CDN a librerías como GSAP, d3, KaTeX, highlight.js, entre otras. La habilidad está diseñada para Claude Code y otras plataformas que soporten renderizado MCP, asegurando que cada explicación visual sea clara, accesible y consistente.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/TLucas97/tarcsweb/tree/HEAD/mods/visual/skills/visual-explainer

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Explicación visual

La imagen que el usuario ve es el fotograma final. El botón de reproducción vuelve a ejecutar la animación una vez. Por lo tanto, la imagen estática debe explicarse por sí sola; el movimiento solo muestra el orden de las cosas.

Este es el estilo interno: tinta oscura, un acento verde y tiempos calmados, sobre blanco con líneas finas en lugar de sombras.

Legibilidad ante todo

La imagen se dibuja 1:1 junto al texto del terminal de aproximadamente 15px. Cualquier cosa más pequeña se lee peor que el chat que la rodea, por lo que el usuario no puede leerla.

  • Sin texto por debajo de 16px (código 15px). Si no cabe, recorta contenido o divídelo en dos imágenes; nunca reduzcas el tamaño de la tipografía.
  • Fuente: Atkinson Hyperlegible (diseñada para legibilidad), con las alternativas a continuación. Cuerpo 400, títulos 700.
  • Menos elementos por imagen: aproximadamente 5 nodos por fila, dos filas como máximo.

Tokens

:root{
  --bg:#fff;          /* siempre blanco */
  --ink:#1d2520;      /* texto principal, trazos principales */
  --muted:#5f6561;    /* texto secundario, etiquetas en líneas */
  --faint:#9aa19c;    /* nodos inactivos, rutas secundarias/opcionales */
  --line:#e4e4e0;     /* bordes de tarjetas, divisores, cuadrícula */
  --tint:#f4f2ef;     /* relleno poco común: chips de código, una fila resaltada */
  --accent:#3b7a57;   /* el ÚNICO color: la ruta que importa */
  --bad:#9a4b3c;      /* solo para una marca de "no / bloqueado", nunca decoración */
}
body{font:400 18px/1.4 "Atkinson Hyperlegible",Inter,system-ui,sans-serif;color:var(--ink)}
code{font:15px "Intel One Mono",ui-monospace,monospace}
  • Escala tipográfica: título 26px/700, etiqueta de nodo 18px, subetiqueta y etiquetas de línea 16px. Título con letter-spacing:-.01em. Los números usan font-variant-numeric:tabular-nums.
  • Trazos: bordes 1px. Conectores 1.5px, stroke-linecap:round. Nada más grueso que 2px.
  • Radios: tarjetas 10px, chips 8px, píldora de token 999px. Sin otros valores.
  • Espaciado: rejilla de 8px. Relleno del cuerpo 24px. Relleno de tarjeta 14px 18px. Separación entre nodos 96-120px, para que quepa una etiqueta de línea.
  • Uso del acento: una ruta, un borde o un chip. Si dos cosas son verdes, una de ellas no debería serlo.

Lienzo

  • Ancho = contenido + 48px de relleno. Típico 600-1100. Nunca ancho completo "para llenar". El contenido comienza arriba a la izquierda.
  • Filas: alto del contenido + 48px, dividido por 19, redondeado hacia arriba. Un flujo de una fila ocupa 9-11 filas; dos niveles 16-20. Máximo 30.
  • Ancho y bajo es mejor que alto. Prefiere un flujo de izquierda a derecha; salta a una segunda fila antes de volverse alto.
  • El estilo base es blanco, 16px de relleno, box-sizing:border-box, overflow:hidden. Establece body{padding:24px} y el fondo tú mismo de todas formas.

Diseño

  • Orden de lectura: título arriba a la izquierda, luego de izquierda a derecha, luego de arriba a abajo. La animación sigue el mismo orden.
  • El título es una oración simple que expresa la conclusión ("Un acierto de caché omite la base de datos"), no un tema ("Caché").
  • Tarjetas solo para cosas que existen (un servicio, una tabla, una cuenta, un paso). Las etiquetas, valores y notas son texto sin formato.
  • Conectores: superposición SVG (position:absolute;inset:0;overflow:visible) en el mismo padre posicionado que los nodos. Mide los extremos con getBoundingClientRect(); nunca codifiques coordenadas. Deja un espacio de 8px entre la línea y la tarjeta.
  • Punta de flecha: un camino de chevron abierto l5 4-5 4 en el color de la línea. Sin triángulos rellenos, sin valores predeterminados de <marker>.
  • Líneas rectas primero. Curvas solo para rodear algo: una cúbica, tangentes horizontales (C midX y1, midX y2, x2 y2).
  • Una ruta que no ocurre: color --faint, discontinua 2 5. Una ruta bloqueada: igual, más una pequeña x de color --bad en su centro.
  • Las etiquetas de línea se sitúan centradas sobre la línea en --muted 16px, 2-3 palabras.
  • Datos en movimiento (una solicitud, una cantidad, un mensaje) son una pequeña píldora oscura: fondo --ink, texto blanco 16px, radio 999px. Termina estacionado donde llegó, para que la imagen estática lo muestre.
  • Gráficos: un eje, línea de 2px o barras finas, líneas de cuadrícula en --line, la serie que importa en --accent y el resto en --faint, etiquetas directas en lugar de leyenda, valores en tinta (nunca en el color de la serie). Si un número es el punto, muestra el número, no un gráfico.

Animación

  • Cada escena termina en un fotograma final significativo. Sin salidas, sin bucles, sin desvanecimientos. La animación total termina al menos 200ms antes de duration_ms.
  • Total típico 2-4s. Quédate por debajo de 6s a menos que sea una historia de varios pasos. duration_ms = último final + 300ms.
  • Orden: título, luego nodos en orden de lectura, luego se dibujan los conectores, luego las etiquetas, luego el token en movimiento, luego el cambio de estado final. Una cosa comienza mientras la anterior se asienta (superposición ~0.1-0.3s); nunca todo a la vez, nunca estrictamente uno tras otro.
  • Valores:
QuéDesdeDuraciónFacilidad (GSAP / cubic-bezier)
Títuloopacidad 0, y 80.6spower3.out / .16,1,.3,1
Tarjetaopacidad 0, y 12, escala .970.8s, escalonado 0.12sexpo.out / .16,1,.3,1
Dibujo del conectordashoffset L+40.7s, escalonado 0.1-0.3spower2.inOut / .65,0,.35,1
Punta de flechaopacidad 00.2s, cuando termina la línealineal
Etiqueta de líneaopacidad 0, y 40.5spower3.out
Viaje del tokena lo largo de la línea1.0spower2.inOut
Intercambio de valorantiguo: y -8, desenfoque 3px, fuera 0.35s; nuevo: y 8, desenfoque 3px, dentro 0.5spower2.in / power3.out
  • Animar solo transform, opacity, filter: blur y el stroke-dashoffset de SVG.
  • Nunca desde scale(0); comienza en .97. Sin rebote, sin sobrepaso, sin elástico. La única excepción: un pequeño pop back.out(1.6) para una marca de "no".
  • Nunca animes texto que el lector deba leer mientras se mueve; deja que aterrice, luego mueve lo siguiente.
  • Metáfora física cuando encaje: si la cosa es una carta, una factura o una tarjeta, muévela como el objeto real.

Librerías

Elige la librería según lo que sea la imagen, antes de escribir cualquier HTML. Hacer a mano lo que una librería ya hace (un diseño de fuerza, una fórmula matemática, resaltado de código) se ve peor y se rompe más.

La imagen esUsaPor qué
Tarjetas y flechas, un flujo, una secuencia de pasosTarjetas HTML + superposición SVG + timeline GSAPControl total del estilo; GSAP ordena los pasos
Una entrada corta, una lista que apareceAnimación animate + stagger, o @keyframes CSSMenos código que una timeline
Un gráfico con muchos nodos cuyas posiciones no puedes elegir a manoelkjs (diseño en capas) o d3-force, luego dibuja en nuestro estiloLa matemática del diseño es difícil de hacer bien a mano
Un gráfico real (ejes, muchos puntos, una escala)d3 (escalas, ejes, formas) estilizado a manoChart.js solo para un bar/line rápido; reestiliza sus valores predeterminados
Matemáticas, fórmulasKaTeXTipografía matemática real
Códigohighlight.js con el tema github, fuente 15pxColores legibles sobre blanco
Muchas partículas, una simulación, física<canvas> con rAF, impulsado por performance.now()El DOM es demasiado lento para cientos de elementos
Algo 3Dthree.js (módulo ES + importmap)Solo cuando la profundidad es el punto
Una sensación de "idea / boceto"rough.jsLíneas dibujadas a mano a propósito

Nunca Mermaid para explicaciones: su apariencia predeterminada lucha contra este estilo. Usa elkjs para el diseño en su lugar.

Fijadas, todas verificadas en cdn.jsdelivr.net (prefijo https://cdn.jsdelivr.net/npm/):

Diseño asíncrono (elkjs, fuentes, KaTeX): construye la escena, luego inicia la timeline. El fotograma final se toma en duration_ms, por lo que todo debe terminar a tiempo.

Problemas comunes:

  • Motion: el fotograma clave final debe usar las mismas funciones de transformación que el inicial. ['translateY(12px) scale(.97)','none'] renderiza scale(0), por lo que el elemento desaparece. Escribe 'translateY(0px) scale(1)'.
  • Dibujo de línea: nunca uses pathLength="1"; el tween de offset de GSAP lo ignora y la línea aparece completa. Mide L=p.getTotalLength(), establece strokeDasharray:${L} ${L+4}``, strokeDashoffset:L+4 (el +4 oculta el punto de la tapa redonda), anima el offset a 0. Una ruta discontinua no se puede dibujar de esta manera; desvanécela.
  • Inserta el SVG medido y las etiquetas antes de iniciar la animación, y mide antes de aplicar cualquier transformación.
  • Scripts al final de <body>; carga la etiqueta CDN antes del script en línea.

Nunca

  • Gradientes, brillo, neón, glassmorphism, sombras pesadas o de color.
  • Púrpura, o más de un tono de acento. Fondos de color en áreas grandes.
  • Emoji o decoración de fuente de iconos. Un pequeño SVG en línea con trazo de 1.5px si un icono es realmente necesario.
  • Todo en cajas. Tarjeta héroe centrada. Una tarjeta dentro de una tarjeta.
  • Un lienzo estirado a todo lo ancho con el contenido flotando en el medio.
  • Flechas que se cruzan entre sí, líneas que tocan tarjetas, etiquetas que se superponen a líneas.
  • Leyendas que repiten el título. Más de ~12 palabras de prosa dentro de la imagen.
  • Texto por debajo de 16px, o una fuente diferente a la anterior, en una explicación.

Después del renderizado, lee el PNG y verifica: espacios, superposiciones, texto recortado, lado derecho vacío.

Esqueleto

<style>/* tokens arriba */ h2{font-size:26px;font-weight:700;letter-spacing:-.01em;margin:0 0 32px}
.row{position:relative;display:flex;gap:112px;width:max-content}
.node{padding:14px 18px;border:1px solid var(--line);border-radius:10px}
.node small{display:block;color:var(--muted);font-size:16px}
.hot{border-color:var(--accent)} svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
path{fill:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}</style>
<h2>Un acierto de caché omite la base de datos</h2>
<div class="row" id="row">
  <div class="node" id="a">Solicitud<small>GET /user/42</small></div>
  <div class="node hot" id="b">Caché<small>Redis, TTL 5 min</small></div>
  <svg id="s"></svg>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
<script>
const R=row.getBoundingClientRect();
function link(p,q,color){ const a=p.getBoundingClientRect(),b=q.getBoundingClientRect();
  const y=a.top+a.height/2-R.top, x1=a.right-R.left+8, x2=b.left-R.left-8;
  s.insertAdjacentHTML('beforeend',`<path class="l" stroke="${color}" d="M${x1} ${y}H${x2}"/><path class="h" opacity="0" stroke="${color}" d="M${x2-5} ${y-4}l5 4-5 4"/>`); }
link(a,b,'#3b7a57');
s.querySelectorAll('.l').forEach(p=>{const L=p.getTotalLength();gsap.set(p,{strokeDasharray:`${L} ${L+4}`,strokeDashoffset:L+4})});
gsap.timeline()
  .from('h2',{opacity:0,y:8,duration:.6,ease:'power3.out'})
  .from('.node',{opacity:0,y:12,scale:.97,duration:.8,ease:'expo.out',stagger:.12},.2)
  .to('.l',{strokeDashoffset:0,duration:.7,ease:'power2.inOut'},1)
  .to('.h',{opacity:1,duration:.2},1.6);
</script>

Llámalo con width ≈ 560, rows: 10, duration_ms: 2200.

Skills relacionados