diff --git a/src/uix/eidos/ARCHETYPE_COHERENCE_AUDIT_2026-06-19.md b/src/uix/eidos/ARCHETYPE_COHERENCE_AUDIT_2026-06-19.md index a84e3f298..7fcc53d20 100644 --- a/src/uix/eidos/ARCHETYPE_COHERENCE_AUDIT_2026-06-19.md +++ b/src/uix/eidos/ARCHETYPE_COHERENCE_AUDIT_2026-06-19.md @@ -31,6 +31,36 @@ consuman por defecto**. --- +## ESTADO DE IMPLEMENTACIÓN — hand-off 2026-06-20 + +**Hecho hoy (sobre el A1 de ayer):** +- **A1 piloto dialog + drawer (plano `modal`)** — `data-depth="modal"` en ambos `Content`; + surface·border·base-shadow vienen del plano; recipes podados (`content-bg/border/ + border-width/shadow` huérfanos; el drawer conserva `content-bg` = gap del focus-ring + + `content-shadow-dragging`). El **on-surface font** del bundle (Decisión 8) arregla el + Times New Roman de contenidos portalizados. +- **Norma contenedor→parte: cap en `md`** (THEMING §5). `Dialog.Close` hereda el size del + dialog vía `context.ts` capando en `md` (sm→sm; md/lg/xl/full→md — `full` es layout, no + control mayor; alineado Radix/Mantine/MD3). Verificado runtime. +- **Dialog title → rol `h3`** (Arq. 5): el recipe apunta `--dialog-title-*` a `--style-h3-*` + (perilla de override viva); mueve el título de Lora (off-scale) a `primary` (sans). +- **Dialog trigger + close = el Button del framework** (patrón `asChild`): el wrapper eidos + del **trigger era passthrough** → renderizaba el ` {/if} diff --git a/src/uix/eidos/components/dialog/dialog-content.svelte b/src/uix/eidos/components/dialog/dialog-content.svelte index c448c32d1..f7b231e6e 100644 --- a/src/uix/eidos/components/dialog/dialog-content.svelte +++ b/src/uix/eidos/components/dialog/dialog-content.svelte @@ -17,6 +17,7 @@ import { ActiveEidos } from '$uix/eidos'; import { composeInlineStyle } from '$uix/eidos/lib/style'; import * as Dialog from '$soma/components/dialog'; + import { setDialogEidosCtx } from './context'; import type { DialogContentProps } from './types'; // `children` is renamed to `bodyContent` so the inner `{#snippet children}` @@ -41,6 +42,13 @@ const eidos = ActiveEidos.require(); const resolvedSize = $derived(eidos.resolve(size, 'md')); + // Publish the resolved size so the parts the dialog owns (close, footer + // actions) follow it instead of hardcoding their own — see context.ts. + setDialogEidosCtx({ + get size() { + return resolvedSize; + } + }); const resolvedPosition = $derived(eidos.resolve(position, 'middle-center')); const isSheet = $derived(resolvedSize !== 'full' && eidos.isBelow('sm')); @@ -81,6 +89,7 @@ data-size={resolvedSize} data-position={resolvedPosition} data-sheet={isSheet ? '' : undefined} + data-depth="modal" data-animation-style={motion === 'none' ? undefined : motion} > {#snippet children(snippetProps)} diff --git a/src/uix/eidos/components/dialog/dialog-trigger.svelte b/src/uix/eidos/components/dialog/dialog-trigger.svelte index 728f98447..1f4c7b881 100644 --- a/src/uix/eidos/components/dialog/dialog-trigger.svelte +++ b/src/uix/eidos/components/dialog/dialog-trigger.svelte @@ -1,10 +1,27 @@ - {@render children?.()} + {#snippet child({ props })} + {#if outerChild} + {@render outerChild({ props })} + {:else} + + {/if} + {/snippet} diff --git a/src/uix/eidos/components/dialog/dialog.css b/src/uix/eidos/components/dialog/dialog.css index 12b0c2cc7..b0b0a779d 100644 --- a/src/uix/eidos/components/dialog/dialog.css +++ b/src/uix/eidos/components/dialog/dialog.css @@ -100,11 +100,12 @@ max-height: var(--_dialog-content-max-height-override, var(--dialog-content-max-height)); padding: var(--_dialog-padding); overflow: auto; - border: var(--dialog-content-border-width) solid var(--dialog-content-border); + /* Elevation bundle (surface · border · shadow) comes from the `modal` plane + via `data-depth` (A1, Decisión 8). The panel keeps only its own radius / + color — radius is a separate axis (Radix factor, A2). The intent variants + below override `border-color` on top of the plane's border. */ border-radius: var(--dialog-content-radius); - background: var(--dialog-content-bg); color: var(--dialog-content-color); - box-shadow: var(--dialog-content-shadow); outline: none; } @@ -238,9 +239,7 @@ * a dialog at all. Each intent tints the panel border and (for evaluative * intents) the title color. The body background stays neutral so long-form * content doesn't compete with the intent signal. */ -[data-dialog-content][data-color='neutral'] { - border-color: var(--dialog-content-border); -} +/* neutral = the plane's own border (`--depth-modal-border`); no override needed. */ [data-dialog-content][data-color='risk'] { border-color: var(--color-risk-border); @@ -294,10 +293,17 @@ [data-dialog-title] { margin: 0; + /* Typography role (Arq. 5 / THEMING §3): the title reads its own + `--dialog-title-*` knobs, which the recipe defaults to the canonical `h3` + heading role (primary/sans · lg · semibold). The role gives coherence by + default; the `--dialog-title-*` tokens stay the override surface — a theme, + the recipe config, or one `` can restyle dialog titles + WITHOUT retuning every `h3`. The intent tints below still override color. */ font-family: var(--dialog-title-font-family); font-size: var(--dialog-title-font-size); font-weight: var(--dialog-title-font-weight); line-height: var(--dialog-title-line-height); + letter-spacing: var(--dialog-title-letter-spacing); color: var(--dialog-title-color); text-wrap: balance; } diff --git a/src/uix/eidos/components/dialog/types.ts b/src/uix/eidos/components/dialog/types.ts index ecdc3b204..cb761d65a 100644 --- a/src/uix/eidos/components/dialog/types.ts +++ b/src/uix/eidos/components/dialog/types.ts @@ -31,7 +31,21 @@ export type DialogPosition = Position; export type DialogCssLength = string | number; export type DialogProps = ProviderProps; -export type DialogTriggerProps = TriggerProps; + +export type DialogTriggerProps = TriggerProps & { + /** + * Visual variant of the underlying button. The trigger composes the canonical + * `