orbital-ds 0.8.0 → 0.10.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 (159) hide show
  1. package/AGENTS.md +162 -80
  2. package/components.manifest.json +1713 -1267
  3. package/contract.json +231 -168
  4. package/dist/hooks/use-ds-messages.d.ts +94 -0
  5. package/dist/hooks/use-ds-messages.js +18 -0
  6. package/dist/hooks/use-ds-motion.d.ts +17 -0
  7. package/dist/hooks/use-ds-motion.js +50 -0
  8. package/dist/lib/echarts-presets.d.ts +153 -0
  9. package/dist/lib/echarts-presets.js +311 -0
  10. package/dist/lib/echarts-server.d.ts +15 -0
  11. package/dist/lib/echarts-server.js +15 -0
  12. package/dist/lib/echarts-setup.d.ts +4 -0
  13. package/dist/lib/echarts-setup.js +60 -0
  14. package/dist/lib/echarts-theme.d.ts +36 -0
  15. package/dist/lib/echarts-theme.js +142 -0
  16. package/dist/lib/i18n.d.ts +102 -0
  17. package/dist/lib/i18n.js +275 -0
  18. package/dist/lib/motion.d.ts +74 -0
  19. package/dist/lib/motion.js +97 -0
  20. package/dist/styles.css +914 -528
  21. package/dist/themes/friendly.css +364 -318
  22. package/dist/themes/friendly.meta.json +75 -14
  23. package/dist/themes/friendly.scoped.css +364 -318
  24. package/dist/themes/friendly.tokens.json +45 -0
  25. package/dist/themes/qratia.meta.json +42 -12
  26. package/dist/themes/qratia.tokens.json +49 -0
  27. package/dist/themes/tactile.css +577 -430
  28. package/dist/themes/tactile.fonts.css +3 -2
  29. package/dist/themes/tactile.guide.md +82 -49
  30. package/dist/themes/tactile.meta.json +175 -82
  31. package/dist/themes/tactile.scoped.css +577 -430
  32. package/dist/themes/tactile.tokens.json +42 -0
  33. package/dist/themes/twitter.css +356 -298
  34. package/dist/themes/twitter.meta.json +83 -61
  35. package/dist/themes/twitter.scoped.css +356 -298
  36. package/dist/themes/twitter.tokens.json +45 -0
  37. package/dist/themes/zyro.css +445 -389
  38. package/dist/themes/zyro.meta.json +67 -14
  39. package/dist/themes/zyro.scoped.css +445 -389
  40. package/dist/themes/zyro.tokens.json +46 -0
  41. package/dist/ui/accordion.js +5 -5
  42. package/dist/ui/alert-dialog.js +3 -3
  43. package/dist/ui/alert.d.ts +1 -1
  44. package/dist/ui/alert.js +9 -3
  45. package/dist/ui/attachment.d.ts +1 -1
  46. package/dist/ui/attachment.js +4 -4
  47. package/dist/ui/avatar.js +6 -6
  48. package/dist/ui/ayuda.js +3 -2
  49. package/dist/ui/badge.d.ts +1 -1
  50. package/dist/ui/badge.js +9 -3
  51. package/dist/ui/banner.d.ts +14 -0
  52. package/dist/ui/banner.js +88 -0
  53. package/dist/ui/breadcrumb.js +7 -3
  54. package/dist/ui/bubble.js +6 -6
  55. package/dist/ui/button-group.js +4 -4
  56. package/dist/ui/button.d.ts +1 -1
  57. package/dist/ui/button.js +5 -5
  58. package/dist/ui/calendar.js +37 -6
  59. package/dist/ui/card.js +4 -4
  60. package/dist/ui/carousel.js +15 -8
  61. package/dist/ui/chart.js +7 -3
  62. package/dist/ui/checkbox.js +1 -1
  63. package/dist/ui/code-block.d.ts +14 -0
  64. package/dist/ui/code-block.js +106 -0
  65. package/dist/ui/combobox.js +7 -7
  66. package/dist/ui/command.js +13 -11
  67. package/dist/ui/context-menu.js +8 -8
  68. package/dist/ui/data-table.d.ts +185 -0
  69. package/dist/ui/data-table.js +714 -0
  70. package/dist/ui/date-picker.d.ts +65 -0
  71. package/dist/ui/date-picker.js +362 -0
  72. package/dist/ui/dialog.js +10 -6
  73. package/dist/ui/drawer.js +9 -9
  74. package/dist/ui/dropdown-menu.js +8 -8
  75. package/dist/ui/dropzone.d.ts +42 -0
  76. package/dist/ui/dropzone.js +220 -0
  77. package/dist/ui/echart.d.ts +31 -0
  78. package/dist/ui/echart.js +88 -0
  79. package/dist/ui/empty.js +3 -3
  80. package/dist/ui/eyebrow.d.ts +7 -0
  81. package/dist/ui/eyebrow.js +16 -0
  82. package/dist/ui/field.js +2 -2
  83. package/dist/ui/filter-bar.d.ts +36 -0
  84. package/dist/ui/filter-bar.js +193 -0
  85. package/dist/ui/heatmap-grid.d.ts +39 -0
  86. package/dist/ui/heatmap-grid.js +195 -0
  87. package/dist/ui/hover-card.js +1 -1
  88. package/dist/ui/i18n-provider.d.ts +11 -0
  89. package/dist/ui/i18n-provider.js +18 -0
  90. package/dist/ui/icon-tile.d.ts +1 -1
  91. package/dist/ui/input-group.d.ts +1 -1
  92. package/dist/ui/input-group.js +11 -9
  93. package/dist/ui/input-otp.js +3 -3
  94. package/dist/ui/input.js +1 -1
  95. package/dist/ui/item.d.ts +1 -1
  96. package/dist/ui/item.js +3 -3
  97. package/dist/ui/kbd.js +1 -1
  98. package/dist/ui/label.js +1 -1
  99. package/dist/ui/legend.d.ts +30 -0
  100. package/dist/ui/legend.js +124 -0
  101. package/dist/ui/marker.d.ts +1 -1
  102. package/dist/ui/marker.js +2 -2
  103. package/dist/ui/menubar.js +9 -9
  104. package/dist/ui/message-scroller.js +5 -2
  105. package/dist/ui/message.js +2 -2
  106. package/dist/ui/motion-provider.d.ts +11 -0
  107. package/dist/ui/motion-provider.js +16 -0
  108. package/dist/ui/native-select.js +4 -4
  109. package/dist/ui/navigation-menu.js +7 -6
  110. package/dist/ui/notifications.d.ts +69 -0
  111. package/dist/ui/notifications.js +335 -0
  112. package/dist/ui/page-header.d.ts +19 -0
  113. package/dist/ui/page-header.js +132 -0
  114. package/dist/ui/pagination.js +19 -11
  115. package/dist/ui/panel.d.ts +12 -0
  116. package/dist/ui/panel.js +41 -0
  117. package/dist/ui/popover.js +2 -2
  118. package/dist/ui/progress.js +2 -2
  119. package/dist/ui/proportion-bar.d.ts +27 -0
  120. package/dist/ui/proportion-bar.js +92 -0
  121. package/dist/ui/questionnaire.js +20 -15
  122. package/dist/ui/radio-group.js +2 -2
  123. package/dist/ui/resizable.js +2 -2
  124. package/dist/ui/scroll-area.js +3 -3
  125. package/dist/ui/select.js +6 -6
  126. package/dist/ui/separator.js +1 -1
  127. package/dist/ui/sheet.js +6 -4
  128. package/dist/ui/sidebar.js +42 -30
  129. package/dist/ui/skeleton.js +1 -1
  130. package/dist/ui/slider.js +6 -6
  131. package/dist/ui/sonner.js +25 -8
  132. package/dist/ui/sparkline.d.ts +26 -0
  133. package/dist/ui/sparkline.js +97 -0
  134. package/dist/ui/spinner.js +4 -1
  135. package/dist/ui/stat.d.ts +61 -0
  136. package/dist/ui/stat.js +238 -0
  137. package/dist/ui/status-badge.d.ts +38 -0
  138. package/dist/ui/status-badge.js +153 -0
  139. package/dist/ui/stepper.d.ts +20 -0
  140. package/dist/ui/stepper.js +152 -0
  141. package/dist/ui/switch.js +2 -2
  142. package/dist/ui/table.js +3 -3
  143. package/dist/ui/tabs.js +5 -5
  144. package/dist/ui/textarea.js +1 -1
  145. package/dist/ui/timeline.d.ts +29 -0
  146. package/dist/ui/timeline.js +157 -0
  147. package/dist/ui/toast.js +15 -12
  148. package/dist/ui/toggle-group.js +2 -2
  149. package/dist/ui/toggle.js +6 -4
  150. package/dist/ui/tooltip.js +2 -2
  151. package/docs/CONTRACT.md +183 -153
  152. package/docs/GRAFICOS.md +125 -0
  153. package/docs/adr/0001-rtl-clases-logicas.md +78 -0
  154. package/package.json +58 -29
  155. package/scripts/brand-core.mjs +153 -0
  156. package/scripts/doctor.mjs +128 -7
  157. package/scripts/i18n.mjs +111 -0
  158. package/scripts/init.mjs +327 -351
  159. package/scripts/setup.mjs +99 -0
