|
|
|
|
# `eidos/components/`
|
|
|
|
|
|
|
|
|
|
Recipes y wrappers visuales por componente. La forma actual de un
|
|
|
|
|
componente es un **subdirectorio** con cuatro archivos; los `.css`
|
|
|
|
|
sueltos del nivel raíz son legacy de la fase "eidos = solo CSS" y se
|
|
|
|
|
migran progresivamente.
|
|
|
|
|
|
|
|
|
|
## Forma actual (toggle es el piloto)
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
toggle/
|
|
|
|
|
toggle.css → recipe CSS (selectores [data-toggle], variants, …)
|
|
|
|
|
toggle.svelte → wrapper sobre $soma/components/toggle
|
|
|
|
|
types.ts → ToggleProps (extiende SomaToggleProps)
|
|
|
|
|
index.ts → re-exports públicos
|
|
|
|
|
README.md → notas del componente (opcional, recomendado para piloto)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### `{name}.svelte` — el wrapper
|
|
|
|
|
|
|
|
|
|
Compone sobre el provider headless del soma. Re-bindable de
|
|
|
|
|
estado (`pressed = $bindable(false)`), emite los data-attrs de tokens
|
|
|
|
|
visuales y opcionalmente añade slots (`icon`, `checkMark`):
|
|
|
|
|
|
|
|
|
|
```svelte
|
|
|
|
|
<script lang="ts">
|
|
|
|
|
import * as Toggle from '$soma/components/toggle';
|
|
|
|
|
import type { ToggleProps } from './types';
|
|
|
|
|
let {
|
|
|
|
|
variant = 'solid',
|
|
|
|
|
size = 'md',
|
|
|
|
|
block = false,
|
|
|
|
|
iconOnly = false,
|
|
|
|
|
icon,
|
|
|
|
|
checkMark = false,
|
|
|
|
|
pressed = $bindable(false),
|
|
|
|
|
children: bodyContent,
|
|
|
|
|
...somaProps
|
|
|
|
|
}: ToggleProps = $props();
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<Toggle.Provider
|
|
|
|
|
{...somaProps}
|
|
|
|
|
bind:pressed
|
|
|
|
|
data-variant={variant}
|
|
|
|
|
data-size={size}
|
|
|
|
|
data-block={block ? '' : undefined}
|
|
|
|
|
data-icon-only={iconOnly ? '' : undefined}
|
|
|
|
|
>
|
|
|
|
|
{#snippet children(snippetProps)}
|
|
|
|
|
{#if icon}{@render icon(snippetProps)}{/if}
|
|
|
|
|
<span class="eidos-toggle-body">{@render bodyContent?.(snippetProps)}</span>
|
|
|
|
|
{#if checkMark === true && snippetProps.pressed}
|
|
|
|
|
<svg class="eidos-toggle-checkmark" …/>
|
|
|
|
|
{/if}
|
|
|
|
|
{/snippet}
|
|
|
|
|
</Toggle.Provider>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Patrones notables:
|
|
|
|
|
|
|
|
|
|
- **`children` se renombra a `bodyContent`** dentro del wrapper porque
|
|
|
|
|
el `{#snippet children}` interno shadowearía el prop y haría
|
|
|
|
|
recursión.
|
|
|
|
|
- **`pressed = $bindable(false)`** se declara explícitamente; sin esto
|
|
|
|
|
un consumer que pase `bind:pressed` choca con un error de Svelte
|
|
|
|
|
("non-bindable property").
|
|
|
|
|
- **`<span class="eidos-toggle-body">`** envuelve el body del usuario
|
|
|
|
|
para que `[data-icon-only] .eidos-toggle-body { sr-only }` lo oculte
|
|
|
|
|
visualmente sin perder accesibilidad.
|
|
|
|
|
|
|
|
|
|
### `types.ts` — extensión de los tipos del soma
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
import type { Snippet } from 'svelte';
|
|
|
|
|
import type { ToggleProps as SomaToggleProps } from '$soma/components/toggle/types';
|
|
|
|
|
import type { Size } from '$uix/eidos/lib/types';
|
|
|
|
|
|
|
|
|
|
export type ToggleVariant = 'solid' | 'outline' | 'ghost';
|
|
|
|
|
export type ToggleSize = Extract<Size, 'sm' | 'md' | 'lg'>;
|
|
|
|
|
|
|
|
|
|
export type ToggleProps = SomaToggleProps & {
|
|
|
|
|
variant?: ToggleVariant;
|
|
|
|
|
size?: ToggleSize;
|
|
|
|
|
block?: boolean;
|
|
|
|
|
iconOnly?: boolean;
|
|
|
|
|
icon?: Snippet<[{ pressed: boolean }]>;
|
|
|
|
|
checkMark?: boolean | Snippet<[{ pressed: boolean }]>;
|
|
|
|
|
};
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Reglas:
|
|
|
|
|
|
|
|
|
|
- **Sin prefijo `Eidos`.** El path `$uix/eidos/components/{x}` ya
|
|
|
|
|
identifica la capa.
|
|
|
|
|
- **Subset el tipo compartido.** `Size` global tiene 8 valores
|
|
|
|
|
(`xxs..xxl + full`); el componente reduce con `Extract` al subset
|
|
|
|
|
que su recipe soporta. Compile error antes que fallback silencioso.
|
|
|
|
|
- **El nombre del prop refleja la API doctrinal.** `intent` y `color`
|
|
|
|
|
pertenecen a soma — no se redeclaran en eidos; se heredan de
|
|
|
|
|
`SomaToggleProps`.
|
|
|
|
|
|
|
|
|
|
### `index.ts` — re-exports
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
export { default } from './toggle.svelte';
|
|
|
|
|
export { default as Provider } from './toggle.svelte';
|
|
|
|
|
|
|
|
|
|
export type {
|
|
|
|
|
ToggleProps,
|
|
|
|
|
ToggleProps as ProviderProps,
|
|
|
|
|
ToggleVariant,
|
|
|
|
|
ToggleSize
|
|
|
|
|
} from './types';
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Doble export (`default` + `Provider`) por la doctrina de API:
|
|
|
|
|
|
|
|
|
|
| Forma | Cuándo |
|
|
|
|
|
|---|---|
|
|
|
|
|
| `import Toggle from '$uix/eidos/components/toggle'` → `<Toggle>` | single-part components, ergonomía Chakra-style |
|
|
|
|
|
| `import * as Toggle from …` → `<Toggle.Provider>` | consumers que prefieren la forma compound (Radix-style) |
|
|
|
|
|
|
|
|
|
|
### `{name}.css` — el recipe
|
|
|
|
|
|
|
|
|
|
Selectores `[data-{component}]`, variantes por `data-color`,
|
|
|
|
|
`data-size`, `data-variant`, etc.
|
|
|
|
|
|
|
|
|
|
Para el subset por componente, el CSS sólo define los tokens
|
|
|
|
|
permitidos por el anexo del libro. Si un componente no admite `loss`,
|
|
|
|
|
no aparece `[data-color='loss']` en su recipe.
|
|
|
|
|
|
|
|
|
|
#### Convención de naming de tokens CSS
|
|
|
|
|
|
|
|
|
|
**Regla:** los tokens CSS llevan el nombre del **componente**, no de la
|
|
|
|
|
**capa**. Sin prefijos de capa — ni `--eidos-`, ni `--air-`, ni
|
|
|
|
|
`--terra-`, ni `--soma-`.
|
|
|
|
|
|
|
|
|
|
| Forma | Uso | Ejemplo |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| `--{component}-…` | tokens públicos (sobreescribibles por el consumer) | `--dialog-content-bg`, `--toggle-radius-md` |
|
|
|
|
|
| `--_{component}-…` | tokens internos del recipe (no parte del API público) | `--_dialog-padding`, `--_toggle-palette-track` |
|
|
|
|
|
|
|
|
|
|
**Por qué bare-prefixed (sin `--eidos-`):**
|
|
|
|
|
|
|
|
|
|
- Los recipes son la skin oficial; el consumer interactúa con tokens
|
|
|
|
|
por componente, no por capa.
|
|
|
|
|
- Si un consumer construye un recipe alternativo a partir de soma+morfo
|
|
|
|
|
(doctrina §13), reutiliza los mismos tokens — no debe importar de qué
|
|
|
|
|
capa "salieron".
|
|
|
|
|
- Migrar de air → eidos no debe romper override de consumer. Mantener
|
|
|
|
|
`--{component}-…` hace la migración invisible (el rename `air-` → ``
|
|
|
|
|
es interno).
|
|
|
|
|
- El selector `[data-{component}]` ya identifica al componente; el
|
|
|
|
|
token sólo necesita coincidir con ese mismo nombre.
|
|
|
|
|
|
|
|
|
|
**Histórico:** la baseline `air/` usaba `--air-{component}-…`. Al
|
|
|
|
|
migrar al wrapper eidos se hace strip del prefijo `air-` (no se
|
|
|
|
|
reemplaza por `eidos-`).
|
|
|
|
|
|
|
|
|
|
## Forma legacy (CSS-only)
|
|
|
|
|
|
|
|
|
|
Los archivos sueltos `accordion.css`, `dialog.css`, `drawer.css`, etc.
|
|
|
|
|
son la fase anterior cuando eidos sólo emitía CSS. Funcionan, pero se
|
|
|
|
|
migran a la forma actual cuando el componente entra en revisión.
|
|
|
|
|
|
|
|
|
|
## Pendientes de migrar a wrapper
|
|
|
|
|
|
|
|
|
|
| Componente | CSS legacy | Wrapper |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| toggle | — | ✅ piloto |
|
|
|
|
|
| switch | — | ✅ |
|
|
|
|
|
| collapsible | — | ✅ (multi-part: flat + compound) |
|
|
|
|
|
| dialog | `dialog.css` | ⏳ |
|
|
|
|
|
| drawer | `drawer.css` | ⏳ |
|
|
|
|
|
| popover | `popover.css` | ⏳ |
|
|
|
|
|
| toast | `toast.css` | ⏳ |
|
uix: drawer/popover/toast/accordion eidos wrappers + sema packs + /uix docs scaffold
- eidos: migrate drawer / popover / toast / accordion to wrapper subdirectory
pattern (provider + parts + tokens + recipe per component); avatar wrapper
added; toggle/switch/collapsible recipe polish.
- sema: per-component packs (accordion, drawer, popover, toast); engine /
resolver / event / sema-map updates; visual channel hold refinements.
- morfo: drawer event surface (variant, dragToDismiss, isDragging, minSize/
maxSize, onDragStart); popover/toast/accordion event refinements; schema +
types updates.
- soma: drawer provider rewrite (variant, dragToDismiss, isDragging binding,
drag callbacks); toast provider/toaster restructure with toast-main +
toast-status parts; popover content/arrow polish; gesture/floating layer
updates; manipulation layer scaffold; avatar removed (eidos owns it now).
- web/routes: legacy demos updated for new APIs; new /uix docs scaffold
(web/routes/uix/) with Radix-style shell, theme/lang/format/semantic prefs,
and standardized component template (Drawer page first — 6 tabs, live
controls, drag-hint arrows, scroll-safe body wrapper).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
| avatar | — | ✅ eidos-native |
|
|
|
|
|
| accordion | `accordion.css` | ⏳ |
|
|
|
|
|
| tabs | `tabs.css` | ⏳ |
|
|
|
|
|
| checkbox | `checkbox.css` | ⏳ |
|
|
|
|
|
| tooltip | `tooltip.css` | ⏳ |
|