Claro, oscuro y sistema
theme
pertenece al framework. Guarda la preferencia y aplica
data-theme
antes del primer pintado.
UIThemeToggle
permite cambiarla, también sin JavaScript. Los tokens cambian solos: no escribas reglas por tema.
La paleta
Cada escala tiene 12 pasos: 1 y 2 para fondos, 3 a 5 para controles, 6 a 8 para bordes, 9 y 10 para sólidos, 11 y 12 para texto. El fondo es blanco puro en claro y negro puro en oscuro. El violeta es para la acción principal, el foco, la selección y lo activo: si todo es violeta, nada destaca.
--ui-color-primary-*
--ui-color-surface-*
--ui-color-info-*
--ui-color-success-*
--ui-color-warning-*
--ui-color-danger-*
Tokens de uso
Lee el token de uso, no el paso:
--ui-color-border, no
--ui-color-surface-6. Ningún hex, tamaño o fuente suelto: si te falta algo, se añade a UI. El contrato completo está en
packages/ui/DESIGN.md.
.release-note {
border: var(--ui-border-width) solid var(--ui-color-border);
border-radius: var(--ui-radius-lg);
background: var(--ui-color-surface);
padding: var(--ui-space-4);
color: var(--ui-color-text-soft);
font-size: var(--ui-font-size-md);
}| Nombre | Tipo / valor inicial | Descripción |
|---|---|---|
--ui-color-bg / -bg-subtle
|
color
| Fondo de la página y bandas discretas. |
--ui-color-surface / -surface-raised
|
color
| Card, panel y tabla; popover y modal. |
--ui-color-control / -hover / -active
|
color
| Fondo de un control y sus estados. |
--ui-color-text / -text-soft
|
color
| Texto y texto secundario. |
--ui-color-border / -border-strong / -control-border
|
color
| Separadores, bordes discretos y borde de un campo con 3:1 o más. |
--ui-color-primary / -hover / -contrast
|
color
| Acción principal y texto sobre ella. |
--ui-color-primary-soft / -text / -border
|
color
| Etiqueta o fondo activo discreto, con su texto y su borde. |
--ui-color-danger / -soft / -border / -text
|
color
| La misma forma tienen info, success y warning. |
--ui-font-size-xs … -6xl
|
rem
| Tamaños de texto: lectura en lg, controles en md, títulos de 2xl en adelante. |
--ui-space-* / --ui-radius-*
|
rem
| Espacio en pasos de 0,25rem y radios de xs a xl. |
--ui-control-height-sm / -md / -lg
|
rem
| Altos de los controles, que crecen solos con un puntero táctil. |
--ui-duration-* / --ui-ease-*
|
tiempo
| Movimiento: fast para color, base y slow para un panel. |
Escala fluida
La interfaz crece con la pantalla en un solo sitio, la base global: 16 px hasta 1440, 18 px a 2560 y 21 px a 3840, siempre a partir del tamaño de letra del navegador. Todos los tokens están en
rem, así que crecen a la vez. Lo que se escribe en
px
no crece.
ui: { base: false }
quita la base, y con ella la escala.
Tu marca
Las hojas de
app/styles
se cargan después del módulo: sobrescribe los pasos de una escala y todo lo que los lee cambia con ellos.
/* app/styles/main.css: tu marca, sobre los pasos de cada escala */
:root {
--ui-color-primary-9: #0a7cff;
--ui-color-primary-10: #0067d6;
--ui-radius-md: 0.5rem;
}
:root[data-theme='dark'] {
--ui-color-primary-9: #3b96ff;
--ui-color-primary-10: #66adff;
}
Si tu web ya tiene sus variables,
ui.tokens
acepta valores CSS o referencias a ellas, y cada clave asigna los tokens
--ui-*
que le corresponden.
import { defineMeekoConfig } from '@meekojs/meeko/framework'
export default defineMeekoConfig({
modules: ['@meekojs/ui'],
theme: { default: 'dark' },
ui: {
// Cada clave asigna tokens --ui-*; una referencia var() sigue los temas de tu web.
tokens: {
primary: 'var(--brand-action)',
primaryHover: 'var(--brand-action-hover)',
onPrimary: 'var(--brand-on-action)',
focus: 'var(--brand-focus)',
surface: 'var(--brand-surface)',
text: 'var(--brand-text)',
border: 'var(--brand-border)',
},
defaults: {
button: { shape: 'pill', size: 'md' },
link: { variant: 'outline' },
card: { variant: 'soft' },
},
},
})| Nombre | Tipo / valor inicial | Descripción |
|---|---|---|
primary / primaryHover / onPrimary
|
string
| --ui-color-primary, su hover y el texto sobre ella. |
accentSoft / accentText
|
string
| Fondos y texto de estados activos: --ui-color-primary-soft y -text. |
surface / surfaceHover
|
string
| Superficies y controles, y sus estados. |
text / textSoft / muted
|
string
| Texto principal y secundario. |
border / borderStrong
|
string
| Separadores y contornos. |
focus / danger
|
string
| Foco de teclado y errores. |
font / radius
|
string
| Familia tipográfica y radio base. |
controlHeight / controlPadding
|
string
| Dimensiones de las acciones. |
controlWeight / controlFontSize
|
string
| Peso y tamaño de texto de las acciones. |
Valores por defecto
ui.defaults
admite
button,
link
y
card. La prioridad es: props explícitas, defaults de aplicación y valores de base. Los defaults se aíslan por aplicación y petición SSR.
Textos e idiomas
Los pocos textos que los componentes pintan por su cuenta (el cierre de
UIModal, el estado vacío de
UITable
y de
UICombobox, los nombres de
UIThemeToggle) vienen en español e inglés. Con
@meekojs/i18n
siguen el idioma del documento, sin configurar nada. Sin ese módulo,
ui.locale
elige el idioma; por defecto, español.
ui.messages
sobrescribe textos o añade otros idiomas.
// meeko.config.ts
export default defineMeekoConfig({
modules: ['@meekojs/ui'],
ui: {
// Sin @meekojs/i18n, el idioma de los textos; con él, el respaldo de un idioma sin textos.
locale: 'en',
messages: {
en: { table: { empty: 'Nothing here yet.' } },
fr: {
modal: { close: 'Fermer' },
table: { empty: 'Aucune donnée.' },
select: { empty: 'Aucun résultat', clear: 'Effacer la sélection' },
themeToggle: {
labels: { light: 'Clair', dark: 'Sombre', system: 'Système' },
unknown: 'Changer de thème',
group: 'Thème',
cycle: 'Thème : {current}. Passer à {next}',
},
},
},
},
})
Una prop o un snippet del componente siempre ganan sobre estos textos. Lo que falta en un idioma se toma de su idioma base (pt
para
pt-BR), de
ui.locale
y, por último, del español. El servidor y el cliente eligen el mismo texto, así que la hidratación no cambia nada.
Los tipos
UIOptions,
UITokens
y
UIDefaults
se exportan desde
@meekojs/ui.