docs(layout): READMEs for 8 layout primitives (audit PASS)

Closes `E-2.3` audit error for the 8 Layout Batch 1 primitives. Each
README follows the canonical structure required by the
`component-audit` script:

- Baseline — origin (air branch), adaptations applied (drop air- prefix,
  rename --air-space-N → --space-N, ActiveEidos.resolve)
- Superficie — minimal usage snippet
- Comparativa — feature parity table vs Radix Themes / Chakra UI /
  Mantine, with explicit "No — gap conocido" markers for missing
  features
- Decisiones — architectural rationale (Radix item/container split,
  composition over inheritance, etc.)
- Eventos Sema — 0-event justification
- Gaps — known feature gaps with disposition markers
  (implementar / diferir / descartar) and reference attribution
- Referencias — links to canonical reference docs
- Passive justification — why scope is `eidos` only

Notable gaps documented for backlog:
- Flex.alignContent (Radix/Chakra)
- Grid.columns/rows numeric shorthand (Radix)
- Grid.inline boolean (parity with Flex)
- Grid.alignContent (Radix/Chakra)
- Stack.divider slot (Chakra)
- Stack/Flex HStack/VStack helpers (Chakra ergonomics)
- Group.grow boolean (Mantine — children fill equally)
- Group.preventGrowOverflow (Mantine)
- Wrap.shouldWrapChildren (Chakra)
- Section.as prop for semantic <section> render

`npm run component:audit`: 77 components, 74 PASS, 3 NEEDS-WORK
(month-grid, year-grid, time-range-picker — pre-existing, unrelated
to layout work).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
active-uix
dev 5 months ago
parent 60a50f1c27
commit fdb0e68028