package/AGENTS.md CHANGED
@@ -1,80 +1,162 @@
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: 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`).
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
+ ## Gráficos e informes (Apache ECharts)
58
+
59
+ - **Librería oficial: ECharts** (dependencia opcional). `chart.tsx` (Recharts) se mantiene por compatibilidad,
60
+ sin nuevas funciones.
61
+ - **El tema gobierna el gráfico**: `<EChart option={…} />` (`orbital-ds/ui/echart`) monta un tema de ECharts
62
+ desde las variables del tema activo y de la marca (paleta `--chart-1…5` + estados, textos, ejes, tooltip,
63
+ fuentes, ritmo) y se repinta al cambiar de tema o de piel. SVG por defecto; `exportable` descarga SVG/PNG.
64
+ Nunca pongas colores en el `option`: los da el tema (si una serie necesita un tono, usa la paleta del tema).
65
+ - **Opciones listas**: `orbital-ds/lib/echarts-presets` (línea/área, barras, combo, mapa de calor, sankey,
66
+ gauge, donut, líneas y áreas de referencia). Sirven igual en pantalla y en informes.
67
+ - **Informes automáticos (servidor / Workers, sin DOM)**: `renderEChartToSvg(option, { width, height, tokens })`
68
+ (`orbital-ds/lib/echarts-server`) con `tokens` = `orbital-ds/themes/<tema>.tokens.json` → `.light` o
69
+ `.dark` (colores ya resueltos; mezcla ahí los de la marca si la app tiene). Para PNG (plantillas de
70
+ documento), la app convierte el SVG (p. ej. resvg) con las fuentes del tema.
71
+ - Registro común de tipos y componentes: `orbital-ds/lib/echarts-setup`. Otro tipo → `echarts.use([...])` en la app.
72
+ - **Recetas completas** (pantalla, informe SVG→PNG, función de servidor de TanStack Start, endpoint en un Worker, marca en los informes): `docs/GRAFICOS.md`.
73
+
74
+ ## Idioma (i18n)
75
+
76
+ - Los textos PROPIOS de los componentes (cerrar, cargando, paginación, carrusel, lateral,
77
+ cuestionario…) salen de `useDsMessages()` y sus catálogos (`orbital-ds/lib/i18n`: en, es,
78
+ pt-BR). **Ningún componente escribe un texto visible o accesible a mano**: el doctor lo rechaza
79
+ (`aria-label="…"`, `sr-only`, `?? "…"`, `title="…"`).
80
+ - Un texto nuevo = una clave nueva en los TRES catálogos (el tipo obliga a tenerla en todos).
81
+ - La app pasa su idioma una vez: `<DsI18nProvider locale={i18n.language}>` (con i18next,
82
+ `useTranslation().i18n.language`). Un texto concreto se sobrescribe con `messages`. Sin
83
+ provider, inglés. Otro idioma cae a su base (`es-CO` → `es`) o al inglés.
84
+ - El texto de la APP (títulos, botones con contenido) lo pone la app con su i18n, no orbital-ds.
85
+ - **En una app con i18next** (la plantilla TanStack es la referencia): los textos de orbital-ds viven
86
+ en el espacio **«orbital»** de sus JSON (`src/i18n/locales/<idioma>.json`), añadido a `ns`, y se
87
+ pasan con `messages={i18n.getResourceBundle(i18n.language, "orbital")}`. `pnpm exec orbital-ds-i18n`
88
+ rellena lo que falte sin pisar lo personalizado; `--check` va en el verify.
89
+ - **Añadir un idioma** (p. ej. `ru`): crea `ru.json` con las mismas claves que `es.json`, añádelo a
90
+ los idiomas de la app y ejecuta `pnpm exec orbital-ds-i18n`. Si orbital-ds no trae ese idioma, deja
91
+ el inglés y LISTA las claves pendientes: tradúcelas en el JSON hasta que `--check` pase.
92
+ - **RTL**: `dsDirection(idioma)` (`orbital-ds/lib/i18n`) da `ltr`/`rtl`; la app lo pone en `<html dir>` y
93
+ `DsI18nProvider` lo pasa a Base UI. La conversión de los componentes a clases lógicas
94
+ (`ms-`/`ps-`/`start-`/`text-start` en lugar de `ml-`/`pl-`/`left-`/`text-left`) es una fase pendiente: decisión y plan en `docs/adr/0001-rtl-clases-logicas.md`.
95
+
96
+ ## Instalar en una app
97
+
98
+ `pnpm exec orbital-ds-init`: elige tema y color, comprueba el contraste y, si lo aceptas,
99
+ escribe `brand.css`, conecta el CSS de la app (bloque de imports en orden), anota DESIGN.md,
100
+ instala Motion y pasa el doctor. Sin preguntas: `--primary <color> --theme <tema> --connect --motion`.
101
+
102
+ ## Cómo comprobar tu trabajo
103
+
104
+ ```bash
105
+ pnpm check:ds # contrato, repetidos, sombras, fugas, valores fijos, personalidad, familias, contraste y demos
106
+ pnpm verify # doctor + typecheck + build
107
+ pnpm manifest # regenera components.manifest.json tras añadir componentes
108
+ pnpm showcase # escaparate: todos los componentes × todos los temas × claro/oscuro × marca
109
+ pnpm showcase:typecheck # tipos de las demos
110
+ pnpm showcase:build # compila el escaparate (comprobación sin servidor)
111
+ ```
112
+
113
+ **Escaparate.** Descubre solo los temas (`src/themes`), las demos (`showcase/src/demos/<componente>.tsx`,
114
+ una por componente: el doctor falla si falta) y las variantes (`showcase/variants/*.css`).
115
+
116
+ **Variante de un tema** (p. ej. «dame variantes de tactile»): un fichero en `showcase/variants/<nombre>.css`
117
+ con `@base-theme <tema>` y `@about <frase>` en su comentario de cabecera y **solo variables** (como un
118
+ `brand.css`). Valídala con `pnpm check:ds -- --css showcase/variants/<nombre>.css`: comprueba que las
119
+ variables existan y el **contraste AA** de la variante sobre su tema. Para llevarla a una app, su contenido
120
+ va al `brand.css`.
121
+
122
+ Si `pnpm check:ds` falla, **corrige la causa**; no lo desactives ni lo rodees.
123
+
124
+ ## Añadir un componente
125
+
126
+ 1. Fichero en `src/ui/<nombre>.tsx` (un componente = un fichero; sin barril).
127
+ 2. `data-slot="<nombre>"` en su raíz y en las partes relevantes.
128
+ 3. Solo tokens. Importa `cn` de `../lib/utils`; los demás componentes, de `./<otro>`.
129
+ 4. Dependencias de terceros de un COMPONENTE: opcionales (`peerDependenciesMeta`), nunca
130
+ obligatorias. Las herramientas de terminal del paquete (`orbital-ds-init`) sí pueden
131
+ tener las suyas (`@clack/prompts`), porque no llegan al bundle de la app.
132
+ 5. Su demo en `showcase/src/demos/<nombre>.tsx` (variantes, tamaños y estados).
133
+ 6. `pnpm manifest`, `pnpm verify`; versión **menor** (añadido compatible).
134
+
135
+ ## Crear un tema
136
+
137
+ Copia `themes/qratia.css` (o `tactile.css`, el ejemplo estricto), cambia valores, no quites
138
+ ninguno, añade `<tema>.fonts.css` con el `@import url()` de sus fuentes, marca la ficha con
139
+ `"conformance": "strict"` y ejecuta `pnpm check:ds`. En modo estricto el doctor exige que la
140
+ personalidad use **solo variables** (ni medidas, ni colores, ni pesos) y que estilice
141
+ **familias completas** de piezas (`slotFamilies` en `contract.json`: si das tinta al
142
+ `checkbox`, también al `radio-group-item`).
143
+
144
+ ## Estándar de integración (cómo debe ajustarse una app)
145
+
146
+ Para que una app (o un agente que la edite) use orbital-ds sin romper nada:
147
+
148
+ 1. **La marca vive solo en `brand.css`.** Ninguna regla de color propia fuera de ese fichero; jamás se edita el paquete.
149
+ 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`).
150
+ 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.
151
+ 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.
152
+ 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.
153
+ 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.
154
+ 7. **Comprueba antes de dar algo por bueno:** `pnpm exec orbital-ds-doctor --css src/brand.css` y el `verify` de la app.
155
+
156
+ ### Accesibilidad (WCAG 2.2)
157
+
158
+ - **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.
159
+ - **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.
160
+ - **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.
161
+ - **Foco siempre visible** (anillo de 3:1 como mínimo) y sin que otro elemento lo tape.
162
+ - **Una marca nueva debe volver a pasar el doctor.** Cambiar `--primary` obliga a revisar `--primary-foreground`, `--link` y `--ring`.