orbital-ds 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/AGENTS.md +145 -80
  2. package/README.md +87 -73
  3. package/components.manifest.json +1326 -1267
  4. package/contract.json +226 -168
  5. package/dist/hooks/use-ds-messages.d.ts +36 -0
  6. package/dist/hooks/use-ds-messages.js +12 -0
  7. package/dist/hooks/use-ds-motion.d.ts +17 -0
  8. package/dist/hooks/use-ds-motion.js +50 -0
  9. package/dist/lib/i18n.d.ts +46 -0
  10. package/dist/lib/i18n.js +109 -0
  11. package/dist/lib/motion.d.ts +74 -0
  12. package/dist/lib/motion.js +97 -0
  13. package/dist/styles.css +876 -528
  14. package/dist/themes/friendly.css +362 -318
  15. package/dist/themes/friendly.meta.json +75 -14
  16. package/dist/themes/friendly.scoped.css +362 -318
  17. package/dist/themes/qratia.meta.json +42 -12
  18. package/dist/themes/tactile.css +575 -429
  19. package/dist/themes/tactile.fonts.css +3 -2
  20. package/dist/themes/tactile.guide.md +82 -49
  21. package/dist/themes/tactile.meta.json +175 -16
  22. package/dist/themes/tactile.scoped.css +575 -429
  23. package/dist/themes/twitter.css +354 -298
  24. package/dist/themes/twitter.meta.json +83 -61
  25. package/dist/themes/twitter.scoped.css +354 -298
  26. package/dist/themes/zyro.css +443 -389
  27. package/dist/themes/zyro.meta.json +67 -14
  28. package/dist/themes/zyro.scoped.css +443 -389
  29. package/dist/ui/accordion.js +5 -5
  30. package/dist/ui/alert-dialog.js +3 -3
  31. package/dist/ui/alert.d.ts +1 -1
  32. package/dist/ui/alert.js +9 -3
  33. package/dist/ui/attachment.d.ts +1 -1
  34. package/dist/ui/attachment.js +4 -4
  35. package/dist/ui/avatar.js +6 -6
  36. package/dist/ui/ayuda.js +3 -2
  37. package/dist/ui/badge.d.ts +1 -1
  38. package/dist/ui/badge.js +9 -3
  39. package/dist/ui/banner.d.ts +14 -0
  40. package/dist/ui/banner.js +88 -0
  41. package/dist/ui/breadcrumb.js +7 -3
  42. package/dist/ui/bubble.js +6 -6
  43. package/dist/ui/button-group.js +4 -4
  44. package/dist/ui/button.d.ts +1 -1
  45. package/dist/ui/button.js +5 -5
  46. package/dist/ui/calendar.js +33 -6
  47. package/dist/ui/card.js +4 -4
  48. package/dist/ui/carousel.js +15 -8
  49. package/dist/ui/chart.js +7 -3
  50. package/dist/ui/checkbox.js +1 -1
  51. package/dist/ui/combobox.js +7 -7
  52. package/dist/ui/command.js +13 -11
  53. package/dist/ui/context-menu.js +8 -8
  54. package/dist/ui/dialog.js +10 -6
  55. package/dist/ui/drawer.js +9 -9
  56. package/dist/ui/dropdown-menu.js +8 -8
  57. package/dist/ui/empty.js +3 -3
  58. package/dist/ui/field.js +2 -2
  59. package/dist/ui/hover-card.js +1 -1
  60. package/dist/ui/i18n-provider.d.ts +11 -0
  61. package/dist/ui/i18n-provider.js +18 -0
  62. package/dist/ui/icon-tile.d.ts +1 -1
  63. package/dist/ui/input-group.d.ts +1 -1
  64. package/dist/ui/input-group.js +11 -9
  65. package/dist/ui/input-otp.js +3 -3
  66. package/dist/ui/input.js +1 -1
  67. package/dist/ui/item.d.ts +1 -1
  68. package/dist/ui/item.js +3 -3
  69. package/dist/ui/kbd.js +1 -1
  70. package/dist/ui/label.js +1 -1
  71. package/dist/ui/marker.d.ts +1 -1
  72. package/dist/ui/marker.js +2 -2
  73. package/dist/ui/menubar.js +9 -9
  74. package/dist/ui/message-scroller.js +5 -2
  75. package/dist/ui/message.js +2 -2
  76. package/dist/ui/motion-provider.d.ts +11 -0
  77. package/dist/ui/motion-provider.js +16 -0
  78. package/dist/ui/native-select.js +4 -4
  79. package/dist/ui/navigation-menu.js +7 -6
  80. package/dist/ui/pagination.js +19 -11
  81. package/dist/ui/popover.js +2 -2
  82. package/dist/ui/progress.js +2 -2
  83. package/dist/ui/questionnaire.js +20 -15
  84. package/dist/ui/radio-group.js +2 -2
  85. package/dist/ui/resizable.js +2 -2
  86. package/dist/ui/scroll-area.js +3 -3
  87. package/dist/ui/select.js +6 -6
  88. package/dist/ui/separator.js +1 -1
  89. package/dist/ui/sheet.js +6 -4
  90. package/dist/ui/sidebar.js +42 -30
  91. package/dist/ui/skeleton.js +1 -1
  92. package/dist/ui/slider.js +6 -6
  93. package/dist/ui/sonner.js +25 -8
  94. package/dist/ui/spinner.js +4 -1
  95. package/dist/ui/switch.js +2 -2
  96. package/dist/ui/table.js +3 -3
  97. package/dist/ui/tabs.js +5 -5
  98. package/dist/ui/textarea.js +1 -1
  99. package/dist/ui/toast.js +15 -12
  100. package/dist/ui/toggle-group.js +2 -2
  101. package/dist/ui/toggle.js +6 -4
  102. package/dist/ui/tooltip.js +2 -2
  103. package/docs/CONTRACT.md +183 -153
  104. package/package.json +160 -142
  105. package/scripts/brand-core.mjs +153 -0
  106. package/scripts/doctor.mjs +128 -7
  107. package/scripts/i18n.mjs +111 -0
  108. package/scripts/init.mjs +294 -57
  109. package/scripts/setup.mjs +99 -0