@ -0,0 +1,97 @@
# Eidos Box
Universal box-model utility. Eidos-native: cada prop mapea a una
custom property `--box-*` emitida inline en un único `<div data-box>`,
y la receta cae con `revert-layer` a la cascada normal cuando no se
fija. Box es la primitiva sobre la que se componen Flex, Grid, Stack,
Group, Wrap, Container y Section.
## Superficie
```svelte
<Box padding={4} gap={3} display="flex" maxWidth={600}>…</Box>
<!-- Como item de un Grid/Flex padre: -->
<Box gridColumn="1 / 3" placeSelf="center">…</Box>
```
## Baseline
Origen: `air/components/layout/box` (rama `morfo-runtime`).
Adaptaciones para eidos: drop del prefijo `air-`, selectores
`[data-box]` directos, vars renombradas a `--box-*`, sustitución de
`var(--air-space-N)` por `var(--space-N)` y resolución reactiva de
props responsive vía `ActiveEidos.require().resolve()`.
Decisión clave introducida en `66c6897c`: los props de **grid item
placement** (`gridColumn`, `gridRow`, `gridArea`, `placeSelf`) viven
en Box, no en Grid. Son props del HIJO que declara su slot, no del
container. Air los puso en Grid — corregido durante el port.
## Comparativa
| Capacidad | UIX (eidos) | Radix Themes | Chakra UI | Mantine |
| --- | --- | --- | --- | --- |
| Display | Sí | Sí | Sí | Sí |
| Width / height + min/max | Sí | Sí | Sí | Sí |
| Padding / margin (+ shorthands X/Y/per-side) | Sí (`paddingX`, `paddingY`, `paddingTop`…) | Sí (`p`, `px`, `pt`…) | Sí | Sí |
| Position + insets | Sí | Sí | Sí | Sí |
| Overflow + axis variants | Sí | Sí | Sí | Sí |
| Flex item (`flex`, `grow`, `shrink`, `basis`, `order`) | Sí | Sí | Sí | — (en Flex) |
| Grid item (`gridColumn`, `gridRow`, `gridArea`, `placeSelf`) | **Sí** (movido desde Grid 2026-05-22) | Sí | Sí | — |
| `align-self` / `justify-self` | Sí | Sí | Sí | — |
| Background / color / shadow | **No** — UIX separa layout de visual treatment | Sí (`bg`, `style`) | Sí (`bg`, `color`) | Sí (`bg`) |
| `as` prop para semantic tag | **No** — root fijo `<div>` (batch 1) | Sí | Sí (vía polymorphic ref) | Sí (`component`) |
| Responsive prop syntax | Sí (`ResponsiveProp` via Eidos) | Sí (`{ initial: …, sm: … }`) | Sí | Sí |
| Container-side flex/grid (`alignItems`, `justifyContent`, `templateColumns`…) | **No** — viven en Flex/Grid (split Radix) | Split Radix | Mezclado en Box | Split Radix |
## Decisiones
- **Item-side props en Box, container-side en Flex/Grid** — split estilo
Radix Themes / Mantine. Chakra y MUI mezclan todo en Box, pero
el split deja un API más predecible.
- **No `bg`/`color`/`shadow`** — UIX separa estructura de tratamiento
visual. Esos props viven en componentes con `variant`/`color`
(avatar, dialog, button…). Box es sólo layout.
- **Root `<div>` fijo** — sin `as` prop en batch 1. Si el consumidor
necesita semantic tag (`<main>`, `<section>`, `<article>`), envuelve
Box. Se reconsiderará si llegan ≥2 casos reales que lo justifiquen.
- **Inline styles, no classnames generados** — el style attr lista
cada `--box-*` declarada; debugger en DevTools muestra exactamente
qué propiedades activas tiene cada Box.
- **`revert-layer` como fallback** — props sin setear no fuerzan
`initial`, dejan que la cascada normal aplique. Permite mezclar Box
con cualquier otro CSS sin "ganar" sobre estilos no relacionados.
## Eventos Sema
Box declara 0 eventos. Es una primitiva pasiva: no commit, no emerge,
no reacciona a nada — sólo estiliza hijos vía cascade. Componentes
que animan/cambian estado al aparecer componen Box con una primitiva
interactiva (popover, drawer, collapsible) que sí posee los verbos
sema relevantes.
## Gaps
| Gap | Disposición | Detalle |
| --- | --- | --- |
| `as` prop para semantic tag (`section`, `article`, `main`, `aside`…) | **diferir** | Esperamos ≥2 casos reales antes de añadir polimorfismo. Hoy se envuelve Box en el tag semántico. |
| `bg` / `color` shorthand sobre tokens UIX | **descartar** | Box es layout puro. Los componentes con variant/color son los que llevan tratamiento visual. |
| `borderRadius` / `boxShadow` props | **descartar** | Idem — escapar vía `style=` cuando se necesite un one-off. |
| `flexBasis` (alias de `basis`) | **diferir** | Posible alias por familiaridad con devs Chakra. Bajo prioridad. |
| Documentación per-prop con ejemplos visuales individuales | **implementar** | En la pasada de docs final. Hoy el demo cubre los casos comunes. |
## Referencias
- Radix Themes Box: https://www.radix-ui.com/themes/docs/components/box
- Chakra UI Box: https://chakra-ui.com/docs/components/box
- Mantine Box: https://mantine.dev/core/box/
- MUI Box: https://mui.com/system/react-box/
## Passive justification
Visual-only primitive (`scope: ['eidos']` en el morfo). Una sola
part Provider que emite el marker `[data-box]`, sin estados, sin
data-attrs específicos, sin ARIA, sin keyboard. El recipe consume
las CSS variables que el componente escribe inline. No hay nada que
animar, ningún ciclo de vida que enviar a sema.

