reactigoded 1.0.0-beta.26
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.
- package/CHANGELOG.md +3001 -0
- package/LICENSE +21 -0
- package/README.md +556 -0
- package/dist/Toast-FZUdYH1L.js +594 -0
- package/dist/cn.js +7 -0
- package/dist/components/Accordion/Accordion.d.ts +49 -0
- package/dist/components/Accordion/AccordionContent.d.ts +15 -0
- package/dist/components/Accordion/AccordionContext.d.ts +59 -0
- package/dist/components/Accordion/AccordionHeader.d.ts +22 -0
- package/dist/components/Accordion/AccordionItem.d.ts +11 -0
- package/dist/components/Accordion/index.d.ts +8 -0
- package/dist/components/Alert/Alert.d.ts +39 -0
- package/dist/components/Alert/index.d.ts +2 -0
- package/dist/components/AlertDialog/AlertDialogClose.d.ts +64 -0
- package/dist/components/AlertDialog/AlertDialogContent.d.ts +58 -0
- package/dist/components/AlertDialog/index.d.ts +14 -0
- package/dist/components/Avatar/Avatar.d.ts +62 -0
- package/dist/components/Avatar/AvatarGroup.d.ts +13 -0
- package/dist/components/Avatar/index.d.ts +4 -0
- package/dist/components/Badge/Badge.d.ts +33 -0
- package/dist/components/Badge/index.d.ts +2 -0
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +14 -0
- package/dist/components/Breadcrumb/BreadcrumbItem.d.ts +21 -0
- package/dist/components/Breadcrumb/index.d.ts +4 -0
- package/dist/components/Button/Button.d.ts +61 -0
- package/dist/components/Button/IconButton.d.ts +48 -0
- package/dist/components/Button/index.d.ts +4 -0
- package/dist/components/Card/Card.d.ts +79 -0
- package/dist/components/Card/CardBody.d.ts +8 -0
- package/dist/components/Card/CardDivider.d.ts +8 -0
- package/dist/components/Card/CardFooter.d.ts +8 -0
- package/dist/components/Card/CardHeader.d.ts +8 -0
- package/dist/components/Card/CardImage.d.ts +15 -0
- package/dist/components/Card/index.d.ts +12 -0
- package/dist/components/Checkbox/Checkbox.d.ts +47 -0
- package/dist/components/Checkbox/index.d.ts +2 -0
- package/dist/components/Chip/Chip.d.ts +38 -0
- package/dist/components/Chip/index.d.ts +2 -0
- package/dist/components/Dialog/Dialog.d.ts +80 -0
- package/dist/components/Dialog/DialogBody.d.ts +8 -0
- package/dist/components/Dialog/DialogClose.d.ts +61 -0
- package/dist/components/Dialog/DialogContent.d.ts +36 -0
- package/dist/components/Dialog/DialogContext.d.ts +1 -0
- package/dist/components/Dialog/DialogFooter.d.ts +8 -0
- package/dist/components/Dialog/DialogHeader.d.ts +13 -0
- package/dist/components/Dialog/DialogTrigger.d.ts +44 -0
- package/dist/components/Dialog/index.d.ts +16 -0
- package/dist/components/Divider/Divider.d.ts +34 -0
- package/dist/components/Divider/index.d.ts +2 -0
- package/dist/components/Input/ErrorText.d.ts +13 -0
- package/dist/components/Input/Helper.d.ts +11 -0
- package/dist/components/Input/Input.d.ts +35 -0
- package/dist/components/Input/InputAddon.d.ts +8 -0
- package/dist/components/Input/InputGroup.d.ts +17 -0
- package/dist/components/Input/Label.d.ts +12 -0
- package/dist/components/Input/index.d.ts +12 -0
- package/dist/components/NativeSelect/NativeSelect.d.ts +41 -0
- package/dist/components/NativeSelect/index.d.ts +2 -0
- package/dist/components/Navbar/Navbar.d.ts +46 -0
- package/dist/components/Navbar/NavbarActions.d.ts +10 -0
- package/dist/components/Navbar/NavbarLink.d.ts +13 -0
- package/dist/components/Navbar/NavbarLogo.d.ts +22 -0
- package/dist/components/Navbar/NavbarMenuButton.d.ts +15 -0
- package/dist/components/Navbar/NavbarNav.d.ts +14 -0
- package/dist/components/Navbar/index.d.ts +12 -0
- package/dist/components/Pagination/Pagination.d.ts +77 -0
- package/dist/components/Pagination/index.d.ts +2 -0
- package/dist/components/Progress/Progress.d.ts +63 -0
- package/dist/components/Progress/index.d.ts +2 -0
- package/dist/components/Radio/Radio.d.ts +28 -0
- package/dist/components/Radio/index.d.ts +2 -0
- package/dist/components/Rating/Rating.d.ts +85 -0
- package/dist/components/Rating/index.d.ts +2 -0
- package/dist/components/Sidebar/Sidebar.d.ts +28 -0
- package/dist/components/Sidebar/SidebarContext.d.ts +32 -0
- package/dist/components/Sidebar/SidebarDivider.d.ts +8 -0
- package/dist/components/Sidebar/SidebarFooter.d.ts +8 -0
- package/dist/components/Sidebar/SidebarHeader.d.ts +13 -0
- package/dist/components/Sidebar/SidebarItem.d.ts +42 -0
- package/dist/components/Sidebar/SidebarNav.d.ts +13 -0
- package/dist/components/Sidebar/SidebarSection.d.ts +11 -0
- package/dist/components/Sidebar/SidebarToggle.d.ts +17 -0
- package/dist/components/Sidebar/index.d.ts +16 -0
- package/dist/components/Skeleton/Skeleton.d.ts +60 -0
- package/dist/components/Skeleton/index.d.ts +2 -0
- package/dist/components/Slider/Slider.d.ts +44 -0
- package/dist/components/Slider/index.d.ts +2 -0
- package/dist/components/Slot/Slot.d.ts +1 -0
- package/dist/components/Slot/composeEventHandlers.d.ts +1 -0
- package/dist/components/Slot/composeRefs.d.ts +1 -0
- package/dist/components/Slot/index.d.ts +3 -0
- package/dist/components/Spinner/Spinner.d.ts +31 -0
- package/dist/components/Spinner/index.d.ts +2 -0
- package/dist/components/Stepper/Step.d.ts +17 -0
- package/dist/components/Stepper/Stepper.d.ts +97 -0
- package/dist/components/Stepper/index.d.ts +4 -0
- package/dist/components/Switch/Switch.d.ts +53 -0
- package/dist/components/Switch/index.d.ts +2 -0
- package/dist/components/Table/Table.d.ts +74 -0
- package/dist/components/Table/index.d.ts +2 -0
- package/dist/components/Tabs/Tabs.d.ts +41 -0
- package/dist/components/Tabs/TabsContent.d.ts +15 -0
- package/dist/components/Tabs/TabsContext.d.ts +61 -0
- package/dist/components/Tabs/TabsList.d.ts +10 -0
- package/dist/components/Tabs/TabsTrigger.d.ts +15 -0
- package/dist/components/Tabs/index.d.ts +8 -0
- package/dist/components/Textarea/Textarea.d.ts +51 -0
- package/dist/components/Textarea/index.d.ts +2 -0
- package/dist/components/ThemeToggle/ThemeToggle.d.ts +43 -0
- package/dist/components/ThemeToggle/index.d.ts +2 -0
- package/dist/components/Timeline/Timeline.d.ts +20 -0
- package/dist/components/Timeline/TimelineItem.d.ts +32 -0
- package/dist/components/Timeline/index.d.ts +4 -0
- package/dist/components/Toast/Toast.d.ts +47 -0
- package/dist/components/Toast/ToastContext.d.ts +93 -0
- package/dist/components/Toast/ToastProvider.d.ts +116 -0
- package/dist/components/Toast/index.d.ts +6 -0
- package/dist/components/floating/Menu/Menu.d.ts +67 -0
- package/dist/components/floating/Menu/MenuContent.d.ts +60 -0
- package/dist/components/floating/Menu/MenuContext.d.ts +78 -0
- package/dist/components/floating/Menu/MenuItem.d.ts +47 -0
- package/dist/components/floating/Menu/MenuLabel.d.ts +6 -0
- package/dist/components/floating/Menu/MenuSeparator.d.ts +6 -0
- package/dist/components/floating/Menu/MenuTrigger.d.ts +53 -0
- package/dist/components/floating/Menu/index.d.ts +12 -0
- package/dist/components/floating/Menu/menuSelectors.d.ts +15 -0
- package/dist/components/floating/Tooltip/Tooltip.d.ts +194 -0
- package/dist/components/floating/Tooltip/index.d.ts +2 -0
- package/dist/components/floating/index.d.ts +3 -0
- package/dist/components/floating/primitives/FloatingTreeRoot.d.ts +55 -0
- package/dist/components/floating/primitives/index.d.ts +2 -0
- package/dist/components/floating/primitives/useFloatingNode.d.ts +1 -0
- package/dist/components/index.d.ts +38 -0
- package/dist/hooks/useControllableState.d.ts +152 -0
- package/dist/hooks/useTheme.d.ts +44 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +1843 -0
- package/dist/server-safe.d.ts +69 -0
- package/dist/server-safe.js +47 -0
- package/dist/styles/igoded-base.css +1 -0
- package/dist/styles/igoded-components.css +1 -0
- package/dist/styles/igoded-design.css +1 -0
- package/dist/styles/igoded-fonts.css +1 -0
- package/dist/styles/igoded-reset.css +1 -0
- package/dist/styles/igoded-state-css.css +1 -0
- package/dist/styles/igoded-tokens.css +1 -0
- package/dist/styles/index.css +3 -0
- package/dist/styles/state/active.css +1 -0
- package/dist/styles/state/checked.css +1 -0
- package/dist/styles/state/default.css +1 -0
- package/dist/styles/state/disabled.css +1 -0
- package/dist/styles/state/empty.css +1 -0
- package/dist/styles/state/first-child.css +1 -0
- package/dist/styles/state/first-of-type.css +1 -0
- package/dist/styles/state/focus-visible.css +1 -0
- package/dist/styles/state/focus-within.css +1 -0
- package/dist/styles/state/focus.css +1 -0
- package/dist/styles/state/group-hover.css +1 -0
- package/dist/styles/state/hover.css +1 -0
- package/dist/styles/state/in-range.css +1 -0
- package/dist/styles/state/indeterminate.css +1 -0
- package/dist/styles/state/invalid.css +1 -0
- package/dist/styles/state/last-child.css +1 -0
- package/dist/styles/state/last-of-type.css +1 -0
- package/dist/styles/state/nth-child.css +1 -0
- package/dist/styles/state/only-child.css +1 -0
- package/dist/styles/state/optional.css +1 -0
- package/dist/styles/state/other.css +1 -0
- package/dist/styles/state/out-of-range.css +1 -0
- package/dist/styles/state/placeholder-shown.css +1 -0
- package/dist/styles/state/read-only.css +1 -0
- package/dist/styles/state/read-write.css +1 -0
- package/dist/styles/state/required.css +1 -0
- package/dist/styles/state/target.css +1 -0
- package/dist/styles/state/valid.css +1 -0
- package/dist/utils/cn.d.ts +11 -0
- package/package.json +282 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Iván Goded
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
# reactigoded
|
|
2
|
+
|
|
3
|
+
Design system de **igoded** — 32 componentes React 19 + TypeScript estricto
|
|
4
|
+
sobre un CSS modular utility-first state-driven (`tokens` / `base` /
|
|
5
|
+
`components` + `reset` opt-in + `state` opt-in).
|
|
6
|
+
|
|
7
|
+
> **Estado**: `1.0.0-beta.25`.
|
|
8
|
+
> Paleta cardinal estable: 7 cardinales con geometría OKLCH dual
|
|
9
|
+
> (L_lux≈0.32 / L_nox≈0.84 / ΔH≤10°), todos AAA contra los 5 fondos
|
|
10
|
+
> del tema en ambos modos. El cardinal `info` se llama internamente
|
|
11
|
+
> `kobalium` (azul cobalto, H≈260°); la API semántica pública —
|
|
12
|
+
> `info` / `--ig-info` / `.ig-*-info` — no cambia. `vitreus` (brand)
|
|
13
|
+
> está reposicionado en H=207.50° (centro perceptual verde↔azul en
|
|
14
|
+
> OKLCH), hex `#053a40` lux / `#3ae2f7` nox. CI local en verde:
|
|
15
|
+
> `lint + typecheck + test:unit + test:contrast (WCAG ≥ 4.5 ambos
|
|
16
|
+
> temas + geometría OKLCH + ΔE OKLab) + build + storybook+axe +
|
|
17
|
+
> verify:size`.
|
|
18
|
+
|
|
19
|
+
## Instalación
|
|
20
|
+
|
|
21
|
+
> **Nota**: el paquete aún no está publicado a npm. La instalación
|
|
22
|
+
> se hace vía clone + `npm link` mientras tanto. La publicación al
|
|
23
|
+
> registro está prevista pero sin fecha confirmada.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
git clone https://github.com/ivangc1/reactigoded.git
|
|
27
|
+
cd reactigoded
|
|
28
|
+
npm ci
|
|
29
|
+
npm run build
|
|
30
|
+
npm link
|
|
31
|
+
|
|
32
|
+
# en tu app:
|
|
33
|
+
cd /tu/app
|
|
34
|
+
npm link reactigoded
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`react` y `react-dom` >= 19 son `peerDependencies`.
|
|
38
|
+
|
|
39
|
+
**`@floating-ui/react` (^0.27) es peer-dep requerido** — lo usa
|
|
40
|
+
internamente `Tooltip` (y futuros `Popover`, `HoverCard`, etc.).
|
|
41
|
+
Instálalo **siempre** junto a la librería:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm install reactigoded react react-dom @floating-ui/react clsx
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**`clsx` (^2.1) también es peer-dep requerido** — lo usa el helper `cn`
|
|
48
|
+
(y el export `reactigoded/cn`). Sin él, `reactigoded/cn` revienta con
|
|
49
|
+
`ERR_MODULE_NOT_FOUND`. Se externaliza como peer (D1-P2, beta.24) para
|
|
50
|
+
no duplicar `clsx` en consumers que ya lo traen vía Tailwind/shadcn.
|
|
51
|
+
|
|
52
|
+
Aunque el tree-shaking elimina `Tooltip` + `@floating-ui/react`
|
|
53
|
+
del bundle final si no los importas, el peer-dep no satisfecho
|
|
54
|
+
rompe la resolución de módulos del bundler **antes** de que el
|
|
55
|
+
tree-shake ocurra. No es opcional para el install, solo para el
|
|
56
|
+
bundle.
|
|
57
|
+
|
|
58
|
+
Razón: `@floating-ui/react` ocupa ~17 KB gz; bundlearla duplicaba
|
|
59
|
+
la dep si el consumer ya la tenía vía Radix/Headless UI/otra DS.
|
|
60
|
+
Externalizarla mantiene el bundle ESM de reactigoded en ~16 KB gz
|
|
61
|
+
(budget 20 KB con headroom para crecimiento, D9 beta.24).
|
|
62
|
+
|
|
63
|
+
### ⚠ Riesgo pre-1.0 — qué pasa cuando FUI publique 0.28
|
|
64
|
+
|
|
65
|
+
`@floating-ui/react` está actualmente en `0.27.x` (pre-1.0). En semver
|
|
66
|
+
pre-1.0 el caret `^0.27.0` se comporta distinto que en versiones
|
|
67
|
+
mayores estables:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
^0.27.0 → matchea 0.27.x SOLAMENTE (NO matchea 0.28.0)
|
|
71
|
+
^1.27.0 → matchea 1.x.x (sí matchearía 1.28.0)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Es decir: una vez FUI publique `0.28.0`, los consumers haciendo
|
|
75
|
+
`npm install reactigoded` con la rango `^0.27.0` de nuestro
|
|
76
|
+
peerDependencies verán warning de peer-dep no satisfecho si tienen
|
|
77
|
+
`@floating-ui/react@0.28.x` ya instalado por otra dep. Eso es
|
|
78
|
+
intencional — un minor bump en `0.x` puede traer breaking changes
|
|
79
|
+
(la convención semver de pre-1.0).
|
|
80
|
+
|
|
81
|
+
**Política del DS** (decision doc `D10-fui-peer-dep-verify.md`):
|
|
82
|
+
|
|
83
|
+
1. Mantenemos `^0.27.0` cerrado hasta verificar compatibilidad
|
|
84
|
+
con la nueva minor.
|
|
85
|
+
2. Cuando FUI publique `0.28.0`, hacemos cross-check de los 20
|
|
86
|
+
símbolos que usamos (`autoUpdate`, `useFloating`, `flip`, etc.).
|
|
87
|
+
3. Si la nueva minor no rompe nuestros uses, ampliamos el rango a
|
|
88
|
+
`^0.27.0 || ^0.28.0` en un patch release del DS.
|
|
89
|
+
4. Si rompe, evaluamos: pinar `0.27.x` permanente, o adoptar `0.28`
|
|
90
|
+
con un minor bump del DS (breaking si el cambio toca API expuesta).
|
|
91
|
+
|
|
92
|
+
**Si tu app YA usa `@floating-ui/react` directamente**: pinea
|
|
93
|
+
explícitamente `0.27.x` en tu `package.json` para evitar que un `npm
|
|
94
|
+
install` de tu app traiga `0.28.0` automático y rompa la resolución
|
|
95
|
+
del peer-dep antes de que actualicemos el rango.
|
|
96
|
+
|
|
97
|
+
```jsonc
|
|
98
|
+
// tu package.json
|
|
99
|
+
"dependencies": {
|
|
100
|
+
"@floating-ui/react": "~0.27.0", // tilde — solo patches dentro de 0.27
|
|
101
|
+
"reactigoded": "^1.0.0"
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Una vez FUI llegue a `1.0.0`, este riesgo desaparece (`^1.0.0`
|
|
106
|
+
permite minor bumps con backwards compat semver-standard).
|
|
107
|
+
|
|
108
|
+
## CSS imports
|
|
109
|
+
|
|
110
|
+
8 entradas. Lo habitual: importa solo `design.css` (+ opcionalmente `fonts.css` si quieres las tipografías Google del DS).
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
// 100% variables --ig-* + keyframes. Cero selectores globales, cero
|
|
114
|
+
// requests remotos. Útil si construyes tus propios componentes sobre los
|
|
115
|
+
// tokens del DS sin cargar nada más.
|
|
116
|
+
import "reactigoded/styles/tokens.css"; // ~98 KB
|
|
117
|
+
|
|
118
|
+
// Globales mínimos: box-sizing + html scroll + scrollbars + ::selection +
|
|
119
|
+
// prefers-reduced-motion / contrast / forced-colors. Garantías a11y +
|
|
120
|
+
// scrollbar tematizada. Requiere tokens.css.
|
|
121
|
+
import "reactigoded/styles/base.css"; // ~4 KB
|
|
122
|
+
|
|
123
|
+
// Solo clases .ig-* (utilities + componentes). Cero globales. Requiere
|
|
124
|
+
// tokens.css + base.css.
|
|
125
|
+
import "reactigoded/styles/components.css"; // ~363 KB
|
|
126
|
+
|
|
127
|
+
// Atajo: tokens + base + components vía @import. Lo habitual.
|
|
128
|
+
import "reactigoded/styles/design.css"; // ~370 KB total
|
|
129
|
+
|
|
130
|
+
// Estilos por defecto para HTML nativo (h1-h6, p, a, button, input, table,
|
|
131
|
+
// code, blockquote…). NO lo importes si ya usas Tailwind preflight,
|
|
132
|
+
// Bootstrap reboot u otro reset.
|
|
133
|
+
import "reactigoded/styles/reset.css"; // ~5.5 KB
|
|
134
|
+
|
|
135
|
+
// Tipografías Google Fonts oficiales del DS (Electrolize / Saira / JetBrains
|
|
136
|
+
// Mono). Opt-in desde 1.0.0-beta.3: el paquete ya NO impone request remoto
|
|
137
|
+
// al consumer. Si no lo importas, los componentes caen al fallback
|
|
138
|
+
// system-ui declarado en tokens.css. Recomendado: self-host con next/font
|
|
139
|
+
// o @fontsource/* para mejor LCP, privacidad y CSP.
|
|
140
|
+
import "reactigoded/styles/fonts.css"; // ~2 KB (solo @import a Google Fonts)
|
|
141
|
+
|
|
142
|
+
// Utilities pseudo-class (hover:ig-bg-brand, focus:..., etc.) — solo si
|
|
143
|
+
// usas las utilities directamente en HTML.
|
|
144
|
+
import "reactigoded/styles/state.css"; // ~6.5 MB sin gzip / ~700 KB gzipped
|
|
145
|
+
|
|
146
|
+
// Atajo final: design + reset + state vía @import (sin duplicar bytes).
|
|
147
|
+
import "reactigoded/styles/all.css";
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Escenarios típicos
|
|
151
|
+
|
|
152
|
+
| Caso de uso | Imports |
|
|
153
|
+
|---------------------------------------------------|--------------------------------------------|
|
|
154
|
+
| Uso normal del DS | `design.css` |
|
|
155
|
+
| DS + tipografías oficiales Google Fonts | `design.css` + `fonts.css` |
|
|
156
|
+
| DS + estilos para HTML nativo | `design.css` + `reset.css` |
|
|
157
|
+
| DS completo con HTML nativo y utilities pseudo | `all.css` (+ `fonts.css` aparte si quieres)|
|
|
158
|
+
| Solo tokens, construyo encima | `tokens.css` |
|
|
159
|
+
| Tokens + a11y baseline, mis componentes | `tokens.css` + `base.css` |
|
|
160
|
+
| Tema custom, mismas clases del DS | `design.css` + override `:root` |
|
|
161
|
+
|
|
162
|
+
> El `<dialog>` de `<Dialog>` / `<AlertDialog>` y los componentes con flex/transition usan
|
|
163
|
+
> `var(--ig-*)` definidos en `design.css`. **Si solo importas `state.css` o
|
|
164
|
+
> `reset.css`, los componentes no tendrán estilo.**
|
|
165
|
+
|
|
166
|
+
> El `reset.css` se separó del `design.css` en `1.0.0-beta.1` (antes estaba
|
|
167
|
+
> activo dentro de `design.css`). Si actualizas desde una beta anterior y
|
|
168
|
+
> notas que tu HTML nativo perdió estilos, importa `reset.css`.
|
|
169
|
+
|
|
170
|
+
> ⚠️ **Breaking visual desde `1.0.0-beta.5`**: el `reset.css` ya no estiliza
|
|
171
|
+
> `<button>` con la marca. Antes daba a todo `<button>` `background: vitreus`
|
|
172
|
+
> + `color: text-on-vitreus`; ahora salen `background: transparent`,
|
|
173
|
+
> `color: inherit`, `border: 0`, `padding: 0`, `cursor: pointer`. Si tu app
|
|
174
|
+
> dependía de que cualquier `<button>` nativo apareciera con look brand
|
|
175
|
+
> "gratis", ahora los verás transparentes. **Migración**: añade la clase
|
|
176
|
+
> base `.ig-btn` + la variante (`.ig-btn-brand`, `.ig-btn-secondary`,
|
|
177
|
+
> `.ig-btn-success`, `.ig-btn-warning`, `.ig-btn-danger`, `.ig-btn-info`,
|
|
178
|
+
> `.ig-btn-outline-*`, `.ig-btn-ghost-*`, `.ig-btn-link`) a esos
|
|
179
|
+
> elementos — usa preferentemente el componente `<Button variant="…">`
|
|
180
|
+
> de la librería, esas clases son la API CSS pública subyacente.
|
|
181
|
+
> **Razón**: combinaciones bg/color heredadas rompían contraste cuando
|
|
182
|
+
> un wrapper aplicaba sus propios colores.
|
|
183
|
+
|
|
184
|
+
### Globales aplicados por `base.css` (incluido en `design.css`)
|
|
185
|
+
|
|
186
|
+
`design.css` **no estiliza** elementos HTML nativos como `h1`, `p`, `a`,
|
|
187
|
+
`button`, `input` o `table` — eso vive en `reset.css` (opt-in).
|
|
188
|
+
|
|
189
|
+
Sí aplica un baseline global mínimo (`base.css`), pensado como
|
|
190
|
+
infraestructura del sistema (no como opinión visual sobre tu HTML):
|
|
191
|
+
|
|
192
|
+
| Selector / @-rule | Qué hace |
|
|
193
|
+
|---|---|
|
|
194
|
+
| `*, *::before, *::after { box-sizing: border-box }` | Necesario para que padding+border de los componentes calcule el tamaño correcto. |
|
|
195
|
+
| `html { scroll-behavior, scrollbar-gutter, accent-color, caret-color }` | Suaviza scroll, reserva gutter de scrollbar, fija color de focus en checkboxes/radios nativos y caret de inputs. |
|
|
196
|
+
| `::-webkit-scrollbar*` | Scrollbar tematizada (solo Chrome/Edge/Safari). |
|
|
197
|
+
| `::selection`, `::-moz-selection` | Color de selección de texto coherente con la marca. |
|
|
198
|
+
| `@media (prefers-reduced-motion: reduce)` | Reduce animation/transition a `0.01ms` para usuarios con sensibilidad al movimiento. **Garantía a11y, no opcional.** |
|
|
199
|
+
| `@media (prefers-contrast: more)` | Refuerza bordes en `.ig-btn`, `.ig-input`, `.ig-card`. |
|
|
200
|
+
| `@media (forced-colors: active)` | Compatibilidad con Windows High Contrast Mode. |
|
|
201
|
+
|
|
202
|
+
**Si quieres cero globales** en una sub-zona aislada, importa solo
|
|
203
|
+
`tokens.css` + `components.css` (sin `base.css`). Pierdes el baseline a11y
|
|
204
|
+
del sistema; asegúrate de que ya lo tienes en tu propia capa.
|
|
205
|
+
|
|
206
|
+
## Uso
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
import {
|
|
210
|
+
Button,
|
|
211
|
+
Dialog,
|
|
212
|
+
DialogTrigger,
|
|
213
|
+
DialogContent,
|
|
214
|
+
DialogHeader,
|
|
215
|
+
DialogBody,
|
|
216
|
+
DialogClose,
|
|
217
|
+
Toast,
|
|
218
|
+
ToastProvider,
|
|
219
|
+
useToast,
|
|
220
|
+
} from "reactigoded";
|
|
221
|
+
import "reactigoded/styles/design.css";
|
|
222
|
+
|
|
223
|
+
function App() {
|
|
224
|
+
return (
|
|
225
|
+
<ToastProvider position="top-right">
|
|
226
|
+
<Page />
|
|
227
|
+
</ToastProvider>
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function Page() {
|
|
232
|
+
const { toast } = useToast();
|
|
233
|
+
return (
|
|
234
|
+
<Button onClick={() => toast({ variant: "success", title: "Guardado" })}>
|
|
235
|
+
Guardar
|
|
236
|
+
</Button>
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Componentes (32)
|
|
242
|
+
|
|
243
|
+
| Categoría | Componentes |
|
|
244
|
+
|---|---|
|
|
245
|
+
| **Acciones** | `Button`, `IconButton`, `Chip`, `Pagination` |
|
|
246
|
+
| **Display** | `Avatar`, `AvatarGroup`, `Badge`, `Card` (+`CardHeader`/`Body`/`Footer`/`Image`/`Divider`), `Divider`, `Skeleton`, `Spinner`, `Timeline`+`TimelineItem` |
|
|
247
|
+
| **Feedback** | `Alert`, `AlertDialog`+`AlertDialogTrigger`+`AlertDialogContent`+`AlertDialogHeader`+`AlertDialogBody`+`AlertDialogFooter`+`AlertDialogClose`, `Dialog`+`DialogTrigger`+`DialogContent`+`DialogHeader`+`DialogBody`+`DialogFooter`+`DialogClose`, `Progress`, `Toast`+`ToastProvider`+`useToast`, `Tooltip`, `FloatingTreeRoot` |
|
|
248
|
+
| **Formularios** | `Checkbox`, `Input` (+`Label`/`Helper`/`ErrorText`/`InputGroup`/`InputAddon`), `Radio`, `Rating`, `NativeSelect`, `Slider`, `Switch`, `Textarea`, `ThemeToggle` |
|
|
249
|
+
| **Navegación** | `Accordion`+`AccordionItem`+`AccordionHeader`+`AccordionContent`, `Breadcrumb`+`BreadcrumbItem`, `Menu`+`MenuTrigger`+`MenuContent`+`MenuItem`+`MenuSeparator`+`MenuLabel`, `Navbar`+`NavbarLogo`+`NavbarNav`+`NavbarLink`+`NavbarActions`+`NavbarMenuButton`, `Sidebar`+`SidebarHeader`+`SidebarNav`+`SidebarItem`+`SidebarFooter`+`SidebarToggle`+`SidebarDivider`+`SidebarSection`, `Stepper`+`Step`, `Table` (+`TableHead`/`Body`/`Foot`/`Row`/`HeaderCell`/`Cell`/`Caption`), `Tabs`+`TabsList`+`TabsTrigger`+`TabsContent` |
|
|
250
|
+
|
|
251
|
+
Hooks públicos: `useTheme`, `useToast`, `useControllableState` + el componente helper `FloatingTreeRoot` (anidación de floats). Detalle completo en la sección [Hooks públicos del DS](#hooks-públicos-del-ds) (D11 beta.24).
|
|
252
|
+
|
|
253
|
+
> **D11 / B-04 (RC1+beta.24)**: los context hooks internos (`useAccordion`,
|
|
254
|
+
> `useTabs`, etc.) quedan retirados del API público. Su shape está
|
|
255
|
+
> acoplada a internals del compound; exponerlos firmaría una API que
|
|
256
|
+
> bloquearía refactor a Floating UI. JSDoc marca explícitamente
|
|
257
|
+
> `@public` / `@internal` (D11). Detalle en
|
|
258
|
+
> `docs/decisions/D11-hooks-disposition.md`.
|
|
259
|
+
|
|
260
|
+
## API CSS pública
|
|
261
|
+
|
|
262
|
+
Las clases `.ig-*` **documentadas en esta sección** (las tablas por componente) son **API pública del paquete**
|
|
263
|
+
y se pueden aplicar directamente sobre HTML estático sin montar React (útil
|
|
264
|
+
para emails, PDFs, demos rápidas, fragmentos server-rendered). El convenio
|
|
265
|
+
es uniforme: **clase base + modifiers de variant / size / shape / state**,
|
|
266
|
+
todos kebab-case y todos compuestos por concatenación con guion.
|
|
267
|
+
|
|
268
|
+
Tabla mínima (clase base por componente). Los modifiers siguen el patrón
|
|
269
|
+
estándar `{base}-{variant}` / `{base}-{size}` y se documentan exhaustivamente
|
|
270
|
+
en Storybook → *Fundamentos / CSS API pública* — [referencia con
|
|
271
|
+
tablas detalladas y ejemplos HTML por los 32 componentes](https://igoded.es/?path=/docs/fundamentos-css-api-publica--docs).
|
|
272
|
+
|
|
273
|
+
| Componente | Clase base | Modifiers principales |
|
|
274
|
+
|-------------------------|---------------------------|----------------------------------------------------------------------------------------|
|
|
275
|
+
| `Accordion` | `.ig-accordion` | `-item`, `-item-open`, `-header`, `-content`, `-icon` |
|
|
276
|
+
| `Alert` | `.ig-alert` | variants `-brand`/`-secondary`/`-success`/`-warning`/`-danger`/`-info`/`-neutral`, `-title`, `-description`, `-icon`, `-close` |
|
|
277
|
+
| `Avatar` / `AvatarGroup`| `.ig-avatar` | sizes `-xs`…`-xl`, `-square`, `-group`, `-status-online`/`-busy`/`-away`/`-offline` |
|
|
278
|
+
| `Badge` | `.ig-badge` | variants color, sizes, `-pill`, `-dot` |
|
|
279
|
+
| `Breadcrumb` | `.ig-breadcrumb` | `-item`, `-current`, `-separator` |
|
|
280
|
+
| `Button` | `.ig-btn` | variants `-brand`/`-secondary`/`-success`/`-warning`/`-danger`/`-info`, `-outline-*`, `-ghost-*`, `-link`, sizes `-xs`…`-xl`, `-block`, `-icon`, `-loading` |
|
|
281
|
+
| `Card` | `.ig-card` | `-header`, `-body`, `-footer`, `-image`, `-divider`, `-bordered` |
|
|
282
|
+
| `Checkbox` | `.ig-checkbox` | variants color, sizes |
|
|
283
|
+
| `Chip` | `.ig-chip` | variants color, `-close` |
|
|
284
|
+
| `Divider` | `.ig-divider` | variants color, `-vertical`, `-dashed`, `-with-text` |
|
|
285
|
+
| `Menu` | `.ig-menu` | `-trigger`, `-content`, `-item`, `-separator`, `-label` *(portal real via Floating UI, D2/D7 beta.24)* |
|
|
286
|
+
| `Input` / `Textarea` / `NativeSelect` | `.ig-input` · `.ig-textarea` · `.ig-native-select` | `-invalid`, `-valid`, `-addon`, `-group`, `-textarea-auto`, `-select-auto` |
|
|
287
|
+
| `Dialog` / `AlertDialog` | `.ig-dialog` *(<dialog> nativo)* | `-header`, `-body`, `-footer`, `-close`, sizes `-sm`…`-xl`/`-full`, `-backdrop-blur`/`-dark`/`-light`/`-no-backdrop`, `-loading`. `AlertDialog` aplica `role="alertdialog"` + `closeOnBackdrop=false` default (D8 beta.24) |
|
|
288
|
+
| `Navbar` | `.ig-navbar` | `-logo`, `-nav`, `-actions`, `-link`, `-menu-button`, `-sticky`/`-fixed` |
|
|
289
|
+
| `Pagination` | `.ig-pagination` | variants color, `-active` |
|
|
290
|
+
| `Progress` | `.ig-progress` | `-bar`, variants color, sizes |
|
|
291
|
+
| `Radio` | `.ig-radio` | variants color, sizes |
|
|
292
|
+
| `Rating` | `.ig-rating` | sizes `-sm`/`-md`/`-lg`, `-readonly` |
|
|
293
|
+
| `Sidebar` | `.ig-sidebar` | `-header`, `-nav`, `-item`, `-section`, `-footer`, `-toggle`, `-divider`, `-collapsed` |
|
|
294
|
+
| `Skeleton` | `.ig-skeleton` | `-avatar`, `-avatar-lg`, `-text`, `-rect`, `-circle` |
|
|
295
|
+
| `Slider` | `.ig-slider` | `-group`, `-value` |
|
|
296
|
+
| `Spinner` | `.ig-spinner` | variants color, sizes |
|
|
297
|
+
| `Stepper` | `.ig-stepper` | `-labeled` |
|
|
298
|
+
| `Switch` / `ThemeToggle`| `.ig-switch` | variants color, sizes |
|
|
299
|
+
| `Table` | `.ig-table` | `-bordered`, `-auto`, `-row`, `-header-cell`, `-cell`, `-caption` |
|
|
300
|
+
| `Tabs` | `.ig-tabs` | variants color, `-content`, `-list`, `-tab`, `-panel` |
|
|
301
|
+
| `Timeline` | `.ig-timeline` | `-item`, `-content`, `-date` |
|
|
302
|
+
| `Toast` | `.ig-toast` | placement `-top-left`/`-top-right`/`-bottom-left`/`-bottom-right`/`-bottom-center` … |
|
|
303
|
+
| `Tooltip` | `.ig-tooltip` | placement `-place-top`/`-place-bottom`/`-place-left`/`-place-right`, variants `-brand`/`-secondary`/… |
|
|
304
|
+
|
|
305
|
+
> Los modifiers son aditivos: una variante completa de Button es, p.ej.,
|
|
306
|
+
> `<button class="ig-btn ig-btn-brand ig-btn-lg ig-btn-block">…</button>`.
|
|
307
|
+
> La librería React monta exactamente estas mismas clases — los componentes
|
|
308
|
+
> son wrappers delgados sobre la capa CSS.
|
|
309
|
+
|
|
310
|
+
## Patrones recurrentes
|
|
311
|
+
|
|
312
|
+
### Controlled vs. uncontrolled
|
|
313
|
+
|
|
314
|
+
Componentes con estado (`Accordion`, `Dialog`, `AlertDialog`, `Menu`,
|
|
315
|
+
`Pagination`, `Rating`, `Sidebar`, `Slider`, `Stepper`, `Switch`, `Tabs`,
|
|
316
|
+
`ThemeToggle`) soportan ambos modos. Convención DS-wide cerrada en
|
|
317
|
+
beta.24 (D3/D4/D5/D6): `{prop}?` + `default{Prop}?` + `on{Prop}Change`.
|
|
318
|
+
|
|
319
|
+
```tsx
|
|
320
|
+
// Uncontrolled — el componente gestiona su estado.
|
|
321
|
+
<Tabs defaultValue="perfil">…</Tabs>
|
|
322
|
+
|
|
323
|
+
// Controlled — la app gestiona el estado.
|
|
324
|
+
const [tab, setTab] = useState("perfil");
|
|
325
|
+
<Tabs value={tab} onValueChange={setTab}>…</Tabs>
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Convención completa por componente:
|
|
329
|
+
|
|
330
|
+
| Componente | Controlled | Uncontrolled | Callback |
|
|
331
|
+
|---|---|---|---|
|
|
332
|
+
| Accordion | `value` | `defaultValue` | `onValueChange` |
|
|
333
|
+
| Dialog / AlertDialog | `open` | `defaultOpen` | `onOpenChange` |
|
|
334
|
+
| Pagination | `page` | `defaultPage` | `onPageChange` |
|
|
335
|
+
| Rating | `value` | `defaultValue` | `onValueChange` |
|
|
336
|
+
| Sidebar | `collapsed` | `defaultCollapsed` | `onCollapsedChange` |
|
|
337
|
+
| Slider | `value` | `defaultValue` | `onValueChange` |
|
|
338
|
+
| Stepper | `active` | `defaultActive` | `onActiveChange` |
|
|
339
|
+
| Switch | `checked` | `defaultChecked` | `onCheckedChange` |
|
|
340
|
+
| Tabs | `value` | `defaultValue` | `onValueChange` |
|
|
341
|
+
| ThemeToggle | `theme` | `defaultTheme` | `onThemeChange` |
|
|
342
|
+
|
|
343
|
+
`Dialog` y `AlertDialog` (D6/D8 beta.24) además aceptan
|
|
344
|
+
`<DialogTrigger>` / `<AlertDialogTrigger>` para abrir sin necesidad de
|
|
345
|
+
gestionar `open` externamente:
|
|
346
|
+
|
|
347
|
+
```tsx
|
|
348
|
+
<Dialog defaultOpen={false}>
|
|
349
|
+
<DialogTrigger className="ig-btn ig-btn-brand">Abrir</DialogTrigger>
|
|
350
|
+
<DialogContent>
|
|
351
|
+
<DialogHeader>Título <DialogClose /></DialogHeader>
|
|
352
|
+
<DialogBody>Contenido</DialogBody>
|
|
353
|
+
</DialogContent>
|
|
354
|
+
</Dialog>
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Tema light/dark
|
|
358
|
+
|
|
359
|
+
Tres opciones según necesidad:
|
|
360
|
+
|
|
361
|
+
1. **Toggle UI listo**: `<ThemeToggle />` (persiste en `localStorage`,
|
|
362
|
+
aplica `data-theme` a `<html>`, SSR-safe).
|
|
363
|
+
2. **Hook programático**: `const { theme, toggleTheme, setTheme } = useTheme()`
|
|
364
|
+
para integrarlo en menús de ajustes.
|
|
365
|
+
3. **Manual**: `document.documentElement.dataset.theme = "dark"` en cualquier
|
|
366
|
+
momento.
|
|
367
|
+
|
|
368
|
+
Para evitar el flash de tema incorrecto en SSR (Next.js, Remix), inyecta un
|
|
369
|
+
script blocking en `<head>` que aplique `data-theme` antes del paint:
|
|
370
|
+
|
|
371
|
+
```html
|
|
372
|
+
<script>
|
|
373
|
+
(function () {
|
|
374
|
+
// Orden de prioridad: storage > preferencia del sistema > dark (default
|
|
375
|
+
// del DS desde 1.0.0-beta.3 — branding dark-first). Sin esto, hay un
|
|
376
|
+
// flash de tema incorrecto entre el primer paint server y el primer
|
|
377
|
+
// paint cliente cuando el usuario tiene tema persistido distinto.
|
|
378
|
+
try {
|
|
379
|
+
var stored = localStorage.getItem("theme");
|
|
380
|
+
var systemDark =
|
|
381
|
+
typeof window.matchMedia === "function" &&
|
|
382
|
+
window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
383
|
+
var t = stored || (systemDark ? "dark" : "light") || "dark";
|
|
384
|
+
document.documentElement.dataset.theme = t;
|
|
385
|
+
} catch (e) {
|
|
386
|
+
document.documentElement.dataset.theme = "dark";
|
|
387
|
+
}
|
|
388
|
+
})();
|
|
389
|
+
</script>
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Hooks públicos del DS
|
|
393
|
+
|
|
394
|
+
El DS expone cuatro símbolos como API pública estable (`@public` en su
|
|
395
|
+
JSDoc). Importables directamente desde `"reactigoded"`:
|
|
396
|
+
|
|
397
|
+
| Símbolo | Para qué sirve | Return type |
|
|
398
|
+
|---|---|---|
|
|
399
|
+
| `useTheme()` | Lee/escribe el tema activo (`data-theme` en `<html>`). Observer con `useSyncExternalStore`, SSR-safe. | `UseThemeReturn` |
|
|
400
|
+
| `useControllableState()` | Pattern controlled/uncontrolled estándar para componentes con estado. Soporta modo `derive()` para fuentes externas (storage, MediaQuery). | `UseControllableStateReturn<T>` |
|
|
401
|
+
| `useToast()` | Dispara toasts desde cualquier hijo de `<ToastProvider>`. Devuelve `{ toast, dismiss, dismissAll }`. | `UseToastReturn` |
|
|
402
|
+
| `FloatingTreeRoot` | Componente. Envuelve la app si anidas Tooltips/Popovers/Menus del DS y quieres cascade dismiss. Opt-in: sin el wrapper, cada float opera independiente. | — |
|
|
403
|
+
|
|
404
|
+
```tsx
|
|
405
|
+
import {
|
|
406
|
+
useTheme,
|
|
407
|
+
useControllableState,
|
|
408
|
+
useToast,
|
|
409
|
+
FloatingTreeRoot,
|
|
410
|
+
type UseToastReturn,
|
|
411
|
+
} from "reactigoded";
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Hooks `useDropdown` / `useTabs` / `useFloatingNode` / `useSidebar` / etc. NO son
|
|
415
|
+
públicos — son detalle de implementación de cada componente. Detalle completo
|
|
416
|
+
en [`docs/decisions/D11-hooks-disposition.md`](docs/decisions/D11-hooks-disposition.md).
|
|
417
|
+
|
|
418
|
+
### Accesibilidad
|
|
419
|
+
|
|
420
|
+
- Todos los componentes interactivos siguen el patrón [WAI-ARIA APG](https://www.w3.org/WAI/ARIA/apg/) más cercano: `role`, `aria-*`, keyboard nav, focus management.
|
|
421
|
+
- Los textos por defecto (`aria-label`, `closeLabel`, `prevLabel`, etc.) están
|
|
422
|
+
**en español**. Para otros idiomas, pasa la prop con tu traducción:
|
|
423
|
+
|
|
424
|
+
```tsx
|
|
425
|
+
<Pagination
|
|
426
|
+
prevLabel="Previous"
|
|
427
|
+
nextLabel="Next"
|
|
428
|
+
aria-label="Pagination"
|
|
429
|
+
…
|
|
430
|
+
/>
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
- `Dialog` / `AlertDialog` usan `<dialog>` HTML nativo (focus trap,
|
|
434
|
+
ESC, top-layer y `aria-modal` automáticos). `AlertDialog` aplica
|
|
435
|
+
`role="alertdialog"` + `closeOnBackdrop=false` por defecto (D8).
|
|
436
|
+
- `Tooltip` inyecta `aria-describedby` en el child y un `<span role="tooltip">`
|
|
437
|
+
sr-only para lectores de pantalla.
|
|
438
|
+
|
|
439
|
+
### SSR / hydration
|
|
440
|
+
|
|
441
|
+
- Todos los componentes son SSR-safe: `renderToString` no lanza con
|
|
442
|
+
ningún componente público (verificado en `src/__ssr__.test.tsx`,
|
|
443
|
+
37 casos sobre los 32 componentes raíz).
|
|
444
|
+
- Componentes que necesitan estado del cliente (ej. `ThemeToggle`,
|
|
445
|
+
para sincronizarse con un script anti-flash que ya escribió
|
|
446
|
+
`data-theme` en `<html>` antes de la hidratación) leen el DOM
|
|
447
|
+
detrás de guards `typeof document !== "undefined"`. En server caen
|
|
448
|
+
a defaults sensatos sin crashear; en cliente recuperan el estado
|
|
449
|
+
real evitando hydration mismatches.
|
|
450
|
+
- `<Dialog>` / `<AlertDialog>` no llaman `showModal()` en server (el
|
|
451
|
+
`<dialog>` queda con `display:none` hasta que el efecto cliente lo
|
|
452
|
+
abre — sin flash).
|
|
453
|
+
- `<Toast>` se renderiza inline en SSR (no portal) hasta que
|
|
454
|
+
`document.body` está disponible.
|
|
455
|
+
- Los effects (`useEffect`, `useLayoutEffect`) corren solo en
|
|
456
|
+
cliente — comportamiento React estándar.
|
|
457
|
+
|
|
458
|
+
## Browserslist
|
|
459
|
+
|
|
460
|
+
Targets oficiales (últimas 2 versiones de Chrome, Firefox, Safari, Edge):
|
|
461
|
+
|
|
462
|
+
- `<dialog>.showModal()`: 98% global ✓
|
|
463
|
+
- `color-mix()`: 95% ✓
|
|
464
|
+
- `backdrop-filter`: 97% ✓
|
|
465
|
+
- `field-sizing` (`Textarea auto`): Chrome 123+, Safari 17.4+; **Firefox aún
|
|
466
|
+
no** — el `Textarea auto` en Firefox cae al comportamiento `rows` por
|
|
467
|
+
defecto.
|
|
468
|
+
|
|
469
|
+
## Scripts (dev)
|
|
470
|
+
|
|
471
|
+
```bash
|
|
472
|
+
npm run dev # playground (http://localhost:5173)
|
|
473
|
+
npm run storybook # docs/demos (http://localhost:6006)
|
|
474
|
+
npm run build # dist/ con index.js + index.cjs + .d.ts + styles/
|
|
475
|
+
npm run test:unit # vitest happy-dom (suite completa)
|
|
476
|
+
npm run test:unit:ci # como test:unit, con isolate=true + pool=forks (CI estricto)
|
|
477
|
+
npm run test:contrast # CSS estático: pares bg/color + geometría OKLCH
|
|
478
|
+
npm run test:storybook # vitest browser Chromium + axe-a11y (DOM real)
|
|
479
|
+
npm run verify # lint + typecheck + test:unit + test:contrast + build + test:storybook + verify:size
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
**`test:contrast` vs `test:storybook`** — son guardrails complementarios,
|
|
483
|
+
no redundantes. `test:contrast` parsea `igoded-components.css` con postcss
|
|
484
|
+
y valida cada regla que declara `color` + `background[-color]` en el mismo
|
|
485
|
+
bloque, contra los 14 hex de los pares cardinales en ambos temas. Es rápido
|
|
486
|
+
y atrapa la mayoría de regresiones, pero **no cubre**: alphas/tinted con
|
|
487
|
+
`color-mix(... transparent)` o `rgba(... .5)` (no compone contra el padre),
|
|
488
|
+
combinators padre-hijo en reglas separadas (solo ve pares dentro del mismo
|
|
489
|
+
bloque), gradients ni `currentColor`. Para esos casos depende
|
|
490
|
+
`test:storybook`, que ejecuta cada story en chromium headless con axe-core
|
|
491
|
+
sobre el DOM final ya pintado.
|
|
492
|
+
|
|
493
|
+
## Estructura
|
|
494
|
+
|
|
495
|
+
```
|
|
496
|
+
src/
|
|
497
|
+
├── components/ # 32 carpetas (1 por componente raíz)
|
|
498
|
+
├── hooks/ # useTheme
|
|
499
|
+
├── utils/ # cn (wrapper de clsx)
|
|
500
|
+
├── styles/ # igoded-{tokens,base,components,design,reset,state-css}.css
|
|
501
|
+
└── index.ts # entry del paquete
|
|
502
|
+
scripts/
|
|
503
|
+
└── strip-orphan-css.mjs # limpia utilities de state-css apuntando a tokens eliminados
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
## Decisiones técnicas
|
|
507
|
+
|
|
508
|
+
- **`ref` como prop** (React 19) — sin `forwardRef`, mejor inferencia.
|
|
509
|
+
- **Sin `PropTypes`** — TypeScript estricto.
|
|
510
|
+
- **`exactOptionalPropertyTypes: true`** — `prop={undefined}` no equivale a
|
|
511
|
+
no pasar la prop.
|
|
512
|
+
- **CSS-first** — la lógica visual vive en `.css`; los componentes React
|
|
513
|
+
son wrappers delgados que aplican clases condicionalmente.
|
|
514
|
+
- **Sin transpilación CSS** — el CSS publicado usa `color-mix()`,
|
|
515
|
+
`backdrop-filter`, `@container`, `field-sizing`. Targets modernos
|
|
516
|
+
(browserslist arriba).
|
|
517
|
+
- **Sourcemaps desactivados en publish** — ni sourcemaps de JS ni
|
|
518
|
+
`.d.ts.map` se publican. El go-to-definition del consumer cae en los
|
|
519
|
+
`.d.ts` (tipos); el source `.ts` no se shippea (`files`), así que un
|
|
520
|
+
`.d.ts.map` colgaría apuntando a `src` ausente (#23).
|
|
521
|
+
- **`sideEffects: ["**/*.css"]`** — bundlers tree-shake JS pero conservan
|
|
522
|
+
CSS imports.
|
|
523
|
+
- **`console.error` legítimos de `tabbable`** — `tabbable` es dep
|
|
524
|
+
transitiva de `@floating-ui/react` (vía `Tooltip` y futuros
|
|
525
|
+
`Popover`/`HoverCard`). Para focus management sobre nodos sin
|
|
526
|
+
tabIndex válido, emite `console.error` del propio upstream. **No
|
|
527
|
+
es bug del DS** — viene del ecosistema Floating UI. El gate de CI
|
|
528
|
+
`bundle-no-dev-warns` filtra solo el prefijo `[reactigoded]` para
|
|
529
|
+
no confundir esos errors legítimos con regresiones nuestras.
|
|
530
|
+
|
|
531
|
+
## Desarrollo
|
|
532
|
+
|
|
533
|
+
Para trabajar sobre el repo (no como consumidor del paquete):
|
|
534
|
+
|
|
535
|
+
```bash
|
|
536
|
+
git clone https://github.com/ivangc1/reactigoded.git
|
|
537
|
+
cd reactigoded
|
|
538
|
+
npm ci
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
`npm ci` plano resuelve limpio: el ERESOLVE de devDeps (eslint 10 vs
|
|
542
|
+
`eslint-plugin-jest-dom`/`jsx-a11y` con peer `^9`) se cierra con
|
|
543
|
+
`overrides` en package.json (#138), y el bump de toolchain
|
|
544
|
+
(storybook 10.5 / vitest 4) alineó el peer de `@vitest/browser`. Ya no
|
|
545
|
+
hace falta `--legacy-peer-deps` (verificado: `npm ci` plano instala 532
|
|
546
|
+
paquetes sin ERESOLVE).
|
|
547
|
+
|
|
548
|
+
**No afecta a los consumidores del paquete**: cuando alguien instala
|
|
549
|
+
`reactigoded` como dep, solo se resuelven `peerDependencies` (`react`,
|
|
550
|
+
`react-dom`, `@floating-ui/react`). Las devDependencies del repo no
|
|
551
|
+
viajan al consumer.
|
|
552
|
+
|
|
553
|
+
## Licencia
|
|
554
|
+
|
|
555
|
+
MIT — ver [LICENSE](./LICENSE).
|
|
556
|
+
|