4.9 KiB
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):
<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:
childrense renombra abodyContentdentro 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 pasebind:pressedchoca 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
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.
Sizeglobal tiene 8 valores (xxs..xxl + full); el componente reduce conExtractal subset que su recipe soporta. Compile error antes que fallback silencioso. - El nombre del prop refleja la API doctrinal.
intentycolorpertenecen a soma — no se redeclaran en eidos; se heredan deSomaToggleProps.
index.ts — re-exports
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. El recipe NO usa el prefijo
--eidos-; usa --{component}-… para tokens públicos y
--_{component}-… para los internos.
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.
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 | switch.css |
⏳ |
| collapsible | collapsible.css |
⏳ |
| dialog | dialog.css |
⏳ |
| drawer | drawer.css |
⏳ |
| popover | popover.css |
⏳ |
| toast | toast.css |
⏳ |
| avatar | (vía contracts) | ⏳ |
| accordion | accordion.css |
⏳ |
| tabs | tabs.css |
⏳ |
| checkbox | checkbox.css |
⏳ |
| tooltip | tooltip.css |
⏳ |