@ -0,0 +1,65 @@
# Eidos Container
Wrapper de ancho máximo centrado. Limita el ancho del contenido a un
tamaño canónico (sm/md/lg/xl/full) y aplica margen automático en los
laterales para centrarlo.
## Superficie
```svelte
<Container size="md">
<h1>Title</h1>
<p>Body bounded to the medium max-width.</p>
</Container>
```
## Baseline
Origen: `air/components/layout/container`. Adaptación estándar.
Tamaños mapean a tokens `--container-size-{xs,sm,md,lg,xl}` en el
recipe; `full` desactiva el max-width.
## Comparativa
| Capacidad | UIX | Radix Themes | Chakra UI | Mantine |
| --- | --- | --- | --- | --- |
| `size` chip (sm/md/lg/xl/full) | Sí (`xs`–`xl` + `full`) | Sí (`1`–`4`) | Sí (`sm`–`8xl`) | Sí (`xs`–`xl`) |
| Centered margin-inline auto | Sí | Sí | Sí | Sí |
| `padding` inherited | Sí (vía Box) | Sí | Sí (`px`) | Sí |
| `fluid` mode (sin max-width) | **No** — gap conocido (usar `size="full"`) | — | — | Sí (`fluid`) |
| `align` start/center/end | Sí (controla margin-inline) | — | — | — |
| Strategy `block` / `grid` | **No** | — | — | Sí |
## Decisiones
- **`size="full"` cumple el rol de `fluid`** — Mantine usa `fluid` boolean
separado; nosotros lo metemos en el size chip para no duplicar API.
- **`align` controla margin-inline** — start/center/end mueven el container
contra el lado izquierdo/derecho. Default center.
- **Padding heredado de Box** — Container no añade padding propio. El consumer
controla padding-block/inline vía las props heredadas.
- **Sin layout strategy `grid`** — Container es un wrapper simple. Si quieres
layout interno, anida un `<Grid>` o `<Flex>`.
## Eventos Sema
0 eventos. Pasivo.
## Gaps
| Gap | Disposición | Detalle |
| --- | --- | --- |
| `fluid` boolean separado | **descartar** | `size="full"` ya cumple. Evita superficie redundante. |
| Strategy `block`/`grid` (Mantine) | **diferir** | Composición con Grid/Flex anidados cubre el caso. |
| Documentación per-size con ejemplos visuales | **implementar** | Pasada de docs final. |
## Referencias
- Radix Themes Container: https://www.radix-ui.com/themes/docs/components/container
- Chakra UI Container: https://chakra-ui.com/docs/components/container
- Mantine Container: https://mantine.dev/core/container/
## Passive justification
Visual-only (`scope: ['eidos']`). Marker `[data-container]`. Sin estado,
sin keyboard, sin ARIA, sin eventos.

@ -0,0 +1,83 @@
# Eidos Flex
`display:flex` container. Eidos-native: añade los props container-side
(`direction`, `align`, `justify`, `wrap`, `rowGap`, `columnGap`) sobre
la superficie completa de [Box](../box/README.md), del que hereda
estructura y se renderiza a través de él. Item-side props
(`alignSelf`, `gridColumn`, `flex`, `grow`, …) viven en el hijo Box.
## Superficie
```svelte
<Flex direction="row" align="center" justify="space-between" gap={3} padding={4}>
<Box>Start</Box>
<Box>Middle</Box>
<Box>End</Box>
</Flex>
```
## Baseline
Origen: `air/components/layout/flex` (rama `morfo-runtime`). Misma
adaptación que Box: drop del prefijo `air-`, vars renombradas a
`--flex-*`, `var(--space-N)` en lugar de `var(--air-space-N)`,
resolución vía `ActiveEidos.resolve`.
Composición: Flex se renderiza a través de `<Box>` con `display="flex"`
fijo. El DOM final es un único `<div data-box data-flex>` — el recipe
de Flex añade selectores `[data-box][data-flex] { … }` sobre los de
Box. Los props heredados (padding, margin, size, position) se pasan
intactos al Box raíz.
## Comparativa
| Capacidad | UIX | Radix Themes | Chakra UI | Mantine |
| --- | --- | --- | --- | --- |
| `direction` (row/column +reverse) | Sí | Sí | Sí (`flexDirection`) | Sí |
| `align` → align-items | Sí | Sí | Sí (`alignItems`) | Sí |
| `justify` → justify-content | Sí | Sí | Sí (`justifyContent`) | Sí |
| `wrap` → flex-wrap | Sí | Sí | Sí (`flexWrap`) | Sí |
| `gap` + `rowGap` / `columnGap` | Sí | Sí (`gap`, `gapX`, `gapY`) | Sí | Sí |
| `inline` boolean (inline-flex) | Sí | Vía `display="inline-flex"` | Sí | Sí (`inline`) |
| `alignContent` (multi-line cross) | **No** — gap conocido | Sí | Sí | Sí |
| Item props heredados de Box | Sí (composición) | Sí | Sí (style-props todo en Box) | — split |
| Responsive | Sí | Sí | Sí | Sí |
## Decisiones
- **Hereda Box por composición, no por mixin** — Flex renderiza a través
de `<Box>` con `display="flex"` fijo. Mantiene el contrato Box-as-foundation
y permite que `[data-box]` siga siendo el selector canónico para todo lo
que pinta como box.
- **`align`/`justify` cortos** — preferimos `align` sobre `alignItems`
(Mantine convention). Coincide con Radix Themes; difiere de Chakra.
- **`inline` boolean en vez de `display="inline-flex"`** — ergonomía;
el resto de la API queda consistente con Box (un solo display).
- **Item props NO en Flex** — `flex`, `grow`, `alignSelf`, `gridColumn`
van en el `<Box>` hijo. Split estilo Radix.
## Eventos Sema
0 eventos. Pasivo — sólo organiza hijos. Mismas reglas que Box.
## Gaps
| Gap | Disposición | Detalle |
| --- | --- | --- |
| `alignContent` (multi-line cross-axis) | **implementar** | Radix + Chakra lo tienen. Útil cuando `wrap` está activo. Backlog Layout fixes. |
| Helpers `HStack` / `VStack` (alias direction-fijo) | **diferir** | Ergonomía Chakra. UIX usa `<Stack direction="…">`. Reconsiderar si la fricción es real. |
| `inline-flex` shorthand alternativo (e.g. `<InlineFlex>`) | **descartar** | `inline` boolean cubre el caso. |
| Slot `divider` entre hijos (separator automático) | **diferir** | Patrón Chakra Stack. Más natural en Stack que en Flex. |
## Referencias
- Radix Themes Flex: https://www.radix-ui.com/themes/docs/components/flex
- Chakra UI Flex: https://chakra-ui.com/docs/components/flex
- Mantine Flex: https://mantine.dev/core/flex/
- MDN flexbox: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_flexible_box_layout
## Passive justification
Visual-only (`scope: ['eidos']`). Una sola part Provider, marker
`[data-flex]`. Sin estados ni keyboard ni ARIA ni eventos. El recipe
consume `--flex-*` writeable inline.

