Pautas de diseño
Cómo aplicar ranui en una pantalla real: elige un rol y un estado, y deja que los tokens pongan los valores.
Las reglas en sí viven en dos sitios, y esta página enlaza a ellos en vez de repetirlas: la
guía de diseño para el método que vale en cualquier producto, y el
adaptador de implementación de ranui
para los tokens, niveles y reglas de componentes de ranui. Ambos se distribuyen en node_modules/ranui/docs/DESIGN.md. El
sistema de diseño lista cada token y su valor, la
tematización cubre las sobrescrituras en tiempo de ejecución y la
arquitectura de información cubre la estructura de la página.
Úsalas cuando elijas color, espacio, tipografía, profundidad o movimiento para una pantalla hecha con elementos
<r-*>.
Principios
- Claridad antes que personalidad. Lo primero es que la tarea principal y la acción principal sean inconfundibles.
- Reutiliza los controles existentes.
r-button,r-input,r-selectyr-modalya traen el comportamiento de formulario, teclado y accesibilidad; cámbiales el estilo en vez de reconstruirlos. - Decide por rol y por estado. «¿Qué es este texto?» tiene respuesta; «¿qué tamaño se ve bien?» no la tiene. El token del rol pone el valor, y ese valor sigue al tema.
- Diseña todos los estados alcanzables y mira el resultado. El estado normal es uno de ocho, y una sombra que nadie ve solo se descubre en un navegador.
Son puntos de partida. Apártate de uno cuando la pantalla gane con ello, y explica por qué.
Elegir un color
La escalera ya decide cómo se ven el hover y el estado activo; tu trabajo es nombrar el rol.
| El elemento es… | Usa |
|---|---|
| El fondo de una página o superficie | --ran-color-bg / -bg-subtle / -bg-elevated / -bg-muted |
| Algo bajo el puntero o siendo pulsado | --ran-color-bg-hover / -bg-active |
| Texto | --ran-color-text / -text-secondary / -text-disabled |
| Un borde | --ran-color-border / -hover / -active |
| La acción para la que existe la pantalla | --ran-color-primary (con --ran-color-primary-text encima) |
| Un estado | --ran-color-success / -warning / -danger |
| Un enlace | --ran-color-link |
Cada acento tiene un solo significado. El primario es monocromo, así que el azul queda para los enlaces y el anillo de foco; el verde es éxito, el ámbar advertencia y el rojo peligro. Usar rojo para resaltar te deja sin nada con qué decir «peligro» más adelante.
Un hexadecimal crudo, un valor de reserva que no cambia con el tema o uno que nombra un token que no
existe se rompe sin avisar en modo oscuro o anula la declaración entera; las
reglas de color del adaptador
explican cada caso, y verify:design los detecta en el código fuente de ranui.
Espacio y ritmo
Toma los espacios de la escala de 4px y deja que la distancia signifique algo:
- 8px entre elementos dentro de un grupo.
- 16px entre grupos.
- 24–32px entre regiones.
Un espacio menor significa una relación más estrecha, así que basta un espacio fuera de la escala para romper el ritmo. Da a cada espacio un único responsable: cuenta el margen del hijo y el relleno del padre antes de añadir un tercer espacio entre ellos.
Elegir la tipografía
Pregunta qué rol cumple el texto (título, etiqueta, cuerpo, botón, monoespaciado); la fuente, el tamaño, el grosor y la altura de línea salen de la escala tipográfica. Un texto de verdad excepcional, como el aviso de un gesto sobre un vídeo, queda mejor con su propio token de componente que forzado al rol más cercano.
Profundidad: sombra y apilamiento
Elige el nivel de sombra según lo que es el elemento: una superficie dentro del flujo, una capa flotante o un diálogo que bloquea. Una capa que cae al nivel de las tarjetas parece clavada a la página.
Incrustar capas de ranui en tu propio marco. La escalera de z-index
empieza en 1000, así que una capa portalizada supera por sí sola el marco habitual de la página. Una capa con position: fixed
que se queda dentro de su propio shadow DOM (el diálogo de r-modal) solo escapa hasta su
contexto de apilamiento ancestro más cercano. Si envuelves el contenido incrustado en algo que cree uno
(isolation, opacity < 1, transform, filter, will-change), sube ese envoltorio solo mientras una
capa esté realmente abierta:
.embed {
isolation: isolate; /* cheap: no z-index of its own, so nothing is promoted */
}
/* Escalate only while a real overlay is open — never "just in case" */
.embed:has(r-modal[open]),
.embed:has(r-modal[closing]) {
position: relative;
z-index: 100;
}Un z-index permanente en el envoltorio sube todo lo que contiene, contenido estático incluido, por encima de tu
cabecera fija durante todo el desplazamiento; este sitio llegó a publicarse así una vez. Coincide con closing además
de con open: la máscara sigue pintándose durante su transición de cierre.
Movimiento
La respuesta frecuente (hover, foco, pulsación) es inmediata. Cuando el movimiento explica un cambio, la respuesta se queda
en 0–100ms, la entrada dura 250–400ms y desacelera, y la salida dura 150–200ms y acelera.
Permite interrumpirlo y respeta prefers-reduced-motion.
Nunca dejes que una propiedad de color haga transición. El CSS no puede saber por qué cambió un color, así que una transition
sobre background-color, color, border-color, box-shadow, fill o stroke también se dispara cuando cambia el
tema: cada elemento se funde a su propio ritmo cuando la página ya ha cambiado. Anima
transform y opacity en su lugar. transition: all y un transition: 0.2s pelado también incluyen el color.
Estados y textos
Todo estado alcanzable forma parte del diseño: hover, activo, foco, deshabilitado, cargando, vacío, error.
El hover corresponde a bg-hover / border-hover, el activo a bg-active y el foco al anillo de foco. Nada que no
se pulse debe parecer pulsable: r-card solo reacciona al hover con hoverable.
El texto también es parte del sistema:
- Los botones nombran el resultado, con el objeto cuando el contexto no lo aporta: «Eliminar miembro». Un diálogo con el objeto claro puede decir «Eliminar»; evita un «Aceptar» genérico.
- Los errores dicen qué pasó y luego cómo arreglarlo. ✅ «La compilación falló: el paquete supera el límite de tamaño. Redúcelo o sube el límite.» ❌ «La operación falló, inténtalo de nuevo.»
- Las confirmaciones describen el cambio, no el éxito, y aparecen solo cuando está confirmado. ✅ «Proyecto eliminado» ❌ «Operación exitosa».
- Deja que el contexto quite lo redundante: un diálogo titulado «Eliminar proyecto» no necesita un botón que diga «Eliminar el proyecto permanentemente, para siempre».
Accesibilidad
- Cumple el contraste WCAG AA del texto contra su fondo.
- Nunca señales un estado solo con color: acompáñalo de un icono, una etiqueta o texto.
- Todo elemento interactivo conserva un anillo de foco visible (
--ran-focus-ring, ooutline: 2px solid var(--ran-color-focus); outline-offset: 2px). - Todo se alcanza con el teclado.
- Respeta
prefers-reduced-motionyprefers-color-scheme.
Ratón y dedo, estrecho y ancho
Ni la forma de apuntar ni el tamaño de la ventana son el objetivo secundario.
- Los arrastres, deslizadores y gestos usan Pointer Events, con
touch-action: noneen la superficie exacta de arrastre. Untouch-action: nonesin ningún manejador de puntero detrás es un control roto. - Lo que solo aparece con hover necesita una alternativa táctil.
trigger="hover"enr-selector-popoverse convierte en un clic en dispositivos táctiles; todo lo que construyas debería hacer lo mismo. - Prefiere tamaños relativos al viewport (
min(560px, calc(100vw - 32px)),clamp()) a inventar un punto de corte: ranui no tiene token de punto de corte, así que cada punto de corte fijo es un número que alguien mantiene. - Nunca ocultes en móvil la única forma de hacer algo. Reorganízalo en su lugar.
- Una posición medida solo es correcta hasta el siguiente reflujo. Todo lo que se derive de
getBoundingClientRect()queda obsoleto al redimensionar, cuando el contenedor se reorganiza y, en un panel portalizado, al desplazarse. Cargar con un ancho estrecho no prueba redimensionar hasta ese ancho, que es donde esto se rompe.
Lo que la biblioteca comprueba de forma mecánica
pnpm -F ranui verify:design comprueba nueve reglas en el código fuente de ranui: valores de reserva de color que no
cambian con el tema, literales de color crudos, las escalas de espacio y de tamaño, arrastres solo para ratón, reglas de :host que rompen
hidden, valores de reserva que nombran tokens no declarados, componentes que buscan en su propio árbol shadow y árboles shadow
construidos fuera del constructor. Una línea que rompe una regla a propósito lo indica con
design-ok: <rule> <reason>. Las comprobaciones solo cubren las raíces de código configuradas; una aplicación que
usa ranui ejecuta sus propias comprobaciones y revisa sus propias páginas.
Ejemplos de diseño
Esquemas derivados de los tokens base de ranui, no componentes reales.
Alinea las filas
Cuando una fila recibe más contenido, mantén su texto alineado con las demás y sus acciones en la misma columna.
Coordina las esquinas anidadas
Si hacen falta ambos bordes, resta el margen interior al radio exterior: 16 − 4 = 12. Las curvas comparten centro y mantienen una separación uniforme.
--ran-radius-lg − --ran-space-1 = --ran-radius-mdFacilita pulsar iconos pequeños
El icono mide 16px y su área de clic se amplía a 32px para facilitar la interacción. Elige el tamaño según se use ratón o pantalla táctil y separa las áreas vecinas.
--ran-size-1 · --ran-size-7Evidencia y aceptación
El apartado verificar un cambio de la guía dice qué comprobar en un navegador real y qué informar: lo que observaste, lo que solo dedujiste y lo que no pudiste comprobar. La revisión de un agente no es la aceptación del usuario.