package/AGENTS.md CHANGED
@@ -1,80 +1,145 @@
1
- # orbital-ds — guía para agentes de IA
2
-
3
- Sistema de diseño: **estructura común + temas + componentes** sobre Base UI y Tailwind v4.
4
- Todo está pensado para que un agente pueda usarlo, ampliarlo y comprobar su trabajo sin
5
- adivinar. Lee antes: `README.md`, `docs/CONTRACT.md`, `contract.json` y
6
- `components.manifest.json` (qué componentes hay, cómo se importan y qué `data-slot` exponen).
7
-
8
- ## Reglas (obligatorias)
9
-
10
- 1. **Solo variables.** Un componente no escribe colores, medidas, sombras, z-index ni
11
- duraciones: pide un hueco a una variable (`--ds-*` o las de color de shadcn). Si falta el
12
- hueco, **añade el token** con un valor que deje el aspecto como estaba y úsalo.
13
- 2. **Añadir, nunca sustituir.** Un componente nuevo es un fichero nuevo en `src/ui/`. No se
14
- reescribe ni se renombra uno existente para otro fin. No uses `--overwrite` de la CLI de
15
- shadcn sin aprobación expresa. Quitar o renombrar algo público = versión **mayor**.
16
- 3. **Nombres en inglés.** Tokens, props y valores de variantes. Variables propias con el
17
- prefijo `--ds-`; las que Tailwind convierte en utilidades (`--color-*`, `--radius-*`,
18
- `--shadow-*`) siguen su convención. Las privadas de un tema llevan el prefijo del tema
19
- (`--zy-*`).
20
- 4. **Un solo motor: Base UI.** Nada de Radix. `asChild` no existe: se usa `render`.
21
- 5. **«Sin sombra» es `0 0 #0000`**, nunca `none` (invalida todo el `box-shadow`, anillo de
22
- foco incluido).
23
- 6. **Un tema cumple el contrato completo** (`contract.json`) y define en `:root` todo
24
- `--ds-*` que defina el tema base.
25
- 7. **La marca de una app vive en SU `brand.css`**, no en el tema del paquete. Para
26
- personalizar una app (color, radio, fuentes) edita ese fichero; nunca `node_modules` ni
27
- los temas. `pnpm exec orbital-ds-init` lo crea sin sobrescribir.
28
-
29
- ## Cómo cambiar el aspecto
30
-
31
- - **Valores** (color, forma, fuentes, escala, sombras, espaciado, materiales, sidebar):
32
- variables del tema en `src/themes/<tema>.css`.
33
- - **Personalidad de un elemento** (por ejemplo, botones en píldora con degradado): reglas en
34
- la sección «PERSONALIDAD» del tema, dirigidas a los ganchos del DOM —`data-slot`,
35
- `data-variant`, `data-size`, `data-active`, `data-state`— y escritas solo con variables. Van
36
- **sin capa** para ganar a las utilidades; define también hover y active.
37
- - **Estructura** distinta de un componente (otro layout): variante del componente, no tema.
38
-
39
- ## Cómo comprobar tu trabajo
40
-
41
- ```bash
42
- pnpm check:ds # contrato de tema, repetidos, sombras, fugas, valores fijos y API pública
43
- pnpm verify # doctor + typecheck + build
44
- pnpm manifest # regenera components.manifest.json tras añadir componentes
45
- ```
46
-
47
- Si `pnpm check:ds` falla, **corrige la causa**; no lo desactives ni lo rodees.
48
-
49
- ## Añadir un componente
50
-
51
- 1. Fichero en `src/ui/<nombre>.tsx` (un componente = un fichero; sin barril).
52
- 2. `data-slot="<nombre>"` en su raíz y en las partes relevantes.
53
- 3. Solo tokens. Importa `cn` de `../lib/utils`; los demás componentes, de `./<otro>`.
54
- 4. Dependencias de terceros: opcionales (`peerDependenciesMeta`), nunca obligatorias.
55
- 5. `pnpm manifest`, `pnpm verify`; versión **menor** (añadido compatible).
56
-
57
- ## Crear un tema
58
-
59
- Copia `themes/qratia.css` (o `zyro.css`), cambia valores, no quites ninguno, añade
60
- `<tema>.fonts.css` con el `@import url()` de sus fuentes y ejecuta `pnpm check:ds`.
61
-
62
- ## Estándar de integración (cómo debe ajustarse una app)
63
-
64
- Para que una app (o un agente que la edite) use orbital-ds sin romper nada:
65
-
66
- 1. **La marca vive solo en `brand.css`.** Ninguna regla de color propia fuera de ese fichero; jamás se edita el paquete.
67
- 2. **Solo variables públicas.** Nada de variables privadas de un tema (por ejemplo `--zw-*`): se renombran sin aviso de versión mayor. Usa `--ds-*` y los tokens del contrato.
68
- 3. **Sin `!important` ni selectores propios** para vencer a la librería (lateral, raíl, botones). Si algo no se puede ajustar con un token, es un hueco de la librería: abre un issue.
69
- 4. **El tema se elige con un solo `@import`** (o `pnpm theme`). Los temas con ámbito (`*.scoped.css`) son solo para un banco de pruebas; la marca (`brand.css`) gana siempre, también sobre ellos.
70
- 5. **Patrón de página.** La cabecera lleva solo botón de menú, título y, siempre visibles, idioma y tema (y avisos si la app los tiene). El subtítulo y las acciones de la vista van al inicio del contenido, centrado en un ancho máximo; solo un lienzo (mapa, kanban, editor) ocupa todo el ancho.
71
- 6. **Cada tema se documenta y se elige informado.** Lee `orbital-ds/themes/<tema>.guide.md` y su ficha `<tema>.meta.json` (esencia, gesto firma, paleta, accesibilidad, qué valores son aproximados) antes de usar o ajustar un tema.
72
- 7. **Comprueba antes de dar algo por bueno:** `pnpm exec orbital-ds-doctor --css src/brand.css` y el `verify` de la app.
73
-
74
- ### Accesibilidad (WCAG 2.2)
75
-
76
- - **Mínimo exigible: AA.** Texto 4,5:1; texto grande y controles 3:1. `pnpm check:ds` falla si un par principal de texto sobre su superficie (texto/fondo, tarjeta, popover, primario, secundario, lateral, destructivo) o un texto de estado (info, danger, warning, success, neutral) baja de 4,5:1.
77
- - **Objetivo: AAA en el texto del cuerpo** (7:1 para texto/fondo y texto/tarjeta). Se mide con `pnpm check:ds -- --aaa` y avisa, no falla: WCAG no aconseja exigir AAA a todo el sitio. Hoy todos los temas lo cumplen.
78
- - **Excepciones declaradas, nunca silenciosas.** Si un tema no puede cumplir un par (el azul de marca de Twitter con texto blanco da 3:1), lo declara en su ficha, en `a11y.exceptions`, con su porqué; el doctor lo muestra como aviso.
79
- - **Foco siempre visible** (anillo de 3:1 como mínimo) y sin que otro elemento lo tape.
80
- - **Una marca nueva debe volver a pasar el doctor.** Cambiar `--primary` obliga a revisar `--primary-foreground`, `--link` y `--ring`.
1
+ # orbital-ds — guía para agentes de IA
2
+
3
+ Sistema de diseño: **estructura común + temas + componentes** sobre Base UI y Tailwind v4.
4
+ Todo está pensado para que un agente pueda usarlo, ampliarlo y comprobar su trabajo sin
5
+ adivinar. Lee antes: `README.md`, `docs/CONTRACT.md`, `contract.json` y
6
+ `components.manifest.json` (qué componentes hay, cómo se importan y qué `data-slot` exponen).
7
+
8
+ ## Reglas (obligatorias)
9
+
10
+ 1. **Solo variables.** Un componente no escribe colores, medidas, sombras, z-index ni
11
+ duraciones: pide un hueco a una variable (`--ds-*` o las de color de shadcn). Si falta el
12
+ hueco, **añade el token** con un valor que deje el aspecto como estaba y úsalo.
13
+ 2. **Añadir, nunca sustituir.** Un componente nuevo es un fichero nuevo en `src/ui/`. No se
14
+ reescribe ni se renombra uno existente para otro fin. No uses `--overwrite` de la CLI de
15
+ shadcn sin aprobación expresa. Quitar o renombrar algo público = versión **mayor**.
16
+ 3. **Nombres en inglés.** Tokens, props y valores de variantes. Variables propias con el
17
+ prefijo `--ds-`; las que Tailwind convierte en utilidades (`--color-*`, `--radius-*`,
18
+ `--shadow-*`) siguen su convención. Las privadas de un tema llevan el prefijo del tema
19
+ (`--zy-*`).
20
+ 4. **Un solo motor: Base UI.** Nada de Radix. `asChild` no existe: se usa `render`.
21
+ 5. **«Sin sombra» es `0 0 #0000`**, nunca `none` (invalida todo el `box-shadow`, anillo de
22
+ foco incluido).
23
+ 6. **Un tema cumple el contrato completo** (`contract.json`) y define en `:root` todo
24
+ `--ds-*` que defina el tema base.
25
+ 7. **La marca de una app vive en SU `brand.css`**, no en el tema del paquete. Para
26
+ personalizar una app (color, radio, fuentes) edita ese fichero; nunca `node_modules` ni
27
+ los temas. `pnpm exec orbital-ds-init` lo crea sin sobrescribir.
28
+
29
+ ## Cómo cambiar el aspecto
30
+
31
+ - **Valores** (color, forma, fuentes, escala, sombras, espaciado, materiales, sidebar):
32
+ variables del tema en `src/themes/<tema>.css`.
33
+ - **Personalidad de un elemento** (por ejemplo, botones en píldora con degradado): reglas en
34
+ la sección «PERSONALIDAD» del tema, dirigidas a los ganchos del DOM —`data-slot`,
35
+ `data-variant`, `data-size`, `data-active`, `data-state`— y escritas solo con variables. Van
36
+ **sin capa** para ganar a las utilidades; define también hover y active.
37
+ - **Estructura** distinta de un componente (otro layout): variante del componente, no tema.
38
+ - **Un solo sitio.** Todos los temas son `conformance: strict`: sus reglas de personalidad solo
39
+ leen variables, y estilizan familias completas de piezas. Para adaptar el aspecto de una app
40
+ basta con su `brand.css`; para cambiar un tema, su bloque de VARIABLES. Si una regla necesita
41
+ un valor que no existe, añade la variable a la estructura (`src/styles.css`) con un valor
42
+ neutro y dásela en el tema.
43
+
44
+ ## Movimiento (animación)
45
+
46
+ - **El tema gobierna el «cómo»**: ritmo (`--ds-motion-*`), curvas (`--ds-ease-*`) y coreografía
47
+ (`--ds-motion-distance`, `-scale`, `-blur`, `--ds-spring-bounce`, `--ds-motion-stagger`,
48
+ `--ds-motion-press-scale`). Cada tema trae el suyo de fábrica; la app lo ajusta en `brand.css`.
49
+ - **La app decide el «qué» y el «cuándo»** con **Motion** (librería oficial, opcional): una vez
50
+ `<DsMotionProvider>` en la raíz y los presets del tema con `useDsMotion()` (`fadeUp`,
51
+ `scaleIn`, `list`, `press`, `spring`). Para animar un componente existente:
52
+ `render={<motion.div {...m.fadeUp} />}`.
53
+ - Los componentes del paquete animan con CSS y nunca dependen de Motion. Ninguna duración, curva
54
+ ni capa se escribe a mano (el doctor lo comprueba también dentro de valores arbitrarios).
55
+ - Otras librerías: `readDsTransition()` (`orbital-ds/lib/motion`) da duración y curva CSS.
56
+
57
+ ## Idioma (i18n)
58
+
59
+ - Los textos PROPIOS de los componentes (cerrar, cargando, paginación, carrusel, lateral,
60
+ cuestionario…) salen de `useDsMessages()` y sus catálogos (`orbital-ds/lib/i18n`: en, es,
61
+ pt-BR). **Ningún componente escribe un texto visible o accesible a mano**: el doctor lo rechaza
62
+ (`aria-label="…"`, `sr-only`, `?? "…"`, `title="…"`).
63
+ - Un texto nuevo = una clave nueva en los TRES catálogos (el tipo obliga a tenerla en todos).
64
+ - La app pasa su idioma una vez: `<DsI18nProvider locale={i18n.language}>` (con i18next,
65
+ `useTranslation().i18n.language`). Un texto concreto se sobrescribe con `messages`. Sin
66
+ provider, inglés. Otro idioma cae a su base (`es-CO` → `es`) o al inglés.
67
+ - El texto de la APP (títulos, botones con contenido) lo pone la app con su i18n, no orbital-ds.
68
+ - **En una app con i18next** (la plantilla TanStack es la referencia): los textos de orbital-ds viven
69
+ en el espacio **«orbital»** de sus JSON (`src/i18n/locales/<idioma>.json`), añadido a `ns`, y se
70
+ pasan con `messages={i18n.getResourceBundle(i18n.language, "orbital")}`. `pnpm exec orbital-ds-i18n`
71
+ rellena lo que falte sin pisar lo personalizado; `--check` va en el verify.
72
+ - **Añadir un idioma** (p. ej. `ru`): crea `ru.json` con las mismas claves que `es.json`, añádelo a
73
+ los idiomas de la app y ejecuta `pnpm exec orbital-ds-i18n`. Si orbital-ds no trae ese idioma, deja
74
+ el inglés y LISTA las claves pendientes: tradúcelas en el JSON hasta que `--check` pase.
75
+ - **RTL**: `dsDirection(idioma)` (`orbital-ds/lib/i18n`) da `ltr`/`rtl`; la app lo pone en `<html dir>` y
76
+ `DsI18nProvider` lo pasa a Base UI. La conversión de los componentes a clases lógicas
77
+ (`ms-`/`ps-`/`start-`/`text-start` en lugar de `ml-`/`pl-`/`left-`/`text-left`) es una fase pendiente.
78
+
79
+ ## Instalar en una app
80
+
81
+ `pnpm exec orbital-ds-init`: elige tema y color, comprueba el contraste y, si lo aceptas,
82
+ escribe `brand.css`, conecta el CSS de la app (bloque de imports en orden), anota DESIGN.md,
83
+ instala Motion y pasa el doctor. Sin preguntas: `--primary <color> --theme <tema> --connect --motion`.
84
+
85
+ ## Cómo comprobar tu trabajo
86
+
87
+ ```bash
88
+ pnpm check:ds # contrato, repetidos, sombras, fugas, valores fijos, personalidad, familias, contraste y demos
89
+ pnpm verify # doctor + typecheck + build
90
+ pnpm manifest # regenera components.manifest.json tras añadir componentes
91
+ pnpm showcase # escaparate: todos los componentes × todos los temas × claro/oscuro × marca
92
+ pnpm showcase:typecheck # tipos de las demos
93
+ pnpm showcase:build # compila el escaparate (comprobación sin servidor)
94
+ ```
95
+
96
+ **Escaparate.** Descubre solo los temas (`src/themes`), las demos (`showcase/src/demos/<componente>.tsx`,
97
+ una por componente: el doctor falla si falta) y las variantes (`showcase/variants/*.css`).
98
+
99
+ **Variante de un tema** (p. ej. «dame variantes de tactile»): un fichero en `showcase/variants/<nombre>.css`
100
+ con `@base-theme <tema>` y `@about <frase>` en su comentario de cabecera y **solo variables** (como un
101
+ `brand.css`). Valídala con `pnpm check:ds -- --css showcase/variants/<nombre>.css`: comprueba que las
102
+ variables existan y el **contraste AA** de la variante sobre su tema. Para llevarla a una app, su contenido
103
+ va al `brand.css`.
104
+
105
+ Si `pnpm check:ds` falla, **corrige la causa**; no lo desactives ni lo rodees.
106
+
107
+ ## Añadir un componente
108
+
109
+ 1. Fichero en `src/ui/<nombre>.tsx` (un componente = un fichero; sin barril).
110
+ 2. `data-slot="<nombre>"` en su raíz y en las partes relevantes.
111
+ 3. Solo tokens. Importa `cn` de `../lib/utils`; los demás componentes, de `./<otro>`.
112
+ 4. Dependencias de terceros de un COMPONENTE: opcionales (`peerDependenciesMeta`), nunca
113
+ obligatorias. Las herramientas de terminal del paquete (`orbital-ds-init`) sí pueden
114
+ tener las suyas (`@clack/prompts`), porque no llegan al bundle de la app.
115
+ 5. Su demo en `showcase/src/demos/<nombre>.tsx` (variantes, tamaños y estados).
116
+ 6. `pnpm manifest`, `pnpm verify`; versión **menor** (añadido compatible).
117
+
118
+ ## Crear un tema
119
+
120
+ Copia `themes/qratia.css` (o `tactile.css`, el ejemplo estricto), cambia valores, no quites
121
+ ninguno, añade `<tema>.fonts.css` con el `@import url()` de sus fuentes, marca la ficha con
122
+ `"conformance": "strict"` y ejecuta `pnpm check:ds`. En modo estricto el doctor exige que la
123
+ personalidad use **solo variables** (ni medidas, ni colores, ni pesos) y que estilice
124
+ **familias completas** de piezas (`slotFamilies` en `contract.json`: si das tinta al
125
+ `checkbox`, también al `radio-group-item`).
126
+
127
+ ## Estándar de integración (cómo debe ajustarse una app)
128
+
129
+ Para que una app (o un agente que la edite) use orbital-ds sin romper nada:
130
+
131
+ 1. **La marca vive solo en `brand.css`.** Ninguna regla de color propia fuera de ese fichero; jamás se edita el paquete.
132
+ 2. **Solo variables públicas.** Nada de variables privadas de un tema: pueden renombrarse. Usa `--ds-*` y los tokens del contrato (`--zw-*` de `tactile` están obsoletas: usa `--ds-key-outline`, `--ds-key-edge` y `--ds-marker`).
133
+ 3. **Sin `!important` ni selectores propios** para vencer a la librería (lateral, raíl, botones). Si algo no se puede ajustar con un token, es un hueco de la librería: abre un issue.
134
+ 4. **El tema se elige con un solo `@import`** (o `pnpm theme`). Los temas con ámbito (`*.scoped.css`) son solo para un banco de pruebas; la marca (`brand.css`) gana siempre, también sobre ellos.
135
+ 5. **Patrón de página.** La cabecera lleva solo botón de menú, título y, siempre visibles, idioma y tema (y avisos si la app los tiene). El subtítulo y las acciones de la vista van al inicio del contenido, centrado en un ancho máximo; solo un lienzo (mapa, kanban, editor) ocupa todo el ancho.
136
+ 6. **Cada tema se documenta y se elige informado.** Lee `orbital-ds/themes/<tema>.guide.md` y su ficha `<tema>.meta.json` (esencia, gesto firma, paleta, accesibilidad, qué valores son aproximados) antes de usar o ajustar un tema.
137
+ 7. **Comprueba antes de dar algo por bueno:** `pnpm exec orbital-ds-doctor --css src/brand.css` y el `verify` de la app.
138
+
139
+ ### Accesibilidad (WCAG 2.2)
140
+
141
+ - **Mínimo exigible: AA.** Texto 4,5:1; texto grande y controles 3:1. `pnpm check:ds` falla si un par principal de texto sobre su superficie (texto/fondo, tarjeta, popover, primario, secundario, lateral, destructivo) o un texto de estado (info, danger, warning, success, neutral) baja de 4,5:1.
142
+ - **Objetivo: AAA en el texto del cuerpo** (7:1 para texto/fondo y texto/tarjeta). Se mide con `pnpm check:ds -- --aaa` y avisa, no falla: WCAG no aconseja exigir AAA a todo el sitio. Hoy todos los temas lo cumplen.
143
+ - **Excepciones declaradas, nunca silenciosas.** Si un tema no puede cumplir un par (el azul de marca de Twitter con texto blanco da 3:1), lo declara en su ficha, en `a11y.exceptions`, con su porqué; el doctor lo muestra como aviso.
144
+ - **Foco siempre visible** (anillo de 3:1 como mínimo) y sin que otro elemento lo tape.
145
+ - **Una marca nueva debe volver a pasar el doctor.** Cambiar `--primary` obliga a revisar `--primary-foreground`, `--link` y `--ring`.
package/README.md CHANGED
@@ -1,73 +1,87 @@
1
- # orbital-ds
2
-
3
- Sistema de diseño genérico: **estructura común + temas intercambiables + ~60 componentes**
4
- sobre [Base UI](https://base-ui.com) y Tailwind v4 (los de shadcn en su versión Base UI).
5
-
6
- - `styles.css` — la ESTRUCTURA: mapea variables de tema a utilidades de Tailwind y define los
7
- tokens semánticos (radios, alturas, sombras, espaciado, capas, movimiento, foco, materiales)
8
- y la capa base. No lleva colores ni fuentes.
9
- - `themes/<tema>.css` — un TEMA: paleta (claro/oscuro), radio base y tipografía.
10
- Hoy: `qratia` y `zyro` (cristal). Añadir otro = añadir otro fichero.
11
- - `themes/<tema>.fonts.css` — las fuentes del tema (un `@import url()`; va el primero).
12
- - `ui/*` — componentes, uno por fichero (`orbital-ds/ui/button`, …): quien no usa gráficos
13
- no necesita `recharts`, quien no usa el calendario no necesita `react-day-picker`.
14
- - `contract.json` + `pnpm check:ds` — el contrato de tema y su comprobación.
15
-
16
- ## Uso en una app (Tailwind v4)
17
-
18
- ```css
19
- @import 'orbital-ds/themes/qratia.fonts.css'; /* fuentes: lo primero */
20
- @import 'tailwindcss';
21
- @plugin '@tailwindcss/typography';
22
- @import 'tw-animate-css';
23
- @import 'orbital-ds/styles.css'; /* estructura */
24
- @import 'orbital-ds/themes/qratia.css'; /* tema (después de la estructura) */
25
- @source '../node_modules/orbital-ds/dist'; /* que Tailwind vea las clases del paquete */
26
- ```
27
-
28
- ```tsx
29
- import { Button } from 'orbital-ds/ui/button';
30
- ```
31
-
32
- Cambiar de identidad = cambiar `qratia` por `zyro` en esas dos líneas de tema/fuentes.
33
- Detalle del contrato, tokens y reglas de nombres en [`docs/CONTRACT.md`](docs/CONTRACT.md).
34
-
35
- ## Guía de cada tema
36
-
37
- Cada tema lleva su documentación, que viaja con el paquete:
38
-
39
- - `orbital-ds/themes/<tema>.guide.md` — guía de diseño: esencia, gesto firma, principios, referencias (qué se tomó de cada una), paleta, tipografía, formas, accesibilidad y estado de los valores (confirmados, aproximados o de diseño propio).
40
- - `orbital-ds/themes/<tema>.meta.json` — la misma ficha legible por máquina.
41
-
42
- `pnpm check:ds` falla si a un tema le falta alguna de las dos. Un tema nuevo debe nacer con ambas.
43
-
44
- ## Marca de una app
45
-
46
- Lo propio de cada app (color principal, acento, radio, fuentes) va en **su** `src/brand.css`,
47
- importado después del tema. Ninguna actualización de orbital-ds lo toca. `pnpm exec orbital-ds-init`
48
- lo crea la primera vez. Detalle en [`docs/CONTRACT.md`](docs/CONTRACT.md).
49
-
50
- ## Regla
51
-
52
- Ningún componente lleva valores propios (colores, medidas, sombras, z-index, duraciones):
53
- pide un hueco a una variable. Para cambiar el aspecto se cambia el tema, no el componente.
54
- Si un componente necesita un hueco nuevo, se AÑADE el token con un valor que deje el aspecto
55
- como estaba. `pnpm check:ds` lo comprueba.
56
-
57
- ## Desarrollo
58
-
59
- ```bash
60
- pnpm install
61
- pnpm verify # doctor + typecheck + build
62
- pnpm check:ds # solo el contrato de tema y los valores fijos
63
- ```
64
-
65
- Peers obligatorios: `react`, `react-dom`, `@base-ui/react`, `tailwindcss`, `tailwind-merge`,
66
- `class-variance-authority`, `clsx`, `lucide-react`, `tw-animate-css`.
67
- Opcionales (solo si usas ese componente): `recharts`, `sonner`, `next-themes`, `cmdk`,
68
- `date-fns` + `react-day-picker`, `embla-carousel-react`, `input-otp`,
69
- `react-resizable-panels`, `@shadcn/react`.
70
-
71
- ## Licencia
72
-
73
- MIT © Fractalia Systems
1
+ # orbital-ds
2
+
3
+ Sistema de diseño genérico: **estructura común + temas intercambiables + ~60 componentes**
4
+ sobre [Base UI](https://base-ui.com) y Tailwind v4 (los de shadcn en su versión Base UI).
5
+
6
+ - `styles.css` — la ESTRUCTURA: mapea variables de tema a utilidades de Tailwind y define los
7
+ tokens semánticos (radios, alturas, sombras, espaciado, capas, movimiento, foco, materiales)
8
+ y la capa base. No lleva colores ni fuentes.
9
+ - `themes/<tema>.css` — un TEMA: paleta (claro/oscuro), radio base y tipografía.
10
+ Hoy: `qratia` y `zyro` (cristal). Añadir otro = añadir otro fichero.
11
+ - `themes/<tema>.fonts.css` — las fuentes del tema (un `@import url()`; va el primero).
12
+ - `ui/*` — componentes, uno por fichero (`orbital-ds/ui/button`, …): quien no usa gráficos
13
+ no necesita `recharts`, quien no usa el calendario no necesita `react-day-picker`.
14
+ - `contract.json` + `pnpm check:ds` — el contrato de tema y su comprobación.
15
+
16
+ ## Uso en una app (Tailwind v4)
17
+
18
+ ```css
19
+ @import 'orbital-ds/themes/qratia.fonts.css'; /* fuentes: lo primero */
20
+ @import 'tailwindcss';
21
+ @plugin '@tailwindcss/typography';
22
+ @import 'tw-animate-css';
23
+ @import 'orbital-ds/styles.css'; /* estructura */
24
+ @import 'orbital-ds/themes/qratia.css'; /* tema (después de la estructura) */
25
+ @source '../node_modules/orbital-ds/dist'; /* que Tailwind vea las clases del paquete */
26
+ ```
27
+
28
+ ```tsx
29
+ import { Button } from 'orbital-ds/ui/button';
30
+ ```
31
+
32
+ Cambiar de identidad = cambiar `qratia` por `zyro` en esas dos líneas de tema/fuentes.
33
+ Detalle del contrato, tokens y reglas de nombres en [`docs/CONTRACT.md`](docs/CONTRACT.md).
34
+
35
+ ## Generar la marca desde un color (asistente)
36
+
37
+ ```
38
+ pnpm exec orbital-ds-init # asistente interactivo
39
+ pnpm exec orbital-ds-init --primary "#1D63D8" # sin preguntas (CI, scripts)
40
+ ```
41
+
42
+ A partir del **color primario** (hex, `rgb()`, `hsl()` u `oklch()`) deriva en OKLCH los neutros teñidos
43
+ (papel, tinta, tarjeta, bordes, lateral), el texto sobre el primario, el enlace y el foco, en piel clara y
44
+ oscura, y **comprueba el contraste** (AA 4,5:1). Si un color no llega, lo ajusta lo mínimo y te lo dice.
45
+ Escribe solo un bloque delimitado en `brand.css`; con `--update` lo reescribe y lo tuyo de fuera no se
46
+ toca. Opciones: `--theme`, `--accent`, `--no-marker` (apaga el rotulador de `tactile`), `--dry-run`,
47
+ `--yes`, `--out`. Sin dependencias.
48
+
49
+ ## Guía de cada tema
50
+
51
+ Cada tema lleva su documentación, que viaja con el paquete:
52
+
53
+ - `orbital-ds/themes/<tema>.guide.md` — guía de diseño: esencia, gesto firma, principios, referencias (qué se tomó de cada una), paleta, tipografía, formas, accesibilidad y estado de los valores (confirmados, aproximados o de diseño propio).
54
+ - `orbital-ds/themes/<tema>.meta.json` — la misma ficha legible por máquina.
55
+
56
+ `pnpm check:ds` falla si a un tema le falta alguna de las dos. Un tema nuevo debe nacer con ambas.
57
+
58
+ ## Marca de una app
59
+
60
+ Lo propio de cada app (color principal, acento, radio, fuentes) va en **su** `src/brand.css`,
61
+ importado después del tema. Ninguna actualización de orbital-ds lo toca. `pnpm exec orbital-ds-init`
62
+ lo crea la primera vez. Detalle en [`docs/CONTRACT.md`](docs/CONTRACT.md).
63
+
64
+ ## Regla
65
+
66
+ Ningún componente lleva valores propios (colores, medidas, sombras, z-index, duraciones):
67
+ pide un hueco a una variable. Para cambiar el aspecto se cambia el tema, no el componente.
68
+ Si un componente necesita un hueco nuevo, se AÑADE el token con un valor que deje el aspecto
69
+ como estaba. `pnpm check:ds` lo comprueba.
70
+
71
+ ## Desarrollo
72
+
73
+ ```bash
74
+ pnpm install
75
+ pnpm verify # doctor + typecheck + build
76
+ pnpm check:ds # solo el contrato de tema y los valores fijos
77
+ ```
78
+
79
+ Peers obligatorios: `react`, `react-dom`, `@base-ui/react`, `tailwindcss`, `tailwind-merge`,
80
+ `class-variance-authority`, `clsx`, `lucide-react`, `tw-animate-css`.
81
+ Opcionales (solo si usas ese componente): `recharts`, `sonner`, `next-themes`, `cmdk`,
82
+ `date-fns` + `react-day-picker`, `embla-carousel-react`, `input-otp`,
83
+ `react-resizable-panels`, `@shadcn/react`.
84
+
85
+ ## Licencia
86
+
87
+ MIT © Fractalia Systems