@ -0,0 +1,76 @@
# Eidos Grid
`display:grid` container. Eidos-native: añade los props grid-template /
auto-flow / placement de container (`align`, `justify`, `placeItems`,
`placeContent`) sobre la superficie de [Box](../box/README.md). Item-side
placement (`gridColumn`, `gridRow`, `gridArea`, `placeSelf`) vive en el
hijo Box — corregido en `66c6897c` (air los puso erróneamente en Grid).
## Superficie
```svelte
<Grid templateColumns="repeat(3, 1fr)" gap={3}>
<Box>Cell 1</Box>
<Box gridColumn="2 / 4">Cell 2 (spans 2)</Box>
<Box>Cell 3</Box>
</Grid>
```
## Baseline
Origen: `air/components/layout/grid`. Misma adaptación que el resto.
Composición a través de Box (`<Box data-grid>`), con recipe que añade
selectores `[data-box][data-grid] { … }`.
## Comparativa
| Capacidad | UIX | Radix Themes | Chakra UI | Mantine SimpleGrid |
| --- | --- | --- | --- | --- |
| `templateColumns` / `templateRows` | Sí (string libre) | Sí | Sí | — (sólo cols) |
| `columns` / `rows` shorthand (`columns={3}` → `repeat(3, 1fr)`) | **No** — gap conocido | Sí (`columns="3"`) | Sí (`columns={3}`) | Sí |
| `autoColumns` / `autoRows` / `autoFlow` | Sí | Sí | Sí | — |
| `gap` + `rowGap` / `columnGap` | Sí | Sí | Sí | Sí |
| `align` → align-items | Sí | Sí | Sí | — |
| `justify` → justify-content | Sí | Sí | Sí | — |
| `placeItems` / `placeContent` | Sí | Sí | Sí | — |
| `alignContent` (multi-line) | **No** — gap conocido | Sí | Sí | — |
| `inline` boolean (inline-grid) | **No** — gap conocido | Vía `display="inline-grid"` | Sí | — |
| Item placement (`gridColumn`, `gridRow`, `gridArea`, `placeSelf`) | **En Box** (Radix) | En Box | En Box | — |
| Responsive `breakpoints` | Sí | Sí | Sí | Sí |
## Decisiones
- **Item placement en Box** — corrección del port. Air tenía
`gridColumn`/`gridRow`/`gridArea` en Grid pero son props del HIJO,
no del contenedor. Movidos a Box + añadido `placeSelf`.
- **`templateColumns` como string libre** — más flexible que el shorthand
numérico. El gap `columns` shorthand está en el backlog (ergonomía).
- **Sin `inline-grid` shorthand** — Box ya soporta `display="inline-grid"`
vía passthrough. Backlog para añadir `inline` boolean por paridad con
Flex.
## Eventos Sema
0 eventos. Pasivo — sólo organiza hijos.
## Gaps
| Gap | Disposición | Detalle |
| --- | --- | --- |
| `columns` / `rows` numeric shorthand | **implementar** | Patrón Radix Themes (`columns="3"` → `repeat(3, 1fr)`). Ergonomía Mantine SimpleGrid. Backlog Layout fixes. |
| `inline` boolean | **implementar** | Paridad con Flex.inline. Trivial — display: inline-grid. |
| `alignContent` (multi-line cross-axis align) | **implementar** | Útil con `autoRows` + scroll. Radix lo tiene. |
| Slot/Cell helpers (e.g. `<Grid.Cell column="2 / 4">`) | **diferir** | Box ya cumple. Reconsiderar si emerge un patrón estable. |
| `subgrid` support | **diferir** | Soporte navegador todavía parcheado; esperar penetración. |
## Referencias
- Radix Themes Grid: https://www.radix-ui.com/themes/docs/components/grid
- Chakra UI Grid: https://chakra-ui.com/docs/components/grid
- Mantine SimpleGrid: https://mantine.dev/core/simple-grid/
- MDN grid layout: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout
## Passive justification
Visual-only (`scope: ['eidos']`). Sin estado mutable, sin keyboard,
sin ARIA, sin eventos.

