Communitygithub.com

nkurunziza-saddy/surfaces

Define qué aspecto tiene cada elemento de la interfaz: relleno, borde, sombra, radio, estados e iconos.

¿Qué es surfaces?

Este skill establece las reglas para definir las superficies de la interfaz de usuario (UI) web: su relleno, borde, sombra, radio, estados interactivos e iconos. Proporciona un conjunto limitado de recetas para garantizar la consistencia visual entre diferentes pantallas, evitando duplicidades como tener dos tipos diferentes de tarjetas. El skill cubre desde la decisión de si una superficie es necesaria hasta la elección del nivel de elevación (página, elevado, flotante o superpuesto), la forma de dibujar los bordes (sombra o borde), la aplicación de radios concéntricos, la definición de estados (hover, presionado, seleccionado, deshabilitado y focus-visible) y el tratamiento de iconos (un solo conjunto, currentColor, trazo que coincida con el peso del texto). Incluye reglas específicas para modo claro y oscuro, modo de colores forzados (forced-colours), imágenes, scroll y materiales. Está diseñado para ser utilizado con la biblioteca product-ui y es aplicable en cualquier proyecto web que requiera un manejo sistemático y preciso de las superficies de la interfaz de usuario.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/nkurunziza-saddy/hmm-interfaces/tree/HEAD/surfaces

Preguntar en tu IA favorita

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

Documentación

Superficies

Este skill decide de qué está hecho cada elemento: su relleno, borde, sombra, radio, estados e iconos. Elige de una lista corta de recetas, así dos pantallas nunca llevan dos tarjetas diferentes.

Antes de cualquier decisión, aplica product-ui §1 (el diario de gusto y precedencia) y §5 (qué skill es dueño de qué).

Decide en este orden

  1. ¿Se necesita una superficie? Elimina antes de añadir. Un título con espacio alrededor no necesita tarjeta. Nunca anides una tarjeta dentro de otra tarjeta. Por qué: cada contenedor añade un borde que el ojo debe leer.
  2. ¿Qué nivel? Página, elevado, flotante o superpuesto. Un nivel por elemento, elegido por lo que hace, no por cuánto quieres que destaque. elevation.md.
  3. ¿Qué dibuja el borde? La elevación obtiene un anillo de sombra. La estructura obtiene un borde. Nunca ambos en un mismo borde. elevation.md.
  4. ¿Qué radio? Toma el token para el rol del elemento, luego haz que los radios anidados sean concéntricos. elevation.md.
  5. ¿Qué estados? Diseña hover, presionado, seleccionado, deshabilitado y focus-visible como cambios en la superficie, antes de pulir el estado por defecto. states-and-icons.md.
  6. ¿Qué tratamiento de iconos? Un conjunto, currentColor, trazo igualado al texto. states-and-icons.md.
  7. ¿Está permitido un material? Solo cromo flotante sobre contenido que se desplaza. materials-and-edges.md.
  8. Bordes del scroll. Divisores, desvanecimientos, overscroll. materials-and-edges.md.

Los cuatro niveles

NivelParaClaroOscuro
PáginaEl fondoRelleno de fondo, sin sombraRelleno más oscuro, sin sombra
ElevadoTarjetas, controles, la opción seleccionadaBlanco, anillo + 1px de caída + 3px de caída ajustadaUn tono más claro, anillo blanco, caída negra ajustada
FlotanteMenús, popovers, tooltips, toastsBlanco, anillo + 1px de caída + 4px de caída ajustadaDos tonos más claro, anillo blanco, caída negra ajustada
SuperpuestoDiálogos, hojas, paleta de comandos (con un scrim)Blanco, anillo + 1px de caída + 6px de caída ajustadaTres tonos más claro, anillo blanco, caída negra ajustada

Los tokens exactos están en elevation.md. Las reglas detrás de ellos:

  • Un anillo más una caída ajustada. Desenfoque ≤ 8px, desplazamiento ≤ 6px, caídas con una dispersión negativa. Por qué: los desenfoques grandes y suaves se leen como brillo, ensucian la página y parecen generados.
  • El modo oscuro se eleva volviéndose más claro. Las sombras apenas se ven en oscuro, así que la claridad transmite altura y un anillo blanco con baja opacidad transmite el borde.
  • Las sombras son translúcidas y de un solo color. Los grises opacos dejan un halo. Las caídas oscuras permanecen negras.
  • Los hermanos comparten un nivel. Las tarjetas en una fila tienen una sombra, un radio, un relleno.
  • Hover cambia el relleno, no la sombra.

