Eidos Toast
Visual wrapper over Soma Toast. Toast is a special case with two public roots:
Toast for manual compound rendering, and Toaster for the imperative
auto-mounted stack. Eidos owns the card recipe, status icon mapping and
viewport placement; Soma owns timers, queueing, hotkey, swipe, ARIA and the
imperative toaster API.
Baselines
| Platform |
Surface |
Comparison |
Air (glm-5) |
Toaster, Root, Title, Message, Description, Action, Close; position/gap, default status icon by type, enter/exit behavior cues. |
Covered and expanded. Eidos keeps Toaster, replaces legacy type with UIX intent, and uses Status/Main layout parts instead of Air's unbacked CSS classes. |
| Radix Toast |
Provider, Viewport, Root, Title, Description, Action, Close; auto-dismiss, hover/focus pause, hotkey, swipe, forceMount, foreground/background urgency. |
Covered by Soma. Urgency maps from UIX intents to status/alert; swipe CSS variables are exposed with --toast-*. |
| Ark UI Toast |
createToaster, Toaster, Root, Title, Description, Action, Close; max, placement, overlap, offsets, promise/update APIs, hotkey. |
Covered for queue/promise/update/hotkey/placement. overlap and structured offsets are deferred to layout recipes. |
| Sonner / shadcn-svelte |
Imperative toast() API and <Toaster>, positions, rich colors, actions, promise toasts. |
Covered with createToaster() + <Toaster>. Eidos uses intents instead of success/error/warning/info. |
Sources: Radix,
Ark UI,
shadcn-svelte Sonner,
Sonner.
Anatomy
Imperative Stack
<script lang="ts">
import { Toaster, createToaster } from '$uix/eidos/components/toast';
const toaster = createToaster({ duration: 5000, max: 5 });
</script>
<Toaster {toaster} position="bottom-right" />
Manual Compound
<script lang="ts">
import { Toast, createToaster } from '$uix/eidos/components/toast';
const toaster = createToaster();
</script>
<Toast {toaster}>
<Toast.Viewport position="top-right">
{#each toaster.toasts as item (item.id)}
<Toast.Item toast={item}>
<Toast.Status />
<Toast.Main>
<Toast.Title>{item.title}</Toast.Title>
<Toast.Description>{item.description}</Toast.Description>
</Toast.Main>
<Toast.Close />
</Toast.Item>
{/each}
</Toast.Viewport>
</Toast>
Decisions
| Gap / Choice |
Decision |
Air Message part |
Not restored as a separate part. Soma/Eidos use Description as the message/body; Main is the layout stack. |
Legacy success/error/warning/info |
Replaced by canonical UIX intents: neutral, affirm, fulfill, risk, threat, loss. |
Toaster attached as Toast.Toaster |
Rejected. Toaster is a competing root, not a child of Toast. |
| Viewport label default |
Lives in Soma translations (components.toast.notifications), not hardcoded in Eidos. |
Ark overlap / structured offsets |
Deferred until the visual recipe needs stacked/overlapping modes beyond position + gap. |
Visual Props
| Surface |
Prop |
Values / Type |
Effect |
Toast.Viewport / Toaster |
position |
six anchored corners/centers |
Fixed viewport placement. |
Toast.Viewport / Toaster |
gap |
`number |
string` |
Toast.Item |
toast.intent |
UIX intents |
Palette, icon and ARIA urgency. |
Toast.Item |
toast.loading |
boolean |
Pending spinner/status state. |
Ownership
- Morfo declares live-region parts, intent-driven roles, swipe attrs and
dismiss/present/announce events.
- Soma owns the toaster store, timers, pause/resume, hotkey focus, swipe
gesture, promise lifecycle and translated close/viewport labels.
- Eidos owns status glyphs, placement/gap styling,
data-icon-only close
styling and card layout.
Baseline
Referencia local: Soma + Morfo + Eidos. La capa visual de Eidos
expone size / variant / color sobre el comportamiento que Soma ya
implementa; el morfo declara parts, ARIA, keyboard y eventos sema.
Las decisiones se alinean con las bibliotecas externas listadas en
la Comparativa.
Comparativa
| Capacidad |
Bits UI |
Ark UI |
React Aria |
shadcn-svelte |
UIX |
| Surface compound (root + parts) |
✓ |
✓ |
✓ |
✓ |
✓ |
| ARIA semantics + keyboard nav |
✓ |
✓ |
✓ |
parcial |
✓ via morfo |
| Variantes visuales (size / variant) |
parcial |
parcial |
n/a |
tailwind |
✓ recipe |
| Form integration |
parcial |
parcial |
✓ |
parcial |
✓ via Field |
| Eventos sema declarativos |
n/a |
n/a |
n/a |
n/a |
✓ |
Decisiones
- El wrapper Eidos se mantiene fino: ergonomía visual + tokens.
Comportamiento y ARIA viven en Soma + Morfo.
- Strings públicos usan idlangref bajo
components.{kebab}.*,
con catálogo en src/uix/langs/components/{kebab}.ts.
- Eventos sema declarados en el morfo cubren los cambios de estado
que cargan peso perceptivo (commit, signal). Las navegaciones
internas por teclado son focus moves, no eventos.
- Cuando la API necesita comportamiento nuevo, va a Soma / Morfo
primero; Eidos sólo expone la receta visual del resultado.
Gaps
| Gap |
Disposición |
Detalle |
| API extendida sobre las referencias externas |
diferir |
Sólo si llega un caso de uso real. Mantener la superficie estable. |
| Cobertura adicional de variantes visuales |
diferir |
El recipe cubre sm/md/lg + solid/outline/ghost. Más variantes requieren caso concreto. |
| Documentación per-prop exhaustiva |
implementar |
Cuando se cierre el ciclo de remediación de cada componente. |
| Tests browser-level del flujo completo (Playwright) |
implementar |
Cobertura visual + interacciones. Se hace en una pasada conjunta de tests. |