@ -0,0 +1,66 @@
# Eidos Group
Cluster horizontal inline. Es [Flex](../flex/README.md) con `direction="row"`
+ `wrap="wrap"` + `align="center"` por defecto. Útil para barras de
acciones, listas de tags, conjuntos de chips.
## Superficie
```svelte
<Group gap={2}>
<Button>One</Button>
<Button>Two</Button>
<Button>Three</Button>
</Group>
```
## Baseline
Origen: `air/components/layout/group`. Adaptación estándar.
Composición: a través de Flex (`<div data-box data-flex data-group>`).
El recipe sólo aplica defaults distintos a los de Flex puro
(`align: center`, `flex-wrap: wrap`).
## Comparativa
| Capacidad | UIX | Mantine Group | Chakra HStack | Radix Themes |
| --- | --- | --- | --- | --- |
| Row con wrap por defecto | Sí | Sí | No (HStack no wrap) | Vía Flex |
| `gap` / `align` / `justify` | Sí | Sí | Sí | Sí |
| `grow` boolean (hijos llenan ancho equitativamente) | **No** — gap conocido | Sí | No | — |
| `preventGrowOverflow` | **No** — gap conocido | Sí | — | — |
| `attached` (cero gap + radios continuos) | Vía CSS local | No | No | — |
## Decisiones
- **Defaults pensados para action rows** — `align: center`, `wrap: wrap`,
cero margen. Match Mantine Group.
- **Mantine `grow`** — útil para distribuir hijos equitativamente. Sin
añadirlo todavía; backlog.
- **`attached` no es un prop de Group canon** — el demo lo expone para
ilustrar el patrón "buttons attached" pero en producción se hace con
CSS local en el container que envuelve los buttons.
## Eventos Sema
0 eventos. Pasivo.
## Gaps
| Gap | Disposición | Detalle |
| --- | --- | --- |
| `grow` boolean (children fill equally) | **implementar** | Patrón Mantine. Backlog Layout fixes prioritario. |
| `preventGrowOverflow` boolean | **diferir** | Refinamiento de `grow`. Sólo aplica cuando `grow` está activo. |
| `attached` como prop canónico | **diferir** | Hoy se hace con CSS local. Si emerge un patrón estable, promover. |
| Slot `divider` | **diferir** | Mismo backlog que Stack. |
## Referencias
- Mantine Group: https://mantine.dev/core/group/
- Chakra HStack: https://chakra-ui.com/docs/components/stack
- Radix Themes: usa `<Flex direction="row" wrap="wrap">`.
## Passive justification
Visual-only (`scope: ['eidos']`). Marker `[data-group]`, sin estados
ni ARIA. Composición sobre Flex.

