You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md

711 lines
21 KiB

sema/morfo/eidos: align with GUIA_IMPLEMENTACION_SEMAUIX (canonical guide) The new doctrinal guide at src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md supersedes src/docs/sema-implementation-guide.md and locks the canonical vocabulary, event shape and color tokens. This commit aligns the codebase to that canon in three concrete moves. Phase 1 — sema/verbs.ts vocabulary: - Restructured from flat array to family-keyed Record per the guide. - Moved select / toggle / acknowledge → commit (these fix state, not contact). Removed edit from handle (it's shift.enter-mode now). - Added new verbs per the canon: contact (tap, focus, trigger, release), commit (complete, restore, expire, set, remove, reorder), signal (remind), handle (rotate, scroll, reorder), shift (route, step, return, context), sustain (start, loading, waiting, syncing, processing, streaming, pending, retrying, end). - validateEventName now recognises both naming shapes: {verb}-{variant} (head=verb) and {family}-{verb} (head=family). - New helper familyForVerb. Tests rewritten — 16/16 green. Phase 2 — morfo event shape: - target moved from event-level into event.semantic. Adds optional semantic.verb (advisory, validated against SEMA_VERBS[family]) and optional semantic.sequence ('pre' | 'coincident' | 'post'). - compile.ts and schema.ts updated. The 22 events across toggle, toast, popover, drawer, dialog refactored to the new shape with explicit verb + sequence. - Polymorphic capability (allowedFamilies + defaultSemantic) and a11ySemantic deferred — no current consumer needs them; will land when the first concrete usage appears. Phase 5 — color tokens (doctrinal 8): - themes/base/light.css and dark.css rewritten to expose primary, secondary, neutral, affirm, fulfill, risk, threat, loss. Renames success→fulfill, warning→risk, danger→threat (same hex). New primitives for secondary (slate-blue), affirm (teal-mint, low activation), loss (deep violet-grave, posterior). info palette deleted entirely — per guide, "info no es intent, es signal.announce + neutral". - _static.css legacy compatibility aliases (--color-bg, --color-success, --color-error, --color-accent, ...) deleted. Clean cut, no transition. Consumers reference doctrinal palettes directly. - 29 consumers (token files + recipes) migrated: - All --*-color-info-* declarations dropped. - Component palettes extended with secondary / affirm / loss. - switch + checkbox recipes updated to use [data-color='affirm'| 'risk'|'threat'|'secondary'] (was 'success'|'warning'|'danger'| 'info'). - toast tokens + recipe renamed to affirm/fulfill/risk/threat/loss (was success/error/warning/info). - meter, progress, mark, badge, button tokens renamed. - Contracts (contracts/contract.css + contracts/components/*) updated. - focus-ring-color-error in themes now points to --color-risk-border (validation errors are signal.warn + risk per doctrina, not threat). Phase 4 (partial): - src/docs/sema-implementation-guide.md deleted (superseded by the canonical guide). Tests: 217/217 green across uix. npm run check holds at the 39-error baseline (all pre-existing in unrelated test files; none introduced). Pending in follow-up commits: - Update active_architecture.md, sema/README.md, morfo/README.md, CLAUDE.md to reflect the canon. - Switch component migration to the eidos wrapper pattern. - Persistence field (untilAction / untilFix / stateBound) and holds-by-intent — defer until the first signal.warn / signal.alert consumer appears. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
# Guía de implementación — Semántica perceptiva en UIX
## De la teoría del libro a la arquitectura del framework
Este documento traduce las decisiones del libro *Semántica perceptiva de la interfaz* a la arquitectura UIX (Morfo/Soma/Sema/Eidos). No repite la teoría — la convierte en contratos, vocabularios, reglas de resolución y convenciones técnicas.
Documento autoritativo para toda migración, wrapper nuevo o extensión de componente.
---
## 1. Vocabulario canónico corregido
### 1.1. Familias
7 familias. Sin excepciones.
```ts
export const SEMA_FAMILIES = [
'contact', // ¿el sistema ha sentido mi acción?
'commit', // ¿algo quedó fijado o tuvo consecuencia?
'signal', // ¿algo reclama mi atención?
'handle', // ¿estoy manipulando directamente un objeto?
'emerge', // ¿algo entró o salió del campo perceptivo?
'shift', // ¿cambió el marco operativo?
'sustain' // ¿esto sigue ocurriendo?
] as const;
```
**Cambios respecto a la implementación actual:**
| Antes | Ahora | Razón |
|---|---|---|
| `alert` como familia | `signal` con verbo `alert` | alert es intensidad dentro de signal, no familia |
| sin `shift` | `shift` añadido | emerge ≠ shift — dropdown ≠ modal |
| sin `loss` | `loss` como intent | threat ≠ loss — amenaza ≠ pérdida consumada |
### 1.2. Intents
6 intents. Regiones evaluativas del espacio valencia/activación.
```ts
export const SEMA_INTENTS = [
'neutral', // sin carga evaluativa fuerte
'affirm', // confirmación positiva, baja activación
'fulfill', // resolución positiva, mayor activación
'risk', // problema corregible, negativo moderado
'threat', // amenaza activa, alta activación negativa
'loss' // pérdida consumada, consecuencia ya ocurrida
] as const;
```
### 1.3. Verbs por familia
```ts
export const SEMA_VERBS = {
contact: [
'press', 'tap', 'activate', 'focus', 'trigger', 'release'
],
commit: [
'select', 'toggle', 'save', 'submit', 'confirm', 'cancel',
'complete', 'fail', 'delete', 'restore', 'reset', 'discard',
'expire', 'acknowledge', 'set', 'remove', 'reorder'
],
signal: [
'announce', 'notify', 'warn', 'alert', 'emphasize', 'remind'
],
handle: [
'pick', 'carry', 'drop', 'drag', 'resize', 'reorder', 'rotate', 'scroll'
],
emerge: [
'present', 'dismiss', 'open', 'close', 'expand', 'collapse',
'reveal', 'hide'
],
shift: [
'enter-mode', 'exit-mode', 'navigate', 'route', 'step',
'return', 'context'
],
sustain: [
'start', 'progress', 'loading', 'waiting', 'syncing',
'processing', 'streaming', 'pending', 'retrying', 'end'
]
} as const;
```
**Cambios de verbs:**
| Antes | Ahora | Razón |
|---|---|---|
| `contact.select` | `commit.select` | seleccionar fija estado = commit |
| `contact.toggle` | `commit.toggle` | alternar fija estado = commit |
| `handle.acknowledge` | `commit.acknowledge` | reconocer cierra algo = commit |
| `handle.edit` | `shift.enter-mode` | editar cambia régimen = shift |
---
## 2. Sistema de 8 tokens de color
### 2.1. Los 8 valores
Dos ejes ortogonales:
**Jerarquía** (sin carga evaluativa):
- `primary` — acción principal
- `secondary` — acción secundaria
**Intent** (carga evaluativa):
- `neutral` — sin juicio fuerte
- `affirm` — confirmación suave
- `fulfill` — objetivo cumplido
- `risk` — problema corregible
- `threat` — amenaza activa
- `loss` — pérdida consumada
### 2.2. Regla de resolución intent ↔ color
```ts
visualColor =
intent !== 'neutral' → intent // la carga evaluativa gana
intent === 'neutral' → color ?? 'neutral' // jerarquía si se pasó, neutral si no
```
Un componente recibe dos props ortogonales con prioridad clara:
- `intent` (semántico) — siempre presente, default `neutral`. Decide firma sema y, si es evaluativo, también el color visual.
- `color` (jerárquico) — opcional, solo `primary | secondary`. Override visual cuando NO hay carga evaluativa. Si pasas `color='primary'` con `intent='threat'`, el intent gana.
```svelte
<Toggle /> <!-- data-color='neutral' -->
<Toggle color="primary" /> <!-- data-color='primary' -->
<Toggle intent="affirm" /> <!-- data-color='affirm' -->
<Toggle intent="threat" color="primary" /> <!-- data-color='threat' (intent gana) -->
```
### 2.3. Mapeo desde convención heredada
| Convención CSS | Token UIX | Nota |
|---|---|---|
| primary | `primary` | jerarquía, no intent |
| secondary | `secondary` | jerarquía, no intent |
| success | `affirm` o `fulfill` | affirm = confirmación suave, fulfill = objetivo cumplido |
| warning | `risk` | problema corregible |
| danger | `threat` o `loss` | threat = antes, loss = después |
| info | `signal.announce + neutral` | info no es intent, es función de atención |
### 2.4. Tokens CSS por theme
Cada theme define los 8 tokens:
```css
:root {
--color-primary-element: ...;
--color-secondary-element: ...;
--color-neutral-element: ...;
--color-affirm-element: ...;
--color-fulfill-element: ...;
--color-risk-element: ...;
--color-threat-element: ...;
--color-loss-element: ...;
}
```
El theme decide hue/sat/lightness por marca. El componente solo declara qué token leer.
### 2.5. CSS en recipes
```css
[data-color='primary'] { ... }
[data-color='secondary'] { ... }
[data-color='neutral'] { ... }
[data-color='affirm'] { ... }
[data-color='fulfill'] { ... }
[data-color='risk'] { ... }
[data-color='threat'] { ... }
[data-color='loss'] { ... }
```
Los selectores legacy (`info`, `success`, `warning`, `danger`) se eliminan.
---
## 3. Subset por componente
No todo componente acepta los 8 valores. Cada componente declara su subset permitido.
### 3.1. Tabla de subsets
| Componente | color | intent permitidos |
|---|---|---|
| Button (acción) | primary, secondary | neutral, affirm, fulfill, risk, threat, loss |
| Button (nav) | primary, secondary | neutral |
| Toggle / Switch | primary, secondary | neutral, affirm, risk, threat |
| Checkbox / Radio | primary, secondary | neutral, affirm |
| Input | — | neutral, risk |
| Select / Combobox | primary, secondary | neutral, affirm |
| Slider | primary | neutral, affirm |
| Alert inline | — | risk |
| Alert crítica | — | threat |
| Toast / Snackbar | — | neutral, affirm, risk |
| Toast con undo | — | loss |
| Banner | — | neutral, risk |
| Badge | — | neutral, risk |
| Modal | — | neutral, threat, risk |
| Spinner / Skeleton | — | no acepta intent |
| Progress bar | — | no acepta intent |
### 3.2. Regla de subset
Si un componente no admite `loss`, no aparece `[data-color='loss']` en su recipe CSS. El intent se valida en TypeScript:
```ts
type ToggleIntent = Extract<SemanticIntent, 'neutral' | 'affirm' | 'risk' | 'threat'>;
```
### 3.3. Regla: el intent no nace del componente
El intent no nace del componente. Pero el componente debe poder recibirlo para expresarlo. La diferencia con la convención heredada es el orden:
- **Convención:** diseñador pinta botón de rojo → botón "es" danger → intent nace del color
- **UIX:** evento es commit.delete + loss → componente recibe loss → aplica firma perceptiva
### 3.4. Regla: la estética no contradice la semántica
La estética tiene libertad dentro del rango que la semántica permite. Un affirm puede ser verde esmeralda o azul suave — eso es estética. Pero un affirm no puede ser rojo con icono de alerta — eso es contradicción semántica.
---
## 4. Familias y componentes: quién expresa qué
### 4.1. emerge vs shift
| Componente | Familia | Razón |
|---|---|---|
| Dropdown | emerge.open | aparición local, no cambia marco |
| Popover | emerge.open | aparición anclada |
| Tooltip | emerge.present | información auxiliar |
| Accordion | emerge.expand | contenido contenido |
| Modal / Dialog | shift.enter-mode | cambia marco, captura foco, subordina fondo |
| Command Palette | shift.enter-mode | cambia régimen operativo |
| Edit mode | shift.enter-mode | cambia qué puede hacerse |
| Wizard step | shift.step | avanza en proceso |
| Route change | shift.navigate | nuevo contexto |
| Drawer (pesado) | shift.enter-mode | si bloquea fondo y captura foco |
| Drawer (ligero) | emerge.open | si no bloquea ni captura |
### 4.2. contact vs commit
```
contact = el sistema recibió mi gesto
commit = algo quedó fijado como consecuencia
```
Si la operación es instantánea (toggle, checkbox, select), el usuario percibe un solo evento: commit. El contact está implícito en el gesto. Se documenta como un solo evento semántico.
### 4.3. signal vs emerge
```
emerge = algo entra o sale del campo perceptivo
signal = algo reclama atención
```
Un toast que aparece es emerge.present. El mensaje dentro puede ser signal.notify + neutral o commit.save + affirm. La aparición no es la señal.
---
## 5. Morfo: declaración semántica del componente
### 5.1. Estructura del evento en Morfo
```ts
events: [
{
name: 'commit-toggle',
semantic: {
family: 'commit',
verb: 'toggle',
intent: undefined, // lo decide el provider según contexto
target: v.partRef('root'),
sequence: 'post' // la señal ocurre después del cambio de estado
}
}
]
```
### 5.2. Campo `sequence` (timing del evento)
```ts
sequence: 'pre' | 'coincident' | 'post'
```
| Valor | Cuándo usar | Ejemplo |
|---|---|---|
| `pre` | señal perceptiva antes del cambio estructural | emerge.dismiss (animar salida antes de cerrar) |
| `coincident` | señal durante el proceso | sustain.progress |
| `post` | señal después del resultado real | commit.save + affirm (confirmar después de guardar) |
No todo evento debe ser `pre` como el Toast dismiss. Contact debe ser `post` (inmediato, sin bloquear estado). Commit.save debe ser `post` (no celebrar antes de que exista resultado).
### 5.3. Capacidad semántica vs evento fijo
Morfo puede declarar capacidad semántica cuando el componente soporta varios eventos según contexto:
```ts
events: [
{
name: 'close',
semantic: {
allowedFamilies: ['shift', 'commit', 'emerge'],
defaultSemantic: { family: 'shift', verb: 'exit-mode' }
}
}
]
```
El provider concreta:
```ts
// Dialog con cambios sin guardar
semantic: { family: 'commit', verb: 'discard', intent: 'loss' }
// Dialog informativo
semantic: { family: 'shift', verb: 'exit-mode' }
```
---
## 6. Sema: holds y persistencia
### 6.1. Separar hold expresivo de persistencia semántica
```ts
hold: number // duración expresiva mínima del evento (ms)
persistence: 'transient' | 'untilAction' | 'untilFix' | 'stateBound'
```
| Tipo | Significado | Ejemplo |
|---|---|---|
| `transient` | desaparece tras hold | contact.press, commit.save + affirm |
| `untilAction` | persiste hasta que el usuario actúe | signal.alert + threat |
| `untilFix` | persiste hasta corrección | signal.warn + risk |
| `stateBound` | ligado al estado del proceso | sustain.progress |
### 6.2. Holds por familia e intent
```ts
const SEMA_HOLDS = {
contact: 120,
emerge: 180,
shift: 240,
commit: {
neutral: 200,
affirm: 180,
fulfill: 280,
risk: 240,
threat: 240,
loss: 240
},
signal: {
neutral: 240,
risk: 'untilFix',
threat: 'untilAction',
loss: 400
},
handle: {
pick: 120,
drop: 180
},
sustain: 'stateBound'
};
```
### 6.3. Sustain no tiene hold fijo
Sustain no es un evento transitorio. Es un estado que dura mientras dura el proceso. No se le asigna hold de 600ms ni de ningún valor fijo. Se gestiona como `stateBound`: el canal visual mantiene los atributos mientras el provider indique que el proceso sigue activo.
---
## 7. Canal visual: atributos DOM
### 7.1. Señales transitorias (Sema escribe, Eidos lee)
```html
data-event="commit-toggle"
data-event-id="sig-42"
data-event-phase="active"
data-event-family="commit"
data-event-intent="affirm"
```
Viven durante el hold. Se limpian antes de resolver la Promise.
### 7.2. Estado persistente (Soma/Effects escriben, Eidos lee)
```html
data-state="open"
data-color="primary"
data-intent="risk"
data-disabled
data-pressed
```
Viven mientras el estado sea verdadero. No son señales transitorias.
### 7.3. Regla: no mezclar transitorio y persistente
El canal visual nunca toca atributos de estado (`data-state`, `data-intent`, `data-disabled`). El estado lo gestiona el runtime. Razón: estado es persistente y señal es transitoria. Pisar el mismo nombre fuerza al canal a borrar estado al limpiar.
---
## 8. Composiciones simultáneas
### 8.1. V1: un solo evento activo por target
Mantener un solo `data-event` activo. Suficiente para:
- dismiss, open, press, complete, toggle, select
### 8.2. V2 (futuro): slots semánticos
Para composiciones simultáneas como:
```
shift.enter-mode + signal.alert + threat
sustain.progress + signal.warn + risk
handle.carry + signal.warn + threat
```
Añadir slots:
```html
data-event-frame="shift.enter-mode"
data-event-signal="signal.alert"
data-event-intent="threat"
```
Así el modal (shift) no absorbe el intent de su contenido (signal).
---
## 9. Accesibilidad semántica en Morfo
### 9.1. Contrato a11y por evento
```ts
a11ySemantic: {
requiresPersistentTrace?: boolean;
requiresLiveRegion?: boolean;
requiresFocusMove?: boolean;
keyboardEquivalent?: boolean;
reducedMotionFallback?: 'state' | 'text' | 'focus' | 'none';
}
```
### 9.2. Ejemplos
```ts
// signal.warn + risk
a11ySemantic: {
requiresPersistentTrace: true,
reducedMotionFallback: 'text'
}
// signal.alert + threat
a11ySemantic: {
requiresPersistentTrace: true,
requiresLiveRegion: true,
requiresFocusMove: true
}
// handle (drag)
a11ySemantic: {
keyboardEquivalent: true
}
// commit.delete + loss
a11ySemantic: {
requiresPersistentTrace: true
}
```
---
## 10. Sound y Vibra
### 10.1. Principios
- Sound y Vibra reciben el signal directamente del engine, no leen DOM.
- Son fire-and-forget: no bloquean al caller.
- Son opcionales, proporcionales y nunca únicos.
- La semántica debe poder vivir sin ellos.
### 10.2. Configuración por familia/intent
```ts
sound: {
enabled: false, // opt-in global
allowFamilies: ['signal', 'commit'], // solo estas familias pueden sonar
allowIntents: ['fulfill', 'threat', 'loss'], // solo estos intents
muteFrequentEvents: true // silenciar contact frecuente
}
```
### 10.3. Eager-init
AudioContext se crea/resume en el primer user gesture (click/touch/keydown en document, capture phase). Convención aplicable a cualquier canal con restricción de "primera vez en gesture": audio, vibration, fullscreen, clipboard write.
---
## 11. Firma perceptiva por evento
Una firma perceptiva es el conjunto de decisiones de canal coordinadas alrededor de un evento.
sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
**Las dimensiones no son un conjunto cerrado.** El framework ships con 5
canales canónicos (`motion`, `sound`, `color`, `presence`, `haptic`) y el
registry `SemaChannelSignatures` se extiende vía TypeScript declaration
merging cuando una app necesita `a11y`, `voice`, etc. Una family puede
no rellenar `presence`; otra puede aportar `haptic`. Una rule de
cascade puede silenciar `motion` para reducir estimulación. Los ejemplos
abajo enumeran las dimensiones relevantes para CADA evento — no una
lista canónica fija.
sema/morfo/eidos: align with GUIA_IMPLEMENTACION_SEMAUIX (canonical guide) The new doctrinal guide at src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md supersedes src/docs/sema-implementation-guide.md and locks the canonical vocabulary, event shape and color tokens. This commit aligns the codebase to that canon in three concrete moves. Phase 1 — sema/verbs.ts vocabulary: - Restructured from flat array to family-keyed Record per the guide. - Moved select / toggle / acknowledge → commit (these fix state, not contact). Removed edit from handle (it's shift.enter-mode now). - Added new verbs per the canon: contact (tap, focus, trigger, release), commit (complete, restore, expire, set, remove, reorder), signal (remind), handle (rotate, scroll, reorder), shift (route, step, return, context), sustain (start, loading, waiting, syncing, processing, streaming, pending, retrying, end). - validateEventName now recognises both naming shapes: {verb}-{variant} (head=verb) and {family}-{verb} (head=family). - New helper familyForVerb. Tests rewritten — 16/16 green. Phase 2 — morfo event shape: - target moved from event-level into event.semantic. Adds optional semantic.verb (advisory, validated against SEMA_VERBS[family]) and optional semantic.sequence ('pre' | 'coincident' | 'post'). - compile.ts and schema.ts updated. The 22 events across toggle, toast, popover, drawer, dialog refactored to the new shape with explicit verb + sequence. - Polymorphic capability (allowedFamilies + defaultSemantic) and a11ySemantic deferred — no current consumer needs them; will land when the first concrete usage appears. Phase 5 — color tokens (doctrinal 8): - themes/base/light.css and dark.css rewritten to expose primary, secondary, neutral, affirm, fulfill, risk, threat, loss. Renames success→fulfill, warning→risk, danger→threat (same hex). New primitives for secondary (slate-blue), affirm (teal-mint, low activation), loss (deep violet-grave, posterior). info palette deleted entirely — per guide, "info no es intent, es signal.announce + neutral". - _static.css legacy compatibility aliases (--color-bg, --color-success, --color-error, --color-accent, ...) deleted. Clean cut, no transition. Consumers reference doctrinal palettes directly. - 29 consumers (token files + recipes) migrated: - All --*-color-info-* declarations dropped. - Component palettes extended with secondary / affirm / loss. - switch + checkbox recipes updated to use [data-color='affirm'| 'risk'|'threat'|'secondary'] (was 'success'|'warning'|'danger'| 'info'). - toast tokens + recipe renamed to affirm/fulfill/risk/threat/loss (was success/error/warning/info). - meter, progress, mark, badge, button tokens renamed. - Contracts (contracts/contract.css + contracts/components/*) updated. - focus-ring-color-error in themes now points to --color-risk-border (validation errors are signal.warn + risk per doctrina, not threat). Phase 4 (partial): - src/docs/sema-implementation-guide.md deleted (superseded by the canonical guide). Tests: 217/217 green across uix. npm run check holds at the 39-error baseline (all pre-existing in unrelated test files; none introduced). Pending in follow-up commits: - Update active_architecture.md, sema/README.md, morfo/README.md, CLAUDE.md to reflect the canon. - Switch component migration to the eidos wrapper pattern. - Persistence field (untilAction / untilFix / stateBound) and holds-by-intent — defer until the first signal.warn / signal.alert consumer appears. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
### 11.1. Ejemplo: commit.save + affirm
```
tiempo: breve
motion: asentamiento mínimo
forma: marca persistente
color: affirm (positivo discreto)
sonido: no por defecto
háptica: no por defecto
accesibilidad: texto o estado visible
```
### 11.2. Ejemplo: signal.alert + threat
```
presencia: dominante
forma: bloque crítico
color: threat (alta saliencia)
texto: acción clara
sonido: opcional, urgente
motion: entrada saliente
persistencia: hasta acción
accesibilidad: foco + live region + persistente
```
### 11.3. Ejemplo: commit.delete + loss
```
presencia: retirada + huella
forma: undo si existe
color: loss (grave/desaturado)
sonido: seco/grave opcional
motion: retirada/descenso
persistencia: huella
accesibilidad: anuncio + undo persistente + foco no perdido
no usar: alarma sostenida de threat
```
---
## 12. Arquetipos y familias frecuentes
Relación orientativa entre archetipos de Morfo y familias:
| Archetype | Familias frecuentes |
|---|---|
| trigger | contact, emerge, shift, commit |
| content | emerge, shift, signal |
| item | commit, handle, signal |
| overlay | shift |
| indicator | sustain, commit |
| thumb | handle |
| track | handle, sustain |
No como regla rígida, sino como documentación que ayuda a decidir qué eventos puede expresar un componente.
---
## 13. Doctrina del API: soma compound, eidos option C
sema/morfo/eidos: align with GUIA_IMPLEMENTACION_SEMAUIX (canonical guide) The new doctrinal guide at src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md supersedes src/docs/sema-implementation-guide.md and locks the canonical vocabulary, event shape and color tokens. This commit aligns the codebase to that canon in three concrete moves. Phase 1 — sema/verbs.ts vocabulary: - Restructured from flat array to family-keyed Record per the guide. - Moved select / toggle / acknowledge → commit (these fix state, not contact). Removed edit from handle (it's shift.enter-mode now). - Added new verbs per the canon: contact (tap, focus, trigger, release), commit (complete, restore, expire, set, remove, reorder), signal (remind), handle (rotate, scroll, reorder), shift (route, step, return, context), sustain (start, loading, waiting, syncing, processing, streaming, pending, retrying, end). - validateEventName now recognises both naming shapes: {verb}-{variant} (head=verb) and {family}-{verb} (head=family). - New helper familyForVerb. Tests rewritten — 16/16 green. Phase 2 — morfo event shape: - target moved from event-level into event.semantic. Adds optional semantic.verb (advisory, validated against SEMA_VERBS[family]) and optional semantic.sequence ('pre' | 'coincident' | 'post'). - compile.ts and schema.ts updated. The 22 events across toggle, toast, popover, drawer, dialog refactored to the new shape with explicit verb + sequence. - Polymorphic capability (allowedFamilies + defaultSemantic) and a11ySemantic deferred — no current consumer needs them; will land when the first concrete usage appears. Phase 5 — color tokens (doctrinal 8): - themes/base/light.css and dark.css rewritten to expose primary, secondary, neutral, affirm, fulfill, risk, threat, loss. Renames success→fulfill, warning→risk, danger→threat (same hex). New primitives for secondary (slate-blue), affirm (teal-mint, low activation), loss (deep violet-grave, posterior). info palette deleted entirely — per guide, "info no es intent, es signal.announce + neutral". - _static.css legacy compatibility aliases (--color-bg, --color-success, --color-error, --color-accent, ...) deleted. Clean cut, no transition. Consumers reference doctrinal palettes directly. - 29 consumers (token files + recipes) migrated: - All --*-color-info-* declarations dropped. - Component palettes extended with secondary / affirm / loss. - switch + checkbox recipes updated to use [data-color='affirm'| 'risk'|'threat'|'secondary'] (was 'success'|'warning'|'danger'| 'info'). - toast tokens + recipe renamed to affirm/fulfill/risk/threat/loss (was success/error/warning/info). - meter, progress, mark, badge, button tokens renamed. - Contracts (contracts/contract.css + contracts/components/*) updated. - focus-ring-color-error in themes now points to --color-risk-border (validation errors are signal.warn + risk per doctrina, not threat). Phase 4 (partial): - src/docs/sema-implementation-guide.md deleted (superseded by the canonical guide). Tests: 217/217 green across uix. npm run check holds at the 39-error baseline (all pre-existing in unrelated test files; none introduced). Pending in follow-up commits: - Update active_architecture.md, sema/README.md, morfo/README.md, CLAUDE.md to reflect the canon. - Switch component migration to the eidos wrapper pattern. - Persistence field (untilAction / untilFix / stateBound) and holds-by-intent — defer until the first signal.warn / signal.alert consumer appears. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
> Actualizacion 2026-05-14: la forma flat con snippet slots queda retirada.
> Eidos usa la option C disciplinada: root visual directo con hijos atados como
> propiedades explicitas. La referencia operativa vive en
> `src/uix/eidos/components/README.md`.
### 13.1. Las dos capas exponen responsabilidades distintas
collapsible: flat <Collapsible> ergonomic default + compound parts Per the doctrine update in GUIA §13: eidos for multi-part components exposes BOTH a flat default that auto-composes Provider/Trigger/Content AND the compound parts for advanced cases. Soma + morfo remain the universal composable foundation underneath. Why: with the previous "compound only" rule for multi-part, eidos collapsible was a pure pass-through that added nothing operational — the consumer wrote the same import + same shape as soma. The flat default makes eidos earn its layer by collapsing the 90% case to a single call: // 90% case — flat ergonomic <Collapsible bind:open> {#snippet trigger()}Show details{/snippet} <p>Body content.</p> </Collapsible> // Advanced — compound (parts in different subtrees, multi-trigger, // conditional content) <header><Collapsible.Provider bind:open> <Collapsible.Trigger>Show</Collapsible.Trigger> </Collapsible.Provider></header> <aside> <Collapsible.Content>...</Collapsible.Content> </aside> The architectural virtue: if the flat doesn't fit, a developer drops to soma + morfo and composes freely. No vendor lock-in in the visual layer; eidos is the design system convention, soma is the universal primitive. Files: - src/uix/eidos/components/collapsible/collapsible.svelte (NEW): flat default that auto-composes Provider + Trigger + Content via a `trigger` snippet for the toggle label and `children` for the body. - src/uix/eidos/components/collapsible/types.ts: adds `CollapsibleFlatProps = SomaCollapsibleProps & { trigger?: Snippet }`. - src/uix/eidos/components/collapsible/index.ts: exports `default` (flat) plus named `Provider`/`Trigger`/`Content` (compound). - src/uix/eidos/components/collapsible/{trigger,content,provider}.svelte: fixed children destructuring so snippets propagate cleanly to soma (was previously spreading $props() blindly which can lose snippet bindings in Svelte 5). - src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md: NEW §13 "Doctrina del API: soma compound, eidos opinionado" formalises the two-shape rule and the architectural virtue (soma+morfo as universal foundation). Renumbered §13/§14 → §14/§15. - web/routes/collapsible/+page.svelte: live preview now uses the flat form; eidos snippet shows the flat shape; soma snippet keeps the compound shape; Notes tab updated. - src/uix/eidos/components/collapsible/README.md: rewrote API section with both shapes + the "if neither fits, use soma+morfo" escape. Tests 218/218 green. npm run check baseline 39. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
```
soma + morfo → composable universal — TODO caso (avanzado, raro, custom)
eidos → visual opinionado del design system sobre la misma anatomia
collapsible: flat <Collapsible> ergonomic default + compound parts Per the doctrine update in GUIA §13: eidos for multi-part components exposes BOTH a flat default that auto-composes Provider/Trigger/Content AND the compound parts for advanced cases. Soma + morfo remain the universal composable foundation underneath. Why: with the previous "compound only" rule for multi-part, eidos collapsible was a pure pass-through that added nothing operational — the consumer wrote the same import + same shape as soma. The flat default makes eidos earn its layer by collapsing the 90% case to a single call: // 90% case — flat ergonomic <Collapsible bind:open> {#snippet trigger()}Show details{/snippet} <p>Body content.</p> </Collapsible> // Advanced — compound (parts in different subtrees, multi-trigger, // conditional content) <header><Collapsible.Provider bind:open> <Collapsible.Trigger>Show</Collapsible.Trigger> </Collapsible.Provider></header> <aside> <Collapsible.Content>...</Collapsible.Content> </aside> The architectural virtue: if the flat doesn't fit, a developer drops to soma + morfo and composes freely. No vendor lock-in in the visual layer; eidos is the design system convention, soma is the universal primitive. Files: - src/uix/eidos/components/collapsible/collapsible.svelte (NEW): flat default that auto-composes Provider + Trigger + Content via a `trigger` snippet for the toggle label and `children` for the body. - src/uix/eidos/components/collapsible/types.ts: adds `CollapsibleFlatProps = SomaCollapsibleProps & { trigger?: Snippet }`. - src/uix/eidos/components/collapsible/index.ts: exports `default` (flat) plus named `Provider`/`Trigger`/`Content` (compound). - src/uix/eidos/components/collapsible/{trigger,content,provider}.svelte: fixed children destructuring so snippets propagate cleanly to soma (was previously spreading $props() blindly which can lose snippet bindings in Svelte 5). - src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md: NEW §13 "Doctrina del API: soma compound, eidos opinionado" formalises the two-shape rule and the architectural virtue (soma+morfo as universal foundation). Renumbered §13/§14 → §14/§15. - web/routes/collapsible/+page.svelte: live preview now uses the flat form; eidos snippet shows the flat shape; soma snippet keeps the compound shape; Notes tab updated. - src/uix/eidos/components/collapsible/README.md: rewrote API section with both shapes + the "if neither fits, use soma+morfo" escape. Tests 218/218 green. npm run check baseline 39. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
```
**Soma siempre es compound** (`Component.Provider`, `Component.Trigger`,
`Component.Content`, …) por simetría: el desarrollador aprende un
patrón único, todas las partes son visibles, el contrato cross-part
(IDs, ARIA refs) queda explícito.
**Eidos no inventa una API flat paralela.** La capa visual conserva la
anatomia declarada por Morfo y materializada por Soma, pero expone un root
visual directo:
collapsible: flat <Collapsible> ergonomic default + compound parts Per the doctrine update in GUIA §13: eidos for multi-part components exposes BOTH a flat default that auto-composes Provider/Trigger/Content AND the compound parts for advanced cases. Soma + morfo remain the universal composable foundation underneath. Why: with the previous "compound only" rule for multi-part, eidos collapsible was a pure pass-through that added nothing operational — the consumer wrote the same import + same shape as soma. The flat default makes eidos earn its layer by collapsing the 90% case to a single call: // 90% case — flat ergonomic <Collapsible bind:open> {#snippet trigger()}Show details{/snippet} <p>Body content.</p> </Collapsible> // Advanced — compound (parts in different subtrees, multi-trigger, // conditional content) <header><Collapsible.Provider bind:open> <Collapsible.Trigger>Show</Collapsible.Trigger> </Collapsible.Provider></header> <aside> <Collapsible.Content>...</Collapsible.Content> </aside> The architectural virtue: if the flat doesn't fit, a developer drops to soma + morfo and composes freely. No vendor lock-in in the visual layer; eidos is the design system convention, soma is the universal primitive. Files: - src/uix/eidos/components/collapsible/collapsible.svelte (NEW): flat default that auto-composes Provider + Trigger + Content via a `trigger` snippet for the toggle label and `children` for the body. - src/uix/eidos/components/collapsible/types.ts: adds `CollapsibleFlatProps = SomaCollapsibleProps & { trigger?: Snippet }`. - src/uix/eidos/components/collapsible/index.ts: exports `default` (flat) plus named `Provider`/`Trigger`/`Content` (compound). - src/uix/eidos/components/collapsible/{trigger,content,provider}.svelte: fixed children destructuring so snippets propagate cleanly to soma (was previously spreading $props() blindly which can lose snippet bindings in Svelte 5). - src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md: NEW §13 "Doctrina del API: soma compound, eidos opinionado" formalises the two-shape rule and the architectural virtue (soma+morfo as universal foundation). Renumbered §13/§14 → §14/§15. - web/routes/collapsible/+page.svelte: live preview now uses the flat form; eidos snippet shows the flat shape; soma snippet keeps the compound shape; Notes tab updated. - src/uix/eidos/components/collapsible/README.md: rewrote API section with both shapes + the "if neither fits, use soma+morfo" escape. Tests 218/218 green. npm run check baseline 39. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
- **Single-part** (Toggle, Switch): el `default` es el componente visual
completo.
- **Multi-part** (Collapsible, Dialog, Drawer, Popover, Toast): el `default`
es el root visual (`<Drawer>`, `<Dialog>`, etc.) y los hijos se acceden como
propiedades attached (`<Drawer.Trigger>`, `<Drawer.Content>`, etc.).
- No hay `Provider` publico en Eidos; `Provider` sigue siendo nombre de Soma.
collapsible: flat <Collapsible> ergonomic default + compound parts Per the doctrine update in GUIA §13: eidos for multi-part components exposes BOTH a flat default that auto-composes Provider/Trigger/Content AND the compound parts for advanced cases. Soma + morfo remain the universal composable foundation underneath. Why: with the previous "compound only" rule for multi-part, eidos collapsible was a pure pass-through that added nothing operational — the consumer wrote the same import + same shape as soma. The flat default makes eidos earn its layer by collapsing the 90% case to a single call: // 90% case — flat ergonomic <Collapsible bind:open> {#snippet trigger()}Show details{/snippet} <p>Body content.</p> </Collapsible> // Advanced — compound (parts in different subtrees, multi-trigger, // conditional content) <header><Collapsible.Provider bind:open> <Collapsible.Trigger>Show</Collapsible.Trigger> </Collapsible.Provider></header> <aside> <Collapsible.Content>...</Collapsible.Content> </aside> The architectural virtue: if the flat doesn't fit, a developer drops to soma + morfo and composes freely. No vendor lock-in in the visual layer; eidos is the design system convention, soma is the universal primitive. Files: - src/uix/eidos/components/collapsible/collapsible.svelte (NEW): flat default that auto-composes Provider + Trigger + Content via a `trigger` snippet for the toggle label and `children` for the body. - src/uix/eidos/components/collapsible/types.ts: adds `CollapsibleFlatProps = SomaCollapsibleProps & { trigger?: Snippet }`. - src/uix/eidos/components/collapsible/index.ts: exports `default` (flat) plus named `Provider`/`Trigger`/`Content` (compound). - src/uix/eidos/components/collapsible/{trigger,content,provider}.svelte: fixed children destructuring so snippets propagate cleanly to soma (was previously spreading $props() blindly which can lose snippet bindings in Svelte 5). - src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md: NEW §13 "Doctrina del API: soma compound, eidos opinionado" formalises the two-shape rule and the architectural virtue (soma+morfo as universal foundation). Renumbered §13/§14 → §14/§15. - web/routes/collapsible/+page.svelte: live preview now uses the flat form; eidos snippet shows the flat shape; soma snippet keeps the compound shape; Notes tab updated. - src/uix/eidos/components/collapsible/README.md: rewrote API section with both shapes + the "if neither fits, use soma+morfo" escape. Tests 218/218 green. npm run check baseline 39. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
### 13.2. Forma publica vigente
collapsible: flat <Collapsible> ergonomic default + compound parts Per the doctrine update in GUIA §13: eidos for multi-part components exposes BOTH a flat default that auto-composes Provider/Trigger/Content AND the compound parts for advanced cases. Soma + morfo remain the universal composable foundation underneath. Why: with the previous "compound only" rule for multi-part, eidos collapsible was a pure pass-through that added nothing operational — the consumer wrote the same import + same shape as soma. The flat default makes eidos earn its layer by collapsing the 90% case to a single call: // 90% case — flat ergonomic <Collapsible bind:open> {#snippet trigger()}Show details{/snippet} <p>Body content.</p> </Collapsible> // Advanced — compound (parts in different subtrees, multi-trigger, // conditional content) <header><Collapsible.Provider bind:open> <Collapsible.Trigger>Show</Collapsible.Trigger> </Collapsible.Provider></header> <aside> <Collapsible.Content>...</Collapsible.Content> </aside> The architectural virtue: if the flat doesn't fit, a developer drops to soma + morfo and composes freely. No vendor lock-in in the visual layer; eidos is the design system convention, soma is the universal primitive. Files: - src/uix/eidos/components/collapsible/collapsible.svelte (NEW): flat default that auto-composes Provider + Trigger + Content via a `trigger` snippet for the toggle label and `children` for the body. - src/uix/eidos/components/collapsible/types.ts: adds `CollapsibleFlatProps = SomaCollapsibleProps & { trigger?: Snippet }`. - src/uix/eidos/components/collapsible/index.ts: exports `default` (flat) plus named `Provider`/`Trigger`/`Content` (compound). - src/uix/eidos/components/collapsible/{trigger,content,provider}.svelte: fixed children destructuring so snippets propagate cleanly to soma (was previously spreading $props() blindly which can lose snippet bindings in Svelte 5). - src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md: NEW §13 "Doctrina del API: soma compound, eidos opinionado" formalises the two-shape rule and the architectural virtue (soma+morfo as universal foundation). Renumbered §13/§14 → §14/§15. - web/routes/collapsible/+page.svelte: live preview now uses the flat form; eidos snippet shows the flat shape; soma snippet keeps the compound shape; Notes tab updated. - src/uix/eidos/components/collapsible/README.md: rewrote API section with both shapes + the "if neither fits, use soma+morfo" escape. Tests 218/218 green. npm run check baseline 39. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
```svelte
<Drawer bind:open>
<Drawer.Trigger>Open</Drawer.Trigger>
<Drawer.Portal>
<Drawer.Overlay />
<Drawer.Content>
<Drawer.Title>Title</Drawer.Title>
<Drawer.Close>Close</Drawer.Close>
</Drawer.Content>
</Drawer.Portal>
</Drawer>
collapsible: flat <Collapsible> ergonomic default + compound parts Per the doctrine update in GUIA §13: eidos for multi-part components exposes BOTH a flat default that auto-composes Provider/Trigger/Content AND the compound parts for advanced cases. Soma + morfo remain the universal composable foundation underneath. Why: with the previous "compound only" rule for multi-part, eidos collapsible was a pure pass-through that added nothing operational — the consumer wrote the same import + same shape as soma. The flat default makes eidos earn its layer by collapsing the 90% case to a single call: // 90% case — flat ergonomic <Collapsible bind:open> {#snippet trigger()}Show details{/snippet} <p>Body content.</p> </Collapsible> // Advanced — compound (parts in different subtrees, multi-trigger, // conditional content) <header><Collapsible.Provider bind:open> <Collapsible.Trigger>Show</Collapsible.Trigger> </Collapsible.Provider></header> <aside> <Collapsible.Content>...</Collapsible.Content> </aside> The architectural virtue: if the flat doesn't fit, a developer drops to soma + morfo and composes freely. No vendor lock-in in the visual layer; eidos is the design system convention, soma is the universal primitive. Files: - src/uix/eidos/components/collapsible/collapsible.svelte (NEW): flat default that auto-composes Provider + Trigger + Content via a `trigger` snippet for the toggle label and `children` for the body. - src/uix/eidos/components/collapsible/types.ts: adds `CollapsibleFlatProps = SomaCollapsibleProps & { trigger?: Snippet }`. - src/uix/eidos/components/collapsible/index.ts: exports `default` (flat) plus named `Provider`/`Trigger`/`Content` (compound). - src/uix/eidos/components/collapsible/{trigger,content,provider}.svelte: fixed children destructuring so snippets propagate cleanly to soma (was previously spreading $props() blindly which can lose snippet bindings in Svelte 5). - src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md: NEW §13 "Doctrina del API: soma compound, eidos opinionado" formalises the two-shape rule and the architectural virtue (soma+morfo as universal foundation). Renumbered §13/§14 → §14/§15. - web/routes/collapsible/+page.svelte: live preview now uses the flat form; eidos snippet shows the flat shape; soma snippet keeps the compound shape; Notes tab updated. - src/uix/eidos/components/collapsible/README.md: rewrote API section with both shapes + the "if neither fits, use soma+morfo" escape. Tests 218/218 green. npm run check baseline 39. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
```
El `index.ts` de cada componente attached usa asignacion explicita, no
`Object.assign`:
collapsible: flat <Collapsible> ergonomic default + compound parts Per the doctrine update in GUIA §13: eidos for multi-part components exposes BOTH a flat default that auto-composes Provider/Trigger/Content AND the compound parts for advanced cases. Soma + morfo remain the universal composable foundation underneath. Why: with the previous "compound only" rule for multi-part, eidos collapsible was a pure pass-through that added nothing operational — the consumer wrote the same import + same shape as soma. The flat default makes eidos earn its layer by collapsing the 90% case to a single call: // 90% case — flat ergonomic <Collapsible bind:open> {#snippet trigger()}Show details{/snippet} <p>Body content.</p> </Collapsible> // Advanced — compound (parts in different subtrees, multi-trigger, // conditional content) <header><Collapsible.Provider bind:open> <Collapsible.Trigger>Show</Collapsible.Trigger> </Collapsible.Provider></header> <aside> <Collapsible.Content>...</Collapsible.Content> </aside> The architectural virtue: if the flat doesn't fit, a developer drops to soma + morfo and composes freely. No vendor lock-in in the visual layer; eidos is the design system convention, soma is the universal primitive. Files: - src/uix/eidos/components/collapsible/collapsible.svelte (NEW): flat default that auto-composes Provider + Trigger + Content via a `trigger` snippet for the toggle label and `children` for the body. - src/uix/eidos/components/collapsible/types.ts: adds `CollapsibleFlatProps = SomaCollapsibleProps & { trigger?: Snippet }`. - src/uix/eidos/components/collapsible/index.ts: exports `default` (flat) plus named `Provider`/`Trigger`/`Content` (compound). - src/uix/eidos/components/collapsible/{trigger,content,provider}.svelte: fixed children destructuring so snippets propagate cleanly to soma (was previously spreading $props() blindly which can lose snippet bindings in Svelte 5). - src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md: NEW §13 "Doctrina del API: soma compound, eidos opinionado" formalises the two-shape rule and the architectural virtue (soma+morfo as universal foundation). Renumbered §13/§14 → §14/§15. - web/routes/collapsible/+page.svelte: live preview now uses the flat form; eidos snippet shows the flat shape; soma snippet keeps the compound shape; Notes tab updated. - src/uix/eidos/components/collapsible/README.md: rewrote API section with both shapes + the "if neither fits, use soma+morfo" escape. Tests 218/218 green. npm run check baseline 39. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
```ts
const Drawer = DrawerRoot as DrawerNamespace;
Drawer.Trigger = Trigger;
Drawer.Portal = Portal;
Drawer.Content = Content;
export { Drawer };
export default Drawer;
collapsible: flat <Collapsible> ergonomic default + compound parts Per the doctrine update in GUIA §13: eidos for multi-part components exposes BOTH a flat default that auto-composes Provider/Trigger/Content AND the compound parts for advanced cases. Soma + morfo remain the universal composable foundation underneath. Why: with the previous "compound only" rule for multi-part, eidos collapsible was a pure pass-through that added nothing operational — the consumer wrote the same import + same shape as soma. The flat default makes eidos earn its layer by collapsing the 90% case to a single call: // 90% case — flat ergonomic <Collapsible bind:open> {#snippet trigger()}Show details{/snippet} <p>Body content.</p> </Collapsible> // Advanced — compound (parts in different subtrees, multi-trigger, // conditional content) <header><Collapsible.Provider bind:open> <Collapsible.Trigger>Show</Collapsible.Trigger> </Collapsible.Provider></header> <aside> <Collapsible.Content>...</Collapsible.Content> </aside> The architectural virtue: if the flat doesn't fit, a developer drops to soma + morfo and composes freely. No vendor lock-in in the visual layer; eidos is the design system convention, soma is the universal primitive. Files: - src/uix/eidos/components/collapsible/collapsible.svelte (NEW): flat default that auto-composes Provider + Trigger + Content via a `trigger` snippet for the toggle label and `children` for the body. - src/uix/eidos/components/collapsible/types.ts: adds `CollapsibleFlatProps = SomaCollapsibleProps & { trigger?: Snippet }`. - src/uix/eidos/components/collapsible/index.ts: exports `default` (flat) plus named `Provider`/`Trigger`/`Content` (compound). - src/uix/eidos/components/collapsible/{trigger,content,provider}.svelte: fixed children destructuring so snippets propagate cleanly to soma (was previously spreading $props() blindly which can lose snippet bindings in Svelte 5). - src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md: NEW §13 "Doctrina del API: soma compound, eidos opinionado" formalises the two-shape rule and the architectural virtue (soma+morfo as universal foundation). Renumbered §13/§14 → §14/§15. - web/routes/collapsible/+page.svelte: live preview now uses the flat form; eidos snippet shows the flat shape; soma snippet keeps the compound shape; Notes tab updated. - src/uix/eidos/components/collapsible/README.md: rewrote API section with both shapes + the "if neither fits, use soma+morfo" escape. Tests 218/218 green. npm run check baseline 39. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
```
### 13.3. La virtud arquitectonica
collapsible: flat <Collapsible> ergonomic default + compound parts Per the doctrine update in GUIA §13: eidos for multi-part components exposes BOTH a flat default that auto-composes Provider/Trigger/Content AND the compound parts for advanced cases. Soma + morfo remain the universal composable foundation underneath. Why: with the previous "compound only" rule for multi-part, eidos collapsible was a pure pass-through that added nothing operational — the consumer wrote the same import + same shape as soma. The flat default makes eidos earn its layer by collapsing the 90% case to a single call: // 90% case — flat ergonomic <Collapsible bind:open> {#snippet trigger()}Show details{/snippet} <p>Body content.</p> </Collapsible> // Advanced — compound (parts in different subtrees, multi-trigger, // conditional content) <header><Collapsible.Provider bind:open> <Collapsible.Trigger>Show</Collapsible.Trigger> </Collapsible.Provider></header> <aside> <Collapsible.Content>...</Collapsible.Content> </aside> The architectural virtue: if the flat doesn't fit, a developer drops to soma + morfo and composes freely. No vendor lock-in in the visual layer; eidos is the design system convention, soma is the universal primitive. Files: - src/uix/eidos/components/collapsible/collapsible.svelte (NEW): flat default that auto-composes Provider + Trigger + Content via a `trigger` snippet for the toggle label and `children` for the body. - src/uix/eidos/components/collapsible/types.ts: adds `CollapsibleFlatProps = SomaCollapsibleProps & { trigger?: Snippet }`. - src/uix/eidos/components/collapsible/index.ts: exports `default` (flat) plus named `Provider`/`Trigger`/`Content` (compound). - src/uix/eidos/components/collapsible/{trigger,content,provider}.svelte: fixed children destructuring so snippets propagate cleanly to soma (was previously spreading $props() blindly which can lose snippet bindings in Svelte 5). - src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md: NEW §13 "Doctrina del API: soma compound, eidos opinionado" formalises the two-shape rule and the architectural virtue (soma+morfo as universal foundation). Renumbered §13/§14 → §14/§15. - web/routes/collapsible/+page.svelte: live preview now uses the flat form; eidos snippet shows the flat shape; soma snippet keeps the compound shape; Notes tab updated. - src/uix/eidos/components/collapsible/README.md: rewrote API section with both shapes + the "if neither fits, use soma+morfo" escape. Tests 218/218 green. npm run check baseline 39. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
La capa visual ya no mantiene dos verdades. Si una app necesita una composicion
que el wrapper visual no cubre, baja a `$soma/components/{x}` y compone la
primitiva headless directamente. Eidos no bloquea esa salida; simplemente no
mantiene un segundo API flat con snippets que duplique el compound.
collapsible: flat <Collapsible> ergonomic default + compound parts Per the doctrine update in GUIA §13: eidos for multi-part components exposes BOTH a flat default that auto-composes Provider/Trigger/Content AND the compound parts for advanced cases. Soma + morfo remain the universal composable foundation underneath. Why: with the previous "compound only" rule for multi-part, eidos collapsible was a pure pass-through that added nothing operational — the consumer wrote the same import + same shape as soma. The flat default makes eidos earn its layer by collapsing the 90% case to a single call: // 90% case — flat ergonomic <Collapsible bind:open> {#snippet trigger()}Show details{/snippet} <p>Body content.</p> </Collapsible> // Advanced — compound (parts in different subtrees, multi-trigger, // conditional content) <header><Collapsible.Provider bind:open> <Collapsible.Trigger>Show</Collapsible.Trigger> </Collapsible.Provider></header> <aside> <Collapsible.Content>...</Collapsible.Content> </aside> The architectural virtue: if the flat doesn't fit, a developer drops to soma + morfo and composes freely. No vendor lock-in in the visual layer; eidos is the design system convention, soma is the universal primitive. Files: - src/uix/eidos/components/collapsible/collapsible.svelte (NEW): flat default that auto-composes Provider + Trigger + Content via a `trigger` snippet for the toggle label and `children` for the body. - src/uix/eidos/components/collapsible/types.ts: adds `CollapsibleFlatProps = SomaCollapsibleProps & { trigger?: Snippet }`. - src/uix/eidos/components/collapsible/index.ts: exports `default` (flat) plus named `Provider`/`Trigger`/`Content` (compound). - src/uix/eidos/components/collapsible/{trigger,content,provider}.svelte: fixed children destructuring so snippets propagate cleanly to soma (was previously spreading $props() blindly which can lose snippet bindings in Svelte 5). - src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md: NEW §13 "Doctrina del API: soma compound, eidos opinionado" formalises the two-shape rule and the architectural virtue (soma+morfo as universal foundation). Renumbered §13/§14 → §14/§15. - web/routes/collapsible/+page.svelte: live preview now uses the flat form; eidos snippet shows the flat shape; soma snippet keeps the compound shape; Notes tab updated. - src/uix/eidos/components/collapsible/README.md: rewrote API section with both shapes + the "if neither fits, use soma+morfo" escape. Tests 218/218 green. npm run check baseline 39. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
---
## 14. Plan de migración
### 14.1. Prioridad 1 — Vocabulario
sema/morfo/eidos: align with GUIA_IMPLEMENTACION_SEMAUIX (canonical guide) The new doctrinal guide at src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md supersedes src/docs/sema-implementation-guide.md and locks the canonical vocabulary, event shape and color tokens. This commit aligns the codebase to that canon in three concrete moves. Phase 1 — sema/verbs.ts vocabulary: - Restructured from flat array to family-keyed Record per the guide. - Moved select / toggle / acknowledge → commit (these fix state, not contact). Removed edit from handle (it's shift.enter-mode now). - Added new verbs per the canon: contact (tap, focus, trigger, release), commit (complete, restore, expire, set, remove, reorder), signal (remind), handle (rotate, scroll, reorder), shift (route, step, return, context), sustain (start, loading, waiting, syncing, processing, streaming, pending, retrying, end). - validateEventName now recognises both naming shapes: {verb}-{variant} (head=verb) and {family}-{verb} (head=family). - New helper familyForVerb. Tests rewritten — 16/16 green. Phase 2 — morfo event shape: - target moved from event-level into event.semantic. Adds optional semantic.verb (advisory, validated against SEMA_VERBS[family]) and optional semantic.sequence ('pre' | 'coincident' | 'post'). - compile.ts and schema.ts updated. The 22 events across toggle, toast, popover, drawer, dialog refactored to the new shape with explicit verb + sequence. - Polymorphic capability (allowedFamilies + defaultSemantic) and a11ySemantic deferred — no current consumer needs them; will land when the first concrete usage appears. Phase 5 — color tokens (doctrinal 8): - themes/base/light.css and dark.css rewritten to expose primary, secondary, neutral, affirm, fulfill, risk, threat, loss. Renames success→fulfill, warning→risk, danger→threat (same hex). New primitives for secondary (slate-blue), affirm (teal-mint, low activation), loss (deep violet-grave, posterior). info palette deleted entirely — per guide, "info no es intent, es signal.announce + neutral". - _static.css legacy compatibility aliases (--color-bg, --color-success, --color-error, --color-accent, ...) deleted. Clean cut, no transition. Consumers reference doctrinal palettes directly. - 29 consumers (token files + recipes) migrated: - All --*-color-info-* declarations dropped. - Component palettes extended with secondary / affirm / loss. - switch + checkbox recipes updated to use [data-color='affirm'| 'risk'|'threat'|'secondary'] (was 'success'|'warning'|'danger'| 'info'). - toast tokens + recipe renamed to affirm/fulfill/risk/threat/loss (was success/error/warning/info). - meter, progress, mark, badge, button tokens renamed. - Contracts (contracts/contract.css + contracts/components/*) updated. - focus-ring-color-error in themes now points to --color-risk-border (validation errors are signal.warn + risk per doctrina, not threat). Phase 4 (partial): - src/docs/sema-implementation-guide.md deleted (superseded by the canonical guide). Tests: 217/217 green across uix. npm run check holds at the 39-error baseline (all pre-existing in unrelated test files; none introduced). Pending in follow-up commits: - Update active_architecture.md, sema/README.md, morfo/README.md, CLAUDE.md to reflect the canon. - Switch component migration to the eidos wrapper pattern. - Persistence field (untilAction / untilFix / stateBound) and holds-by-intent — defer until the first signal.warn / signal.alert consumer appears. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
1. Renombrar `alert` → `signal` en SEMA_FAMILIES
2. Añadir `shift` a SEMA_FAMILIES
3. Añadir `loss` a SEMA_INTENTS
4. Mover verbs: select/toggle a commit, acknowledge a commit, edit a shift
5. Actualizar SEMA_VERBS con la tabla completa
collapsible: flat <Collapsible> ergonomic default + compound parts Per the doctrine update in GUIA §13: eidos for multi-part components exposes BOTH a flat default that auto-composes Provider/Trigger/Content AND the compound parts for advanced cases. Soma + morfo remain the universal composable foundation underneath. Why: with the previous "compound only" rule for multi-part, eidos collapsible was a pure pass-through that added nothing operational — the consumer wrote the same import + same shape as soma. The flat default makes eidos earn its layer by collapsing the 90% case to a single call: // 90% case — flat ergonomic <Collapsible bind:open> {#snippet trigger()}Show details{/snippet} <p>Body content.</p> </Collapsible> // Advanced — compound (parts in different subtrees, multi-trigger, // conditional content) <header><Collapsible.Provider bind:open> <Collapsible.Trigger>Show</Collapsible.Trigger> </Collapsible.Provider></header> <aside> <Collapsible.Content>...</Collapsible.Content> </aside> The architectural virtue: if the flat doesn't fit, a developer drops to soma + morfo and composes freely. No vendor lock-in in the visual layer; eidos is the design system convention, soma is the universal primitive. Files: - src/uix/eidos/components/collapsible/collapsible.svelte (NEW): flat default that auto-composes Provider + Trigger + Content via a `trigger` snippet for the toggle label and `children` for the body. - src/uix/eidos/components/collapsible/types.ts: adds `CollapsibleFlatProps = SomaCollapsibleProps & { trigger?: Snippet }`. - src/uix/eidos/components/collapsible/index.ts: exports `default` (flat) plus named `Provider`/`Trigger`/`Content` (compound). - src/uix/eidos/components/collapsible/{trigger,content,provider}.svelte: fixed children destructuring so snippets propagate cleanly to soma (was previously spreading $props() blindly which can lose snippet bindings in Svelte 5). - src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md: NEW §13 "Doctrina del API: soma compound, eidos opinionado" formalises the two-shape rule and the architectural virtue (soma+morfo as universal foundation). Renumbered §13/§14 → §14/§15. - web/routes/collapsible/+page.svelte: live preview now uses the flat form; eidos snippet shows the flat shape; soma snippet keeps the compound shape; Notes tab updated. - src/uix/eidos/components/collapsible/README.md: rewrote API section with both shapes + the "if neither fits, use soma+morfo" escape. Tests 218/218 green. npm run check baseline 39. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
### 14.2. Prioridad 2 — Tokens de color
sema/morfo/eidos: align with GUIA_IMPLEMENTACION_SEMAUIX (canonical guide) The new doctrinal guide at src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md supersedes src/docs/sema-implementation-guide.md and locks the canonical vocabulary, event shape and color tokens. This commit aligns the codebase to that canon in three concrete moves. Phase 1 — sema/verbs.ts vocabulary: - Restructured from flat array to family-keyed Record per the guide. - Moved select / toggle / acknowledge → commit (these fix state, not contact). Removed edit from handle (it's shift.enter-mode now). - Added new verbs per the canon: contact (tap, focus, trigger, release), commit (complete, restore, expire, set, remove, reorder), signal (remind), handle (rotate, scroll, reorder), shift (route, step, return, context), sustain (start, loading, waiting, syncing, processing, streaming, pending, retrying, end). - validateEventName now recognises both naming shapes: {verb}-{variant} (head=verb) and {family}-{verb} (head=family). - New helper familyForVerb. Tests rewritten — 16/16 green. Phase 2 — morfo event shape: - target moved from event-level into event.semantic. Adds optional semantic.verb (advisory, validated against SEMA_VERBS[family]) and optional semantic.sequence ('pre' | 'coincident' | 'post'). - compile.ts and schema.ts updated. The 22 events across toggle, toast, popover, drawer, dialog refactored to the new shape with explicit verb + sequence. - Polymorphic capability (allowedFamilies + defaultSemantic) and a11ySemantic deferred — no current consumer needs them; will land when the first concrete usage appears. Phase 5 — color tokens (doctrinal 8): - themes/base/light.css and dark.css rewritten to expose primary, secondary, neutral, affirm, fulfill, risk, threat, loss. Renames success→fulfill, warning→risk, danger→threat (same hex). New primitives for secondary (slate-blue), affirm (teal-mint, low activation), loss (deep violet-grave, posterior). info palette deleted entirely — per guide, "info no es intent, es signal.announce + neutral". - _static.css legacy compatibility aliases (--color-bg, --color-success, --color-error, --color-accent, ...) deleted. Clean cut, no transition. Consumers reference doctrinal palettes directly. - 29 consumers (token files + recipes) migrated: - All --*-color-info-* declarations dropped. - Component palettes extended with secondary / affirm / loss. - switch + checkbox recipes updated to use [data-color='affirm'| 'risk'|'threat'|'secondary'] (was 'success'|'warning'|'danger'| 'info'). - toast tokens + recipe renamed to affirm/fulfill/risk/threat/loss (was success/error/warning/info). - meter, progress, mark, badge, button tokens renamed. - Contracts (contracts/contract.css + contracts/components/*) updated. - focus-ring-color-error in themes now points to --color-risk-border (validation errors are signal.warn + risk per doctrina, not threat). Phase 4 (partial): - src/docs/sema-implementation-guide.md deleted (superseded by the canonical guide). Tests: 217/217 green across uix. npm run check holds at the 39-error baseline (all pre-existing in unrelated test files; none introduced). Pending in follow-up commits: - Update active_architecture.md, sema/README.md, morfo/README.md, CLAUDE.md to reflect the canon. - Switch component migration to the eidos wrapper pattern. - Persistence field (untilAction / untilFix / stateBound) and holds-by-intent — defer until the first signal.warn / signal.alert consumer appears. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
1. Añadir tokens: `secondary`, `affirm`, `loss`
2. Renombrar: `success → fulfill`, `warning → risk`, `danger → threat`
3. Eliminar: `info`
4. Implementar regla de resolución intent ↔ color en providers
collapsible: flat <Collapsible> ergonomic default + compound parts Per the doctrine update in GUIA §13: eidos for multi-part components exposes BOTH a flat default that auto-composes Provider/Trigger/Content AND the compound parts for advanced cases. Soma + morfo remain the universal composable foundation underneath. Why: with the previous "compound only" rule for multi-part, eidos collapsible was a pure pass-through that added nothing operational — the consumer wrote the same import + same shape as soma. The flat default makes eidos earn its layer by collapsing the 90% case to a single call: // 90% case — flat ergonomic <Collapsible bind:open> {#snippet trigger()}Show details{/snippet} <p>Body content.</p> </Collapsible> // Advanced — compound (parts in different subtrees, multi-trigger, // conditional content) <header><Collapsible.Provider bind:open> <Collapsible.Trigger>Show</Collapsible.Trigger> </Collapsible.Provider></header> <aside> <Collapsible.Content>...</Collapsible.Content> </aside> The architectural virtue: if the flat doesn't fit, a developer drops to soma + morfo and composes freely. No vendor lock-in in the visual layer; eidos is the design system convention, soma is the universal primitive. Files: - src/uix/eidos/components/collapsible/collapsible.svelte (NEW): flat default that auto-composes Provider + Trigger + Content via a `trigger` snippet for the toggle label and `children` for the body. - src/uix/eidos/components/collapsible/types.ts: adds `CollapsibleFlatProps = SomaCollapsibleProps & { trigger?: Snippet }`. - src/uix/eidos/components/collapsible/index.ts: exports `default` (flat) plus named `Provider`/`Trigger`/`Content` (compound). - src/uix/eidos/components/collapsible/{trigger,content,provider}.svelte: fixed children destructuring so snippets propagate cleanly to soma (was previously spreading $props() blindly which can lose snippet bindings in Svelte 5). - src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md: NEW §13 "Doctrina del API: soma compound, eidos opinionado" formalises the two-shape rule and the architectural virtue (soma+morfo as universal foundation). Renumbered §13/§14 → §14/§15. - web/routes/collapsible/+page.svelte: live preview now uses the flat form; eidos snippet shows the flat shape; soma snippet keeps the compound shape; Notes tab updated. - src/uix/eidos/components/collapsible/README.md: rewrote API section with both shapes + the "if neither fits, use soma+morfo" escape. Tests 218/218 green. npm run check baseline 39. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
### 14.3. Prioridad 3 — Holds y persistencia
sema/morfo/eidos: align with GUIA_IMPLEMENTACION_SEMAUIX (canonical guide) The new doctrinal guide at src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md supersedes src/docs/sema-implementation-guide.md and locks the canonical vocabulary, event shape and color tokens. This commit aligns the codebase to that canon in three concrete moves. Phase 1 — sema/verbs.ts vocabulary: - Restructured from flat array to family-keyed Record per the guide. - Moved select / toggle / acknowledge → commit (these fix state, not contact). Removed edit from handle (it's shift.enter-mode now). - Added new verbs per the canon: contact (tap, focus, trigger, release), commit (complete, restore, expire, set, remove, reorder), signal (remind), handle (rotate, scroll, reorder), shift (route, step, return, context), sustain (start, loading, waiting, syncing, processing, streaming, pending, retrying, end). - validateEventName now recognises both naming shapes: {verb}-{variant} (head=verb) and {family}-{verb} (head=family). - New helper familyForVerb. Tests rewritten — 16/16 green. Phase 2 — morfo event shape: - target moved from event-level into event.semantic. Adds optional semantic.verb (advisory, validated against SEMA_VERBS[family]) and optional semantic.sequence ('pre' | 'coincident' | 'post'). - compile.ts and schema.ts updated. The 22 events across toggle, toast, popover, drawer, dialog refactored to the new shape with explicit verb + sequence. - Polymorphic capability (allowedFamilies + defaultSemantic) and a11ySemantic deferred — no current consumer needs them; will land when the first concrete usage appears. Phase 5 — color tokens (doctrinal 8): - themes/base/light.css and dark.css rewritten to expose primary, secondary, neutral, affirm, fulfill, risk, threat, loss. Renames success→fulfill, warning→risk, danger→threat (same hex). New primitives for secondary (slate-blue), affirm (teal-mint, low activation), loss (deep violet-grave, posterior). info palette deleted entirely — per guide, "info no es intent, es signal.announce + neutral". - _static.css legacy compatibility aliases (--color-bg, --color-success, --color-error, --color-accent, ...) deleted. Clean cut, no transition. Consumers reference doctrinal palettes directly. - 29 consumers (token files + recipes) migrated: - All --*-color-info-* declarations dropped. - Component palettes extended with secondary / affirm / loss. - switch + checkbox recipes updated to use [data-color='affirm'| 'risk'|'threat'|'secondary'] (was 'success'|'warning'|'danger'| 'info'). - toast tokens + recipe renamed to affirm/fulfill/risk/threat/loss (was success/error/warning/info). - meter, progress, mark, badge, button tokens renamed. - Contracts (contracts/contract.css + contracts/components/*) updated. - focus-ring-color-error in themes now points to --color-risk-border (validation errors are signal.warn + risk per doctrina, not threat). Phase 4 (partial): - src/docs/sema-implementation-guide.md deleted (superseded by the canonical guide). Tests: 217/217 green across uix. npm run check holds at the 39-error baseline (all pre-existing in unrelated test files; none introduced). Pending in follow-up commits: - Update active_architecture.md, sema/README.md, morfo/README.md, CLAUDE.md to reflect the canon. - Switch component migration to the eidos wrapper pattern. - Persistence field (untilAction / untilFix / stateBound) and holds-by-intent — defer until the first signal.warn / signal.alert consumer appears. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
1. Separar `hold` expresivo de `persistence` semántica
2. Actualizar holds por familia/intent según tabla
3. Sustain como `stateBound`, no hold fijo
collapsible: flat <Collapsible> ergonomic default + compound parts Per the doctrine update in GUIA §13: eidos for multi-part components exposes BOTH a flat default that auto-composes Provider/Trigger/Content AND the compound parts for advanced cases. Soma + morfo remain the universal composable foundation underneath. Why: with the previous "compound only" rule for multi-part, eidos collapsible was a pure pass-through that added nothing operational — the consumer wrote the same import + same shape as soma. The flat default makes eidos earn its layer by collapsing the 90% case to a single call: // 90% case — flat ergonomic <Collapsible bind:open> {#snippet trigger()}Show details{/snippet} <p>Body content.</p> </Collapsible> // Advanced — compound (parts in different subtrees, multi-trigger, // conditional content) <header><Collapsible.Provider bind:open> <Collapsible.Trigger>Show</Collapsible.Trigger> </Collapsible.Provider></header> <aside> <Collapsible.Content>...</Collapsible.Content> </aside> The architectural virtue: if the flat doesn't fit, a developer drops to soma + morfo and composes freely. No vendor lock-in in the visual layer; eidos is the design system convention, soma is the universal primitive. Files: - src/uix/eidos/components/collapsible/collapsible.svelte (NEW): flat default that auto-composes Provider + Trigger + Content via a `trigger` snippet for the toggle label and `children` for the body. - src/uix/eidos/components/collapsible/types.ts: adds `CollapsibleFlatProps = SomaCollapsibleProps & { trigger?: Snippet }`. - src/uix/eidos/components/collapsible/index.ts: exports `default` (flat) plus named `Provider`/`Trigger`/`Content` (compound). - src/uix/eidos/components/collapsible/{trigger,content,provider}.svelte: fixed children destructuring so snippets propagate cleanly to soma (was previously spreading $props() blindly which can lose snippet bindings in Svelte 5). - src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md: NEW §13 "Doctrina del API: soma compound, eidos opinionado" formalises the two-shape rule and the architectural virtue (soma+morfo as universal foundation). Renumbered §13/§14 → §14/§15. - web/routes/collapsible/+page.svelte: live preview now uses the flat form; eidos snippet shows the flat shape; soma snippet keeps the compound shape; Notes tab updated. - src/uix/eidos/components/collapsible/README.md: rewrote API section with both shapes + the "if neither fits, use soma+morfo" escape. Tests 218/218 green. npm run check baseline 39. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
### 14.4. Prioridad 4 — Sequence timing
sema/morfo/eidos: align with GUIA_IMPLEMENTACION_SEMAUIX (canonical guide) The new doctrinal guide at src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md supersedes src/docs/sema-implementation-guide.md and locks the canonical vocabulary, event shape and color tokens. This commit aligns the codebase to that canon in three concrete moves. Phase 1 — sema/verbs.ts vocabulary: - Restructured from flat array to family-keyed Record per the guide. - Moved select / toggle / acknowledge → commit (these fix state, not contact). Removed edit from handle (it's shift.enter-mode now). - Added new verbs per the canon: contact (tap, focus, trigger, release), commit (complete, restore, expire, set, remove, reorder), signal (remind), handle (rotate, scroll, reorder), shift (route, step, return, context), sustain (start, loading, waiting, syncing, processing, streaming, pending, retrying, end). - validateEventName now recognises both naming shapes: {verb}-{variant} (head=verb) and {family}-{verb} (head=family). - New helper familyForVerb. Tests rewritten — 16/16 green. Phase 2 — morfo event shape: - target moved from event-level into event.semantic. Adds optional semantic.verb (advisory, validated against SEMA_VERBS[family]) and optional semantic.sequence ('pre' | 'coincident' | 'post'). - compile.ts and schema.ts updated. The 22 events across toggle, toast, popover, drawer, dialog refactored to the new shape with explicit verb + sequence. - Polymorphic capability (allowedFamilies + defaultSemantic) and a11ySemantic deferred — no current consumer needs them; will land when the first concrete usage appears. Phase 5 — color tokens (doctrinal 8): - themes/base/light.css and dark.css rewritten to expose primary, secondary, neutral, affirm, fulfill, risk, threat, loss. Renames success→fulfill, warning→risk, danger→threat (same hex). New primitives for secondary (slate-blue), affirm (teal-mint, low activation), loss (deep violet-grave, posterior). info palette deleted entirely — per guide, "info no es intent, es signal.announce + neutral". - _static.css legacy compatibility aliases (--color-bg, --color-success, --color-error, --color-accent, ...) deleted. Clean cut, no transition. Consumers reference doctrinal palettes directly. - 29 consumers (token files + recipes) migrated: - All --*-color-info-* declarations dropped. - Component palettes extended with secondary / affirm / loss. - switch + checkbox recipes updated to use [data-color='affirm'| 'risk'|'threat'|'secondary'] (was 'success'|'warning'|'danger'| 'info'). - toast tokens + recipe renamed to affirm/fulfill/risk/threat/loss (was success/error/warning/info). - meter, progress, mark, badge, button tokens renamed. - Contracts (contracts/contract.css + contracts/components/*) updated. - focus-ring-color-error in themes now points to --color-risk-border (validation errors are signal.warn + risk per doctrina, not threat). Phase 4 (partial): - src/docs/sema-implementation-guide.md deleted (superseded by the canonical guide). Tests: 217/217 green across uix. npm run check holds at the 39-error baseline (all pre-existing in unrelated test files; none introduced). Pending in follow-up commits: - Update active_architecture.md, sema/README.md, morfo/README.md, CLAUDE.md to reflect the canon. - Switch component migration to the eidos wrapper pattern. - Persistence field (untilAction / untilFix / stateBound) and holds-by-intent — defer until the first signal.warn / signal.alert consumer appears. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
1. Añadir campo `sequence` a morfo events
2. Implementar `pre | coincident | post` en runtime.trigger
collapsible: flat <Collapsible> ergonomic default + compound parts Per the doctrine update in GUIA §13: eidos for multi-part components exposes BOTH a flat default that auto-composes Provider/Trigger/Content AND the compound parts for advanced cases. Soma + morfo remain the universal composable foundation underneath. Why: with the previous "compound only" rule for multi-part, eidos collapsible was a pure pass-through that added nothing operational — the consumer wrote the same import + same shape as soma. The flat default makes eidos earn its layer by collapsing the 90% case to a single call: // 90% case — flat ergonomic <Collapsible bind:open> {#snippet trigger()}Show details{/snippet} <p>Body content.</p> </Collapsible> // Advanced — compound (parts in different subtrees, multi-trigger, // conditional content) <header><Collapsible.Provider bind:open> <Collapsible.Trigger>Show</Collapsible.Trigger> </Collapsible.Provider></header> <aside> <Collapsible.Content>...</Collapsible.Content> </aside> The architectural virtue: if the flat doesn't fit, a developer drops to soma + morfo and composes freely. No vendor lock-in in the visual layer; eidos is the design system convention, soma is the universal primitive. Files: - src/uix/eidos/components/collapsible/collapsible.svelte (NEW): flat default that auto-composes Provider + Trigger + Content via a `trigger` snippet for the toggle label and `children` for the body. - src/uix/eidos/components/collapsible/types.ts: adds `CollapsibleFlatProps = SomaCollapsibleProps & { trigger?: Snippet }`. - src/uix/eidos/components/collapsible/index.ts: exports `default` (flat) plus named `Provider`/`Trigger`/`Content` (compound). - src/uix/eidos/components/collapsible/{trigger,content,provider}.svelte: fixed children destructuring so snippets propagate cleanly to soma (was previously spreading $props() blindly which can lose snippet bindings in Svelte 5). - src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md: NEW §13 "Doctrina del API: soma compound, eidos opinionado" formalises the two-shape rule and the architectural virtue (soma+morfo as universal foundation). Renumbered §13/§14 → §14/§15. - web/routes/collapsible/+page.svelte: live preview now uses the flat form; eidos snippet shows the flat shape; soma snippet keeps the compound shape; Notes tab updated. - src/uix/eidos/components/collapsible/README.md: rewrote API section with both shapes + the "if neither fits, use soma+morfo" escape. Tests 218/218 green. npm run check baseline 39. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
### 14.5. Prioridad 5 — a11ySemantic
sema/morfo/eidos: align with GUIA_IMPLEMENTACION_SEMAUIX (canonical guide) The new doctrinal guide at src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md supersedes src/docs/sema-implementation-guide.md and locks the canonical vocabulary, event shape and color tokens. This commit aligns the codebase to that canon in three concrete moves. Phase 1 — sema/verbs.ts vocabulary: - Restructured from flat array to family-keyed Record per the guide. - Moved select / toggle / acknowledge → commit (these fix state, not contact). Removed edit from handle (it's shift.enter-mode now). - Added new verbs per the canon: contact (tap, focus, trigger, release), commit (complete, restore, expire, set, remove, reorder), signal (remind), handle (rotate, scroll, reorder), shift (route, step, return, context), sustain (start, loading, waiting, syncing, processing, streaming, pending, retrying, end). - validateEventName now recognises both naming shapes: {verb}-{variant} (head=verb) and {family}-{verb} (head=family). - New helper familyForVerb. Tests rewritten — 16/16 green. Phase 2 — morfo event shape: - target moved from event-level into event.semantic. Adds optional semantic.verb (advisory, validated against SEMA_VERBS[family]) and optional semantic.sequence ('pre' | 'coincident' | 'post'). - compile.ts and schema.ts updated. The 22 events across toggle, toast, popover, drawer, dialog refactored to the new shape with explicit verb + sequence. - Polymorphic capability (allowedFamilies + defaultSemantic) and a11ySemantic deferred — no current consumer needs them; will land when the first concrete usage appears. Phase 5 — color tokens (doctrinal 8): - themes/base/light.css and dark.css rewritten to expose primary, secondary, neutral, affirm, fulfill, risk, threat, loss. Renames success→fulfill, warning→risk, danger→threat (same hex). New primitives for secondary (slate-blue), affirm (teal-mint, low activation), loss (deep violet-grave, posterior). info palette deleted entirely — per guide, "info no es intent, es signal.announce + neutral". - _static.css legacy compatibility aliases (--color-bg, --color-success, --color-error, --color-accent, ...) deleted. Clean cut, no transition. Consumers reference doctrinal palettes directly. - 29 consumers (token files + recipes) migrated: - All --*-color-info-* declarations dropped. - Component palettes extended with secondary / affirm / loss. - switch + checkbox recipes updated to use [data-color='affirm'| 'risk'|'threat'|'secondary'] (was 'success'|'warning'|'danger'| 'info'). - toast tokens + recipe renamed to affirm/fulfill/risk/threat/loss (was success/error/warning/info). - meter, progress, mark, badge, button tokens renamed. - Contracts (contracts/contract.css + contracts/components/*) updated. - focus-ring-color-error in themes now points to --color-risk-border (validation errors are signal.warn + risk per doctrina, not threat). Phase 4 (partial): - src/docs/sema-implementation-guide.md deleted (superseded by the canonical guide). Tests: 217/217 green across uix. npm run check holds at the 39-error baseline (all pre-existing in unrelated test files; none introduced). Pending in follow-up commits: - Update active_architecture.md, sema/README.md, morfo/README.md, CLAUDE.md to reflect the canon. - Switch component migration to the eidos wrapper pattern. - Persistence field (untilAction / untilFix / stateBound) and holds-by-intent — defer until the first signal.warn / signal.alert consumer appears. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
1. Añadir contrato a11ySemantic a morfo events
2. Implementar reducedMotionFallback, liveRegion, focusMove
collapsible: flat <Collapsible> ergonomic default + compound parts Per the doctrine update in GUIA §13: eidos for multi-part components exposes BOTH a flat default that auto-composes Provider/Trigger/Content AND the compound parts for advanced cases. Soma + morfo remain the universal composable foundation underneath. Why: with the previous "compound only" rule for multi-part, eidos collapsible was a pure pass-through that added nothing operational — the consumer wrote the same import + same shape as soma. The flat default makes eidos earn its layer by collapsing the 90% case to a single call: // 90% case — flat ergonomic <Collapsible bind:open> {#snippet trigger()}Show details{/snippet} <p>Body content.</p> </Collapsible> // Advanced — compound (parts in different subtrees, multi-trigger, // conditional content) <header><Collapsible.Provider bind:open> <Collapsible.Trigger>Show</Collapsible.Trigger> </Collapsible.Provider></header> <aside> <Collapsible.Content>...</Collapsible.Content> </aside> The architectural virtue: if the flat doesn't fit, a developer drops to soma + morfo and composes freely. No vendor lock-in in the visual layer; eidos is the design system convention, soma is the universal primitive. Files: - src/uix/eidos/components/collapsible/collapsible.svelte (NEW): flat default that auto-composes Provider + Trigger + Content via a `trigger` snippet for the toggle label and `children` for the body. - src/uix/eidos/components/collapsible/types.ts: adds `CollapsibleFlatProps = SomaCollapsibleProps & { trigger?: Snippet }`. - src/uix/eidos/components/collapsible/index.ts: exports `default` (flat) plus named `Provider`/`Trigger`/`Content` (compound). - src/uix/eidos/components/collapsible/{trigger,content,provider}.svelte: fixed children destructuring so snippets propagate cleanly to soma (was previously spreading $props() blindly which can lose snippet bindings in Svelte 5). - src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md: NEW §13 "Doctrina del API: soma compound, eidos opinionado" formalises the two-shape rule and the architectural virtue (soma+morfo as universal foundation). Renumbered §13/§14 → §14/§15. - web/routes/collapsible/+page.svelte: live preview now uses the flat form; eidos snippet shows the flat shape; soma snippet keeps the compound shape; Notes tab updated. - src/uix/eidos/components/collapsible/README.md: rewrote API section with both shapes + the "if neither fits, use soma+morfo" escape. Tests 218/218 green. npm run check baseline 39. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
### 14.6. Componentes por migrar
sema/morfo/eidos: align with GUIA_IMPLEMENTACION_SEMAUIX (canonical guide) The new doctrinal guide at src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md supersedes src/docs/sema-implementation-guide.md and locks the canonical vocabulary, event shape and color tokens. This commit aligns the codebase to that canon in three concrete moves. Phase 1 — sema/verbs.ts vocabulary: - Restructured from flat array to family-keyed Record per the guide. - Moved select / toggle / acknowledge → commit (these fix state, not contact). Removed edit from handle (it's shift.enter-mode now). - Added new verbs per the canon: contact (tap, focus, trigger, release), commit (complete, restore, expire, set, remove, reorder), signal (remind), handle (rotate, scroll, reorder), shift (route, step, return, context), sustain (start, loading, waiting, syncing, processing, streaming, pending, retrying, end). - validateEventName now recognises both naming shapes: {verb}-{variant} (head=verb) and {family}-{verb} (head=family). - New helper familyForVerb. Tests rewritten — 16/16 green. Phase 2 — morfo event shape: - target moved from event-level into event.semantic. Adds optional semantic.verb (advisory, validated against SEMA_VERBS[family]) and optional semantic.sequence ('pre' | 'coincident' | 'post'). - compile.ts and schema.ts updated. The 22 events across toggle, toast, popover, drawer, dialog refactored to the new shape with explicit verb + sequence. - Polymorphic capability (allowedFamilies + defaultSemantic) and a11ySemantic deferred — no current consumer needs them; will land when the first concrete usage appears. Phase 5 — color tokens (doctrinal 8): - themes/base/light.css and dark.css rewritten to expose primary, secondary, neutral, affirm, fulfill, risk, threat, loss. Renames success→fulfill, warning→risk, danger→threat (same hex). New primitives for secondary (slate-blue), affirm (teal-mint, low activation), loss (deep violet-grave, posterior). info palette deleted entirely — per guide, "info no es intent, es signal.announce + neutral". - _static.css legacy compatibility aliases (--color-bg, --color-success, --color-error, --color-accent, ...) deleted. Clean cut, no transition. Consumers reference doctrinal palettes directly. - 29 consumers (token files + recipes) migrated: - All --*-color-info-* declarations dropped. - Component palettes extended with secondary / affirm / loss. - switch + checkbox recipes updated to use [data-color='affirm'| 'risk'|'threat'|'secondary'] (was 'success'|'warning'|'danger'| 'info'). - toast tokens + recipe renamed to affirm/fulfill/risk/threat/loss (was success/error/warning/info). - meter, progress, mark, badge, button tokens renamed. - Contracts (contracts/contract.css + contracts/components/*) updated. - focus-ring-color-error in themes now points to --color-risk-border (validation errors are signal.warn + risk per doctrina, not threat). Phase 4 (partial): - src/docs/sema-implementation-guide.md deleted (superseded by the canonical guide). Tests: 217/217 green across uix. npm run check holds at the 39-error baseline (all pre-existing in unrelated test files; none introduced). Pending in follow-up commits: - Update active_architecture.md, sema/README.md, morfo/README.md, CLAUDE.md to reflect the canon. - Switch component migration to the eidos wrapper pattern. - Persistence field (untilAction / untilFix / stateBound) and holds-by-intent — defer until the first signal.warn / signal.alert consumer appears. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
| Componente | CSS legacy | Wrapper | Subset color |
|---|---|---|---|
| toggle | — | ✅ piloto | primary, secondary, neutral, affirm, risk, threat |
| switch | switch.css | ⏳ | primary, secondary, neutral, affirm, risk, threat |
| dialog | dialog.css | ⏳ | neutral, risk, threat |
| drawer | drawer.css | ⏳ | neutral |
| popover | popover.css | ⏳ | neutral |
| toast | toast.css | ⏳ | neutral, affirm, risk, loss |
| checkbox | checkbox.css | ⏳ | primary, secondary, neutral, affirm |
| accordion | accordion.css | ⏳ | neutral |
| tabs | tabs.css | ⏳ | neutral |
| tooltip | tooltip.css | ⏳ | neutral |
---
collapsible: flat <Collapsible> ergonomic default + compound parts Per the doctrine update in GUIA §13: eidos for multi-part components exposes BOTH a flat default that auto-composes Provider/Trigger/Content AND the compound parts for advanced cases. Soma + morfo remain the universal composable foundation underneath. Why: with the previous "compound only" rule for multi-part, eidos collapsible was a pure pass-through that added nothing operational — the consumer wrote the same import + same shape as soma. The flat default makes eidos earn its layer by collapsing the 90% case to a single call: // 90% case — flat ergonomic <Collapsible bind:open> {#snippet trigger()}Show details{/snippet} <p>Body content.</p> </Collapsible> // Advanced — compound (parts in different subtrees, multi-trigger, // conditional content) <header><Collapsible.Provider bind:open> <Collapsible.Trigger>Show</Collapsible.Trigger> </Collapsible.Provider></header> <aside> <Collapsible.Content>...</Collapsible.Content> </aside> The architectural virtue: if the flat doesn't fit, a developer drops to soma + morfo and composes freely. No vendor lock-in in the visual layer; eidos is the design system convention, soma is the universal primitive. Files: - src/uix/eidos/components/collapsible/collapsible.svelte (NEW): flat default that auto-composes Provider + Trigger + Content via a `trigger` snippet for the toggle label and `children` for the body. - src/uix/eidos/components/collapsible/types.ts: adds `CollapsibleFlatProps = SomaCollapsibleProps & { trigger?: Snippet }`. - src/uix/eidos/components/collapsible/index.ts: exports `default` (flat) plus named `Provider`/`Trigger`/`Content` (compound). - src/uix/eidos/components/collapsible/{trigger,content,provider}.svelte: fixed children destructuring so snippets propagate cleanly to soma (was previously spreading $props() blindly which can lose snippet bindings in Svelte 5). - src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md: NEW §13 "Doctrina del API: soma compound, eidos opinionado" formalises the two-shape rule and the architectural virtue (soma+morfo as universal foundation). Renumbered §13/§14 → §14/§15. - web/routes/collapsible/+page.svelte: live preview now uses the flat form; eidos snippet shows the flat shape; soma snippet keeps the compound shape; Notes tab updated. - src/uix/eidos/components/collapsible/README.md: rewrote API section with both shapes + the "if neither fits, use soma+morfo" escape. Tests 218/218 green. npm run check baseline 39. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
## 15. Reglas invariantes
sema/morfo/eidos: align with GUIA_IMPLEMENTACION_SEMAUIX (canonical guide) The new doctrinal guide at src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md supersedes src/docs/sema-implementation-guide.md and locks the canonical vocabulary, event shape and color tokens. This commit aligns the codebase to that canon in three concrete moves. Phase 1 — sema/verbs.ts vocabulary: - Restructured from flat array to family-keyed Record per the guide. - Moved select / toggle / acknowledge → commit (these fix state, not contact). Removed edit from handle (it's shift.enter-mode now). - Added new verbs per the canon: contact (tap, focus, trigger, release), commit (complete, restore, expire, set, remove, reorder), signal (remind), handle (rotate, scroll, reorder), shift (route, step, return, context), sustain (start, loading, waiting, syncing, processing, streaming, pending, retrying, end). - validateEventName now recognises both naming shapes: {verb}-{variant} (head=verb) and {family}-{verb} (head=family). - New helper familyForVerb. Tests rewritten — 16/16 green. Phase 2 — morfo event shape: - target moved from event-level into event.semantic. Adds optional semantic.verb (advisory, validated against SEMA_VERBS[family]) and optional semantic.sequence ('pre' | 'coincident' | 'post'). - compile.ts and schema.ts updated. The 22 events across toggle, toast, popover, drawer, dialog refactored to the new shape with explicit verb + sequence. - Polymorphic capability (allowedFamilies + defaultSemantic) and a11ySemantic deferred — no current consumer needs them; will land when the first concrete usage appears. Phase 5 — color tokens (doctrinal 8): - themes/base/light.css and dark.css rewritten to expose primary, secondary, neutral, affirm, fulfill, risk, threat, loss. Renames success→fulfill, warning→risk, danger→threat (same hex). New primitives for secondary (slate-blue), affirm (teal-mint, low activation), loss (deep violet-grave, posterior). info palette deleted entirely — per guide, "info no es intent, es signal.announce + neutral". - _static.css legacy compatibility aliases (--color-bg, --color-success, --color-error, --color-accent, ...) deleted. Clean cut, no transition. Consumers reference doctrinal palettes directly. - 29 consumers (token files + recipes) migrated: - All --*-color-info-* declarations dropped. - Component palettes extended with secondary / affirm / loss. - switch + checkbox recipes updated to use [data-color='affirm'| 'risk'|'threat'|'secondary'] (was 'success'|'warning'|'danger'| 'info'). - toast tokens + recipe renamed to affirm/fulfill/risk/threat/loss (was success/error/warning/info). - meter, progress, mark, badge, button tokens renamed. - Contracts (contracts/contract.css + contracts/components/*) updated. - focus-ring-color-error in themes now points to --color-risk-border (validation errors are signal.warn + risk per doctrina, not threat). Phase 4 (partial): - src/docs/sema-implementation-guide.md deleted (superseded by the canonical guide). Tests: 217/217 green across uix. npm run check holds at the 39-error baseline (all pre-existing in unrelated test files; none introduced). Pending in follow-up commits: - Update active_architecture.md, sema/README.md, morfo/README.md, CLAUDE.md to reflect the canon. - Switch component migration to the eidos wrapper pattern. - Persistence field (untilAction / untilFix / stateBound) and holds-by-intent — defer until the first signal.warn / signal.alert consumer appears. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
1. **El intent no nace del componente.** Pero el componente debe poder recibirlo.
2. **La estética no contradice la semántica.** Libertad dentro del rango que el intent permite.
3. **Color expresa intent, no lo define.** El intent viene de la evaluación del evento.
4. **Emerge ≠ shift.** Dropdown = emerge. Modal = shift.
5. **Threat ≠ loss.** Antes de la consecuencia ≠ después de la consecuencia.
6. **Affirm ≠ fulfill.** Confirmación suave ≠ objetivo cumplido.
7. **Info no es intent.** Es signal.announce + neutral.
8. **Sustain no tiene hold fijo.** Dura mientras dure el proceso.
9. **Los canales no-visuales no leen DOM.** Reciben signal del engine.
10. **La semántica debe sobrevivir sin color, sin motion, sin sonido y sin háptica.**
---
*Documento derivado de "Semántica perceptiva de la interfaz" (Navarro Leal) y la arquitectura UIX (Morfo/Soma/Sema/Eidos).*

Powered by TurnKey Linux.