Reglas que no necesitan referencia

  • Los bordes muestran estructura, las sombras muestran elevación. Divisores, inputs, celdas de tabla y estados seleccionados mantienen bordes. Una tarjeta cuyo borde existe solo para elevarla obtiene un anillo.
  • Mantén border: 1px solid transparent debajo de un anillo de sombra. Por qué: el modo de colores forzados elimina las sombras, y el borde aún dibuja un borde.
  • Las imágenes obtienen un contorno interior de 1px: outline: 1px solid negro al 10% (blanco al 10% en oscuro), outline-offset: -1px. Nunca un color teñido, que aparece como un fleco. Omite logotipos y obras de arte transparentes.
  • Radio concéntrico. Exterior = interior + relleno (+ borde), hasta 24px de relleno. Más allá, son superficies separadas.
  • El foco es un anillo, nunca nada. :focus-visible muestra un contorno de acento de 2px con un desplazamiento de 2px; los campos lo toman al ras, como un borde de acento de 2px sin espacio. outline: none sin un reemplazo es un error. El anillo no ocupa espacio de diseño.
  • Los controles deshabilitados no tienen hover, presión ni escala.
  • Iconos: un conjunto por superficie, currentColor, contorno por defecto y relleno cuando está activo. El trazo sigue el peso del texto vecino, 1.5px a 400 hasta 2px a 600.
  • Desenfoque detrás solo en cromo flotante. Nunca en contenido, tarjetas o tablas.
  • Superposiciones desplazables (diálogos, cajones, menús) obtienen overscroll-behavior: contain.

Pares

RotoArregladoPor qué
border: 1px solid #e5e5e5 en una tarjetabox-shadow: var(--elev-raised); border: 1px solid transparentUn borde de solo profundidad se convierte en anillo; los colores forzados aún dibujan un borde
box-shadow: 0 10px 40px rgba(0,0,0,.2)0 0 0 1px a.08, 0 1px 2px a.12, 0 4px 8px -4px a.16Ajustado y nítido vence a grande y suave
Tarjeta oscura con 0 8px 24px #000Relleno más claro más 0 0 0 1px oklch(1 0 0 / .08)Las sombras desaparecen en oscuro; la claridad muestra altura
Radio de tarjeta 8, radio de imagen interior 8, relleno 8Interior 8, exterior 16Las esquinas concéntricas mantienen un espacio uniforme
<img> fundiéndose en una tarjeta blancaoutline: 1px solid oklch(0 0 0 / .1); outline-offset: -1pxEl borde se lee sin un borde
button:focus { outline: none }button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px }Los usuarios de teclado mantienen su lugar
Trazo de icono de 1.5px junto a una etiqueta de peso 600Trazo de 2pxEl peso del trazo coincide con el peso del tallo
Iconos rellenos en cada ranura de la barra de herramientasContorno por defecto, relleno para el activoEl relleno es la señal de estado
backdrop-filter: blur(20px) en una tarjetaUna superficie opacaEl desenfoque pertenece al cromo que flota sobre contenido desplazable

Antes de terminar

PatrónArreglo
box-shadow con desenfoque > 8px o alfa > .2 en UI claroUsa un token de nivel
border más box-shadow haciendo el mismo trabajoAnillo más borde transparente solamente
Anillo de sombra sin border: 1px solid transparentAgrégarlo
Mismo border-radius en un padre y su hijo con rellenoinner + padding para el padre
outline: none o outline: 0 sin reemplazo :focus-visibleAgrega el anillo
:focus (no :focus-visible) estilizando un anilloCambia a :focus-visible
border-width cambiando en un estadoColor, relleno o un borde transparente del mismo ancho
fill="#…" o stroke="#…" codificado en un iconocurrentColor
Dos bibliotecas de iconos importadas en una pantallaUna
backdrop-filter fuera de una barra fija, barra lateral o menú flotanteQuítalo
Lista de superposición sin overscroll-behavior: containAgrégarlo
Corte duro en el borde de un desplazador, o una sombra recortada por overflow: hiddenDesvanece el borde; añade relleno al desplazador

Verifica renderizando claro y oscuro a 2× y recortando un borde de cada nivel. Pasa el ratón, presiona, presiona Tab para enfocar, selecciona y deshabilita cada control y compara el tamaño de la caja antes y después. Alterna colores forzados (DevTools de Chrome, emulación de renderizado) y confirma que cada tarjeta aún tiene un borde.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

nkurunziza-saddy/break

Stress-tests a piece of UI with worst-case data and every reachable state, then reports what broke with a numbered fix for each. Use it when the user types /break, or asks to "break this", "stress-test", "try the worst case", "what happens with long names", "check the empty and error states" or "find the edge cases" on a component or screen.

nkurunziza-saddy/layout

Structure and space in product UI on the web. It sets the spacing scale, grouping, alignment, density (compact or comfortable), hit areas, app shells (sidebar, toolbar, content, inspector), max widths, container-query responsiveness, dropdown and popover sizing, room for long and translated text, layout stability (no shift on load) and sticky elements that must not cover focus.

nkurunziza-saddy/motion

Builds motion for product UI on the web. It decides whether something should move at all, then why, which tool (CSS transition, WAAPI, Motion, spring), which properties, curve, duration, interruption, exit and reduced-motion path, and it writes the code. Also covers stagger and choreography, gestures (drag, flick, sheets), motion tokens and animation performance.

nkurunziza-saddy/pick-library

Picks the right library for a frontend task from a curated, status-checked list, instead of hand-rolling it or installing an abandoned package. Use it when the user asks "what should I use for…", "is there a library for…", or names a package, and when you are about to build a toast, command menu, drawer, date picker, table, virtual list, drag and drop, chart, OTP input, animated number, theme switch, form validation…

Skills relacionados