@ -0,0 +1,70 @@
# Eidos Section
Bloque con padding vertical canónico. Aplica padding-block según un
size variant (`xs`/`sm`/`md`/`lg`/`xl`) y opcionalmente un tono de
fondo. Pensado para separar secciones de página sin tener que repetir
cálculos de spacing.
## Superficie
```svelte
<Section size="lg" tone="default">
<h2>Section title</h2>
<p>Content with consistent vertical breathing.</p>
</Section>
```
## Baseline
Origen: `air/components/layout/section`. Adaptación estándar.
**Limitación conocida**: el root se renderiza como `<div>` en este
batch (sin `as` prop). Para semantic `<section>` HTML, envuelve
manualmente o espera al batch que añada polimorfismo.
## Comparativa
| Capacidad | UIX | Radix Themes Section | Chakra | Mantine |
| --- | --- | --- | --- | --- |
| `size` chip (xs/sm/md/lg/xl) | Sí | Sí (`1`–`4`) | — (no Section) | — (no Section) |
| Padding-block según size | Sí | Sí | — | — |
| `tone` (background variant) | Sí (`default`/`subtle`/`muted`) | No | — | — |
| Render `<section>` semántico | **No** — `<div>` (batch 1) | Sí | — | — |
Chakra y Mantine no tienen un componente Section dedicado — usan Box
o Container directamente. UIX justifica el componente para encapsular
el padding-block canónico repetido en páginas.
## Decisiones
- **Render como `<div>` en batch 1** — sin `as` prop todavía. Si el SEO o
el screen reader necesita `<section>`, envuelve manualmente. Se
reconsiderará si ≥2 consumers piden polimorfismo.
- **`tone` propio en lugar de `bg` heredado** — `tone` mapea a tokens
canónicos (`surface-default`, `surface-subtle`, `surface-muted`) que
garantizan contraste con el body text. `bg` libre rompería el contrato
de contraste.
- **Padding-block dependiente del size token** — match Radix Themes Section
semantic (sus sizes 1-4 mapean al mismo set).
## Eventos Sema
0 eventos. Pasivo.
## Gaps
| Gap | Disposición | Detalle |
| --- | --- | --- |
| `as` prop para semantic `<section>`/`<article>`/`<main>` | **implementar** | Es el caso de uso primario. Backlog Layout polymorphic batch. |
| Más tonos / background imagery | **diferir** | El tone scale actual es suficiente. Imagery vía `style=`. |
| Padding-inline matching | **diferir** | Hoy se compone con Container dentro de Section. |
## Referencias
- Radix Themes Section: https://www.radix-ui.com/themes/docs/components/section
- Chakra y Mantine: no tienen Section dedicado.
## Passive justification
Visual-only (`scope: ['eidos']`). Marker `[data-section]`. Sin estados
ni keyboard ni ARIA. El size variant define padding-block; el tone
variant define background.

@ -0,0 +1,71 @@
# Eidos Stack
Direction-controlled Flex wrapper. Por defecto vertical (column); con
`direction="row"` se convierte en horizontal. Es azúcar sobre
[Flex](../flex/README.md) cuando lo único que importa es apilar items
con un gap.
## Superficie
```svelte
<Stack gap={3}>
<Box>Row A</Box>
<Box>Row B</Box>
<Box>Row C</Box>
</Stack>
<Stack direction="row" align="center" gap={2}>…</Stack>
```
## Baseline
Origen: `air/components/layout/stack`. Adaptación estándar (drop air,
vars `--stack-*`, `var(--space-N)`).
Composición: se renderiza a través de Flex (no de Box directamente).
El DOM final es `<div data-box data-flex data-stack>`. El recipe de
Stack es prácticamente un marker — todo el comportamiento viene del
Flex inferior.
## Comparativa
| Capacidad | UIX | Chakra Stack | Mantine Stack | Radix Themes |
| --- | --- | --- | --- | --- |
| `direction` row/column | Sí | Sí (Stack/HStack/VStack) | Sólo column (Stack), Group para row | Vía Flex |
| `gap` | Sí | Sí (`spacing`) | Sí | Sí |
| `align` / `justify` | Sí | Sí | Sí | Vía Flex |
| `wrap` | Sí (heredado Flex) | No directo | No | Vía Flex |
| Slot `divider` entre hijos | **No** — gap conocido | Sí (`divider={<Separator/>}`) | Sí (`gap` + Divider component) | — |
| Helpers `HStack` / `VStack` | **No** — gap conocido | Sí | Sí (`Group` = HStack) | — |
## Decisiones
- **Componente único con `direction` en vez de tres componentes**
— preferimos un solo Stack con prop sobre el patrón Chakra
`Stack`/`HStack`/`VStack`. Menos superficie pública, mismo poder.
- **Defaults a column** — match Mantine. Si quieres row con espacio entre
items y wrap, [Group](../group/README.md) ofrece esos defaults.
- **No `divider` slot por ahora** — useful pero no crítico. Backlog.
## Eventos Sema
0 eventos. Pasivo.
## Gaps
| Gap | Disposición | Detalle |
| --- | --- | --- |
| Slot `divider` para insertar separator entre items | **diferir** | Patrón Chakra. Útil para listas/menús. Backlog Layout fixes. |
| Helpers `HStack` / `VStack` | **diferir** | Ergonomía Chakra. UIX prefiere `<Stack direction="row">`. Reconsiderar si la fricción es real en consumers. |
| `preventGrowOverflow` para hijos con `grow` | **diferir** | Patrón Mantine Group; aplicable también a Stack horizontal. |
## Referencias
- Chakra UI Stack: https://chakra-ui.com/docs/components/stack
- Mantine Stack: https://mantine.dev/core/stack/
- Radix Themes: usa `<Flex direction="column">` sin Stack dedicado.
## Passive justification
Visual-only (`scope: ['eidos']`). Sin estado, sin keyboard, sin ARIA,
sin eventos. Marker pasa a través de Flex/Box.

