¿Qué hace Pixel HUD UI?
Un marco de interfaz de usuario, no solo un tema de color. Tiene tres capas, y un buen resultado usa las tres:
- Fundamentos: una cuadrícula de 4 px, una escala tipográfica ajustada a una fuente pixelada de 12 px, roles de color (cada color significa una cosa), reglas de 1 px en lugar de sombras, movimiento paso a paso.
- Controles: paneles y barras de título, teclas (botones) con intenciones, teclas de icono, pestañas, controles segmentados, filas de lista, campos de formulario, entradas, selectores, casillas de verificación y botones de radio cuadrados, interruptores de lámpara, controles deslizantes de indicador, indicadores de progreso, lámparas, etiquetas, insignias, teclas, menús, tooltips, diálogos, toasts, tablas, bloques de código, prosa, cargadores, estados vacíos. Cada uno tiene tamaños fijos y un modelo de estado compartido (hover, presionado, foco, seleccionado, deshabilitado, carga, error).
- Paletas: tokens
--hud-*, para que el marco se asiente sobre cualquier color, incluida la propia marca de la aplicación.
Archivos
| Archivo | Qué es |
|---|---|
references/design-system.md | La especificación. Principios, fundamentos y la anatomía de cada control, tamaños, estados, cuándo usarlo y accesibilidad. Léelo antes de diseñar. |
assets/pixel-hud.css | La implementación: tokens, variables globales claras bajo [data-skin="pixel"], y las clases de control hud-* |
assets/palettes.css | starward (espacio profundo, oscuro), terminal (gris-verde, oscuro), paper (arena cálida, claro) |
assets/fonts.css | Fusion Pixel 12px (OFL), alojado en jsDelivr; o auto-alojado vía @fontsource |
assets/pixel-caret.js | Cursor de bloque de 3 px opcional para campos de texto (data-pixel-caret) |
assets/demo.html | Cada control en cada estado, con un selector de paleta: la referencia visual |
references/integration.md | Recetas por stack: mapeo de colores de una aplicación, Tailwind, shadcn/ui, React/Next, Vue, ámbito, cambio sin parpadeo, fuentes auto-alojadas |
scripts/check-contrast.mjs | Verificación WCAG para cualquier paleta: node scripts/check-contrast.mjs my.css |
Flujo de trabajo
1. Lee la especificación y la demo
Lee references/design-system.md (al menos los Principios, los Fundamentos y los controles que la tarea necesita) y mira assets/demo.html. La especificación dice por qué cada control se ve como se ve; seguirla es lo que hace que una pantalla se lea como este marco en lugar de "un tema oscuro con una fuente pixelada".
2. Mira el proyecto
Antes de copiar nada, averigua:
- el stack y dónde se carga el CSS global (archivo de diseño,
main.ts,index.html, entrada de Tailwind); - cómo se definen los colores hoy (propiedades personalizadas CSS, tema de Tailwind, variables HSL de shadcn, hex en componentes);
- si esto es una UI nueva o un reestilizado, la única apariencia de la aplicación o un tema intercambiable, toda la página o un área.
Estos deciden el mapeo de colores (paso 4) y evitan que luches contra los estilos de la aplicación.
3. Agrega el kit
Copia pixel-hud.css, fonts.css, palettes.css (si se usa una paleta empaquetada) y pixel-caret.js (si la aplicación tiene entradas de texto) en el proyecto. Orden de carga: fuentes → paletas → pixel-hud.css, después de los estilos base de la aplicación.
4. Elige los colores
- Una paleta empaquetada:
data-hud-palette="starward" | "terminal" | "paper". - Los colores propios de la aplicación: un bloque mapea sus variables a
--hud-*(references/integration.md› Mapeo de colores de una aplicación). Mantiene la marca, agrega el marco. - Una nueva paleta: sigue "新建一套配色" en la especificación.
Luego ejecuta node scripts/check-contrast.mjs <archivo> en cualquier paleta que hayas escrito o mapeado, y corrige cada FALLO: los controles dependen de que los colores de barra, texto y verde sean legibles en cada superficie.
5. Actívalo
<html data-skin="pixel" data-hud-palette="starward">
Un tema intercambiable establece estos antes de la primera pintura (references/integration.md › Cambio sin parpadeo). Para estilizar solo un área, pon ambos atributos en su contenedor.
6. Construye con los controles
Los globales ya manejan el tipo, las esquinas cuadradas, las entradas nativas, los selectores, los controles deslizantes de rango, las casillas de verificación, las barras de desplazamiento, los anillos de foco, la selección y las líneas de barrido. Dale a cada elemento su rol con una clase, siguiendo la especificación para el tamaño y el estado:
| Necesidad | Control (clase) |
|---|---|
| Agrupar información relacionada | .hud-panel + .hud-titlebar (+ .hud-titlebar__actions), cuerpo .hud-panel__body, secciones .hud-subhead |
| Acción principal | .hud-btn.is-solid (intención: accent, go, warn, info, danger) |
| Acción secundaria | .hud-btn |
| Acción solo icono | .hud-icon-btn + aria-label |
| Cambiar vistas | .hud-tabs > .hud-tab[aria-selected] |
| Elegir uno de 2–5 valores | .hud-segmented > button[aria-pressed] |
| Lista navegable | .hud-row[aria-current] |
| Entrada etiquetada | .hud-field > .hud-label + input/select + .hud-help / .hud-error |
| Desplegable | .hud-select > select |
| Sí/no, uno de muchos | .hud-check, .hud-radio (marcas cuadradas) |
| Encendido/apagado instantáneo | button.hud-switch[role=switch][aria-checked] > .hud-switch__knob |
| Nivel / progreso | .hud-gauge + --value (data-state warn/alert) |
| Estado | .hud-lamp[data-state] |
| Valor, ID, parámetro | .hud-tag; conteos .hud-badge; teclas kbd |
| Menús, sugerencias, modal, feedback | .hud-menu, .hud-tooltip, .hud-backdrop > .hud-dialog, .hud-toasts > .hud-toast |
| Datos, código, artículos | table.hud-table, .hud-code, .hud-prose |
| Entrada de comando / chat | .hud-input + data-pixel-caret |
| Esperando, nada que mostrar | .hud-loader, aria-busy en una tecla, .hud-empty |
Pon las clases en el código fuente del componente (JSX, plantillas), pasándolas a través de la prop className/class de una biblioteca de componentes, en lugar de escribir selectores contra los internos del marco: sobreviven a las refactorizaciones y se leen claramente.
Al reestilizar una aplicación existente, primero mapea cada componente existente a la tabla de arriba (una lista corta en tu respuesta ayuda al usuario a seguir), luego aplícalo.
7. Verifica el resultado
- Captura la página (o ábrela) y compárala con
assets/demo.html. - Confirma que la fuente pixelada se cargó (
document.fonts, pestaña Red); un CSP puede bloquear jsDelivr, entonces auto-alójala. - Navega con tabulador: cada control alcanzable, anillos de foco verdes de 1 px visibles.
- Recorre el modelo de estado en los controles principales: hover, presionado, deshabilitado, carga, error.
- El script de contraste pasa para la paleta en uso.
Las reglas que más importan
La especificación tiene el razonamiento completo; estas son las que se rompen con más frecuencia:
- Cuadrado y plano. Sin radio, sin sombras borrosas, sin degradados excepto líneas de barrido. Solo las superposiciones obtienen la sombra de desplazamiento dura.
- Los colores mantienen sus trabajos. Barra = estructura y selección; verde = encendido, énfasis, foco; amarillo = valores; naranja = notas y advertencias; rojo = peligro. El verde usado como decoración deja de significar "encendido".
- Seleccionado = invertido. Relleno de barra con texto oscuro; las filas agregan un borde verde de 3 px. Sobre un fondo de color de barra, hover invierte al revés.
- Una acción principal sólida por área; las acciones lado a lado obtienen cada una su propio color de intención y lo mantienen cuando están deshabilitadas (atenuar, no contornear).
- Las barras de título solo encabezan paneles. Los encabezados de tabla y código usan el tinte suave
--hud-bar-soft. - Los tamaños provienen de la escala: controles de 24/28/32 px, espaciado en la cuadrícula de 4 px, texto de 12/14/16/24/36 px.
Errores comunes
- El marco fuerza
border-radius: 0 !importanten su ámbito. Mantén algo redondo (un avatar) limitando la piel a un contenedor que lo excluya. color-mix()necesita Chrome/Edge 111, Safari 16.2, Firefox 113; para navegadores antiguos establece--hud-bar-soft/--hud-bar-linea colores planos.- Una clase que establece
displaymostraría elementoshidden; el marco vuelve a ocultar[hidden]dentro de su ámbito, así que prefiere el atributohiddenpara alternar. - Los marcos que establecen el valor de un campo desde el código no disparan
input; llama afield.__pixelCaret.update()después de tal cambio si el cursor debe moverse de inmediato. - Las líneas de barrido están en un z-index muy alto con
pointer-events: none; apágalas condata-hud-scanlines="off"donde estorben (capturas de pantalla, aplicaciones de lienzo).