@ -0,0 +1,68 @@
# Eidos Wrap
Like [Group](../group/README.md) but enforces wrapping. Pensado para
clusters de elementos de ancho variable (pills, badges, tags) donde
la nueva línea es comportamiento explícito, no fallback. Expone
`rowGap` / `columnGap` como first-class para separar espaciado de
ejes en wrap dinámico.
## Superficie
```svelte
<Wrap rowGap={2} columnGap={3}>
<Pill>svelte</Pill>
<Pill>kit</Pill>
<Pill>vite</Pill>
…
</Wrap>
```
## Baseline
Origen: `air/components/layout/wrap`. Adaptación estándar.
Composición: a través de Flex con `wrap="wrap"` fijo. DOM:
`<div data-box data-flex data-wrap>`.
## Comparativa
| Capacidad | UIX | Chakra Wrap | Mantine | Radix Themes |
| --- | --- | --- | --- | --- |
| `wrap` siempre activo | Sí (fijo) | Sí | Vía Group | Vía Flex |
| `rowGap` / `columnGap` first-class | Sí | Sí (`spacingX`/`spacingY`) | Sí | Sí |
| `align` / `justify` | Sí | Sí | Sí | Sí |
| `shouldWrapChildren` (auto-wrap cada hijo en WrapItem) | **No** — gap conocido | Sí | — | — |
| Componente `WrapItem` paralelo | **No** | Sí | — | — |
## Decisiones
- **Sin `WrapItem` companion** — los hijos son Box plain. Si necesitas
control individual de wrap, ponlo en el Box hijo via `flex` /
`basis` props.
- **`shouldWrapChildren` no por defecto** — Chakra lo hace con un
`Children.map` que envuelve cada hijo. En Svelte sería un snippet
pattern más complejo; no añade poder real. Backlog si llega caso.
- **Differencia con Group** — Group por defecto tiene wrap pero la
intención semántica es "row con fallback wrap"; Wrap es "siempre
wrap, optimiza para clusters dinámicos".
## Eventos Sema
0 eventos. Pasivo.
## Gaps
| Gap | Disposición | Detalle |
| --- | --- | --- |
| `shouldWrapChildren` (auto-wrap cada hijo) | **diferir** | Patrón Chakra. En Svelte sería más complejo; valorar si llega caso real. |
| `WrapItem` companion para control fino | **descartar** | Box hijo ya cubre. Reduce superficie pública. |
## Referencias
- Chakra Wrap: https://chakra-ui.com/docs/components/wrap
- Mantine: usa Group sin componente separado.
- Radix Themes: Flex con `wrap="wrap"`.
## Passive justification
Visual-only (`scope: ['eidos']`). Marker `[data-wrap]`. Sin estados,
sin ARIA, sin eventos.
Loading…
Cancel
Save

Powered by TurnKey Linux.