|
|
|
|
|
/**
|
|
|
|
|
|
* Eidos — Dialog component recipe.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Eidos applies universally to the data-attrs the dialog morfo emits. Tokens
|
|
|
|
|
|
* follow the bare-prefixed convention (`--dialog-*` public, `--_dialog-*`
|
|
|
|
|
|
* internal — see `eidos/components/README.md`). No `air-` / `eidos-`
|
|
|
|
|
|
* keyframe prefixes either.
|
|
|
|
|
|
*
|
|
|
|
|
|
* The morfo declares `data-last-action` as a prewrite on every close-* event,
|
|
|
|
|
|
* written BEFORE the `data-state` flips to 'closed'. The exit border-top is
|
|
|
|
|
|
* tinted by causa during the closing animation. See the data-last-action
|
|
|
|
|
|
* block at the bottom of this file.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/* ── Trigger ───────────────────────────────────────────────────────────────
|
|
|
|
|
|
* The trigger composes the framework `<Button>` (eidos `dialog-trigger.svelte`
|
|
|
|
|
|
* renders `<Button {...props}>` via soma's `child`), so ALL its chrome —
|
|
|
|
|
|
* layout, bg, hover, focus-ring, disabled — comes from the Button recipe. No
|
|
|
|
|
|
* bespoke `[data-dialog-trigger]` envelope here: it would paint the SAME
|
|
|
|
|
|
* element as `[data-button]` and fight it (the Close recipe is the model).
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/* ── Overlay ───────────────────────────────────────────────────────────── */
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-overlay] {
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
inset: 0;
|
|
|
|
|
|
background: color-mix(
|
|
|
|
|
|
in srgb,
|
|
|
|
|
|
var(--dialog-overlay-bg) var(--dialog-overlay-opacity),
|
|
|
|
|
|
transparent
|
|
|
|
|
|
);
|
|
|
|
|
|
backdrop-filter: blur(var(--dialog-overlay-blur));
|
|
|
|
|
|
z-index: var(--dialog-overlay-z);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
feat(motion): motion engine as arts/motion service + F6 tokens + F7 typegen
Relocate the motion runtime out of eidos into a runtime art (src/arts/motion,
$motion), exposed as uix.motion and consumed by BOTH soma (Presence.motion ->
motion.run) and eidos (delegates + registers presets) -- dissolving the
soma->eidos coupling. Remove DialogProps.runMotion / eidos.motionRunner; the
bridge is now EngineMotion.run (reads data-animation-style). Delete the 4
relocated dead files (lib/motion/{types,runtime,runner,presets/js}.ts); the
preset DATA (presets/css.ts) stays in eidos. Regenerate generated/base.css.
F6 - token rigor (Carbon): tokenize the raw firma durations (slower/deliberate/
emphatic/sustained holds, escalating by announce intent severity), add
--motion-distance-xl (30px shared-axis), --motion-scale-through (0.92), the
emphasized easing, and productive/expressive sets ([data-motion-set=expressive]).
F7 - extensibility + typegen: app-extensible, type-safe preset-name registry
(EidosMotionPresets, mirroring SemaChannelSignatures); MotionPresetName =
keyof EidosMotionPresets | none | (string & {}).
Also sweeps other in-progress working-tree edits (web/routes/temas/grafito).
Verify: npm run check -> 1 pre-existing error (grafito), 0 new; motion 22/22,
active-uix 25/25, Presence 2/2, Dialog 3/3. Pre-existing words-track failures
unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4 months ago
|
|
|
|
/* Overlay + content enter/exit motion comes from the motion system (presets
|
|
|
|
|
|
* `fade` / `scale-fade` via `data-animation-style`). `data-state` here is only
|
feat(eidos): canonize theming scales + tokenize magic numbers
Audit-driven canonization of the eidos theming layer: a canonical scale that
components bypass with literals drifts into N variants. Every axis is now
retunable-by-theme AND consumed via token, never a bare literal.
Bloque A/B (scales): --blur-* (Tailwind-aligned, depth planes consume it);
inner-shadow --shadow-inset-* (mode-aware) for the recessed plane; gradient
angle/named tokens; --breakpoint-* sourced from ActiveDom (runtime, dev-settable)
+ container queries; opacity dual numeric+semantic scale; border-width
none/thin/medium/thick/heavy (adds real 3px); tracking caps/widest. Fase 7:
3 size archetypes documented + coherence guard (no px/rem in recipe
font-size/icon-size).
Bloque C (magic numbers): z-index 80/50/99 (combobox/nav-menu/drag-drop) ->
recipe content-z/preview-z tokens (overlay micro-band soma mirrors); on-scale
durations -> var(--duration-*) (dialog fast/slow, card slow); 12 single
border/ring widths -> var(--border-width-*), value-preserving. Off-scale kept
only as justified recipe tokens (continuous spinner/loading periods, sub-fast
press). Self-contained dimensional scales (avatar ring, ring-thickness) left whole.
Docs: THEMING.md SS35 + SS6 + SS29, THEMING_NOTES, README, TSC. Excludes
words/palabras/chronos (active dev tracks).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4 months ago
|
|
|
|
* steady styling. Asymmetric timing — `fast` in / `slow` out — drawn from the
|
|
|
|
|
|
* canonical duration scale. See `eidos-motion.md`. */
|
feat(motion): motion engine as arts/motion service + F6 tokens + F7 typegen
Relocate the motion runtime out of eidos into a runtime art (src/arts/motion,
$motion), exposed as uix.motion and consumed by BOTH soma (Presence.motion ->
motion.run) and eidos (delegates + registers presets) -- dissolving the
soma->eidos coupling. Remove DialogProps.runMotion / eidos.motionRunner; the
bridge is now EngineMotion.run (reads data-animation-style). Delete the 4
relocated dead files (lib/motion/{types,runtime,runner,presets/js}.ts); the
preset DATA (presets/css.ts) stays in eidos. Regenerate generated/base.css.
F6 - token rigor (Carbon): tokenize the raw firma durations (slower/deliberate/
emphatic/sustained holds, escalating by announce intent severity), add
--motion-distance-xl (30px shared-axis), --motion-scale-through (0.92), the
emphasized easing, and productive/expressive sets ([data-motion-set=expressive]).
F7 - extensibility + typegen: app-extensible, type-safe preset-name registry
(EidosMotionPresets, mirroring SemaChannelSignatures); MotionPresetName =
keyof EidosMotionPresets | none | (string & {}).
Also sweeps other in-progress working-tree edits (web/routes/temas/grafito).
Verify: npm run check -> 1 pre-existing error (grafito), 0 new; motion 22/22,
active-uix 25/25, Presence 2/2, Dialog 3/3. Pre-existing words-track failures
unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4 months ago
|
|
|
|
[data-dialog-overlay],
|
|
|
|
|
|
[data-dialog-content] {
|
feat(eidos): canonize theming scales + tokenize magic numbers
Audit-driven canonization of the eidos theming layer: a canonical scale that
components bypass with literals drifts into N variants. Every axis is now
retunable-by-theme AND consumed via token, never a bare literal.
Bloque A/B (scales): --blur-* (Tailwind-aligned, depth planes consume it);
inner-shadow --shadow-inset-* (mode-aware) for the recessed plane; gradient
angle/named tokens; --breakpoint-* sourced from ActiveDom (runtime, dev-settable)
+ container queries; opacity dual numeric+semantic scale; border-width
none/thin/medium/thick/heavy (adds real 3px); tracking caps/widest. Fase 7:
3 size archetypes documented + coherence guard (no px/rem in recipe
font-size/icon-size).
Bloque C (magic numbers): z-index 80/50/99 (combobox/nav-menu/drag-drop) ->
recipe content-z/preview-z tokens (overlay micro-band soma mirrors); on-scale
durations -> var(--duration-*) (dialog fast/slow, card slow); 12 single
border/ring widths -> var(--border-width-*), value-preserving. Off-scale kept
only as justified recipe tokens (continuous spinner/loading periods, sub-fast
press). Self-contained dimensional scales (avatar ring, ring-thickness) left whole.
Docs: THEMING.md SS35 + SS6 + SS29, THEMING_NOTES, README, TSC. Excludes
words/palabras/chronos (active dev tracks).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4 months ago
|
|
|
|
--motion-duration-enter: var(--duration-fast);
|
|
|
|
|
|
--motion-duration-exit: var(--duration-slow);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ── Content ───────────────────────────────────────────────────────────── */
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content] {
|
|
|
|
|
|
--_dialog-size-width: var(--dialog-content-width-md);
|
|
|
|
|
|
--_dialog-padding: var(--dialog-content-padding-md);
|
|
|
|
|
|
--_dialog-width: var(--_dialog-content-width-override, var(--_dialog-size-width));
|
|
|
|
|
|
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
left: 50%;
|
|
|
|
|
|
top: 50%;
|
|
|
|
|
|
translate: -50% -50%;
|
|
|
|
|
|
z-index: calc(var(--dialog-overlay-z) + 1);
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: var(--dialog-stack-gap);
|
|
|
|
|
|
width: min(calc(100vw - var(--dialog-content-width-inset)), var(--_dialog-width));
|
|
|
|
|
|
min-width: var(--_dialog-content-min-width-override, auto);
|
|
|
|
|
|
max-width: var(--_dialog-content-max-width-override, none);
|
|
|
|
|
|
height: var(--_dialog-content-height-override, auto);
|
|
|
|
|
|
min-height: var(--_dialog-content-min-height-override, auto);
|
|
|
|
|
|
max-height: var(--_dialog-content-max-height-override, var(--dialog-content-max-height));
|
|
|
|
|
|
padding: var(--_dialog-padding);
|
|
|
|
|
|
overflow: auto;
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
color: var(--dialog-content-color);
|
|
|
|
|
|
outline: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
feat(motion): motion engine as arts/motion service + F6 tokens + F7 typegen
Relocate the motion runtime out of eidos into a runtime art (src/arts/motion,
$motion), exposed as uix.motion and consumed by BOTH soma (Presence.motion ->
motion.run) and eidos (delegates + registers presets) -- dissolving the
soma->eidos coupling. Remove DialogProps.runMotion / eidos.motionRunner; the
bridge is now EngineMotion.run (reads data-animation-style). Delete the 4
relocated dead files (lib/motion/{types,runtime,runner,presets/js}.ts); the
preset DATA (presets/css.ts) stays in eidos. Regenerate generated/base.css.
F6 - token rigor (Carbon): tokenize the raw firma durations (slower/deliberate/
emphatic/sustained holds, escalating by announce intent severity), add
--motion-distance-xl (30px shared-axis), --motion-scale-through (0.92), the
emphasized easing, and productive/expressive sets ([data-motion-set=expressive]).
F7 - extensibility + typegen: app-extensible, type-safe preset-name registry
(EidosMotionPresets, mirroring SemaChannelSignatures); MotionPresetName =
keyof EidosMotionPresets | none | (string & {}).
Also sweeps other in-progress working-tree edits (web/routes/temas/grafito).
Verify: npm run check -> 1 pre-existing error (grafito), 0 new; motion 22/22,
active-uix 25/25, Presence 2/2, Dialog 3/3. Pre-existing words-track failures
unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4 months ago
|
|
|
|
/* Content enter/exit motion comes from the motion system (preset `scale-fade`
|
|
|
|
|
|
* via `data-animation-style`). Soma's Presence waits for `getAnimations()`
|
|
|
|
|
|
* before unmounting, so the preset animation gates the cycle. `data-state` is
|
|
|
|
|
|
* steady styling only. */
|
|
|
|
|
|
|
|
|
|
|
|
/* ── Position (3×3 grid) ────────────────────────────────────────────────
|
|
|
|
|
|
* The default `[data-dialog-content]` rule above already centers the panel
|
|
|
|
|
|
* (`left/top: 50%; translate: -50% -50%;`) — that is the implicit
|
|
|
|
|
|
* `middle-center` form. The selectors below override the anchoring axes
|
|
|
|
|
|
* for the other 8 cells. `data-size='full'` and `data-sheet` come AFTER
|
|
|
|
|
|
* these in the cascade and win when applicable. */
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content][data-position='top-left'] {
|
|
|
|
|
|
top: var(--dialog-content-position-inset);
|
|
|
|
|
|
left: var(--dialog-content-position-inset);
|
|
|
|
|
|
right: auto;
|
|
|
|
|
|
bottom: auto;
|
|
|
|
|
|
translate: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content][data-position='top-center'] {
|
|
|
|
|
|
top: var(--dialog-content-position-inset);
|
|
|
|
|
|
left: 50%;
|
|
|
|
|
|
right: auto;
|
|
|
|
|
|
bottom: auto;
|
|
|
|
|
|
translate: -50% 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content][data-position='top-right'] {
|
|
|
|
|
|
top: var(--dialog-content-position-inset);
|
|
|
|
|
|
right: var(--dialog-content-position-inset);
|
|
|
|
|
|
left: auto;
|
|
|
|
|
|
bottom: auto;
|
|
|
|
|
|
translate: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content][data-position='middle-left'] {
|
|
|
|
|
|
top: 50%;
|
|
|
|
|
|
left: var(--dialog-content-position-inset);
|
|
|
|
|
|
right: auto;
|
|
|
|
|
|
bottom: auto;
|
|
|
|
|
|
translate: 0 -50%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* `middle-center` is the default — no override needed. */
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content][data-position='middle-right'] {
|
|
|
|
|
|
top: 50%;
|
|
|
|
|
|
right: var(--dialog-content-position-inset);
|
|
|
|
|
|
left: auto;
|
|
|
|
|
|
bottom: auto;
|
|
|
|
|
|
translate: 0 -50%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content][data-position='bottom-left'] {
|
|
|
|
|
|
bottom: var(--dialog-content-position-inset);
|
|
|
|
|
|
left: var(--dialog-content-position-inset);
|
|
|
|
|
|
top: auto;
|
|
|
|
|
|
right: auto;
|
|
|
|
|
|
translate: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content][data-position='bottom-center'] {
|
|
|
|
|
|
bottom: var(--dialog-content-position-inset);
|
|
|
|
|
|
left: 50%;
|
|
|
|
|
|
top: auto;
|
|
|
|
|
|
right: auto;
|
|
|
|
|
|
translate: -50% 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content][data-position='bottom-right'] {
|
|
|
|
|
|
bottom: var(--dialog-content-position-inset);
|
|
|
|
|
|
right: var(--dialog-content-position-inset);
|
|
|
|
|
|
top: auto;
|
|
|
|
|
|
left: auto;
|
|
|
|
|
|
translate: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ── Sizing ────────────────────────────────────────────────────────────── */
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content][data-size='sm'] {
|
|
|
|
|
|
--_dialog-size-width: var(--dialog-content-width-sm);
|
|
|
|
|
|
--_dialog-padding: var(--dialog-content-padding-sm);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content][data-size='md'] {
|
|
|
|
|
|
--_dialog-size-width: var(--dialog-content-width-md);
|
|
|
|
|
|
--_dialog-padding: var(--dialog-content-padding-md);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content][data-size='lg'] {
|
|
|
|
|
|
--_dialog-size-width: var(--dialog-content-width-lg);
|
|
|
|
|
|
--_dialog-padding: var(--dialog-content-padding-lg);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content][data-size='xl'] {
|
|
|
|
|
|
--_dialog-size-width: var(--dialog-content-width-xl);
|
|
|
|
|
|
--_dialog-padding: var(--dialog-content-padding-full);
|
|
|
|
|
|
border-radius: var(--dialog-content-full-radius);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content][data-size='full'] {
|
|
|
|
|
|
inset: var(--dialog-content-full-inset);
|
|
|
|
|
|
translate: none;
|
|
|
|
|
|
width: var(--_dialog-content-width-override, auto);
|
|
|
|
|
|
border-radius: var(--dialog-content-full-radius);
|
|
|
|
|
|
--_dialog-padding: var(--dialog-content-padding-full);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Auto-sheet: the eidos wrapper sets `data-sheet=""` on Content when the
|
|
|
|
|
|
* viewport is narrower than the `sm` breakpoint AND the requested size is
|
|
|
|
|
|
* not `full`. Bottom-anchored, full-width, top-rounded. */
|
|
|
|
|
|
[data-dialog-content][data-sheet] {
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
top: auto;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
translate: none;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
max-height: var(--dialog-content-max-height-sheet);
|
|
|
|
|
|
border-radius: var(--dialog-content-radius) var(--dialog-content-radius) 0 0;
|
|
|
|
|
|
--_dialog-padding: var(--dialog-content-padding-sm);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ── Color (intent → palette) ──────────────────────────────────────────────
|
|
|
|
|
|
* Modal subset of the 8 system tokens (canon §3.1). Soma resolves the
|
|
|
|
|
|
* consumer's `intent` prop to `data-color`. The subset is intentionally
|
|
|
|
|
|
* tight: a dialog is not a hierarchy and irreversible loss should not be
|
|
|
|
|
|
* 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. */
|
|
|
|
|
|
/* neutral = the plane's own border (`--depth-modal-border`); no override needed. */
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content][data-color='risk'] {
|
|
|
|
|
|
border-color: var(--color-risk-border);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content][data-color='risk'] [data-dialog-title] {
|
|
|
|
|
|
color: var(--color-risk-text);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content][data-color='threat'] {
|
|
|
|
|
|
border-color: var(--color-threat-border);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content][data-color='threat'] [data-dialog-title] {
|
|
|
|
|
|
color: var(--color-threat-text);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ── Layout shells (eidos-only, no morfo backing) ──────────────────────── */
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-header] {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: start;
|
|
|
|
|
|
gap: var(--dialog-header-gap);
|
|
|
|
|
|
/* Reserve space on the trailing edge so a top-right close doesn't
|
|
|
|
|
|
* collide with title text. The padding flips when a close is anchored
|
|
|
|
|
|
* top-left via the rules below. */
|
|
|
|
|
|
padding-inline-end: calc(var(--dialog-close-size) + var(--space-2));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content]:has([data-dialog-close][data-position^='top-left']) [data-dialog-header] {
|
|
|
|
|
|
padding-inline-end: 0;
|
|
|
|
|
|
padding-inline-start: calc(var(--dialog-close-size) + var(--space-2));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-content]:has([data-dialog-close][data-position^='bottom-']) [data-dialog-header],
|
|
|
|
|
|
[data-dialog-content]:has([data-dialog-close][data-position='top-center']) [data-dialog-header] {
|
|
|
|
|
|
padding-inline: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-footer] {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: end;
|
|
|
|
|
|
gap: var(--dialog-footer-gap);
|
|
|
|
|
|
margin-top: var(--dialog-footer-margin-top);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ── Title / Description ───────────────────────────────────────────────── */
|
|
|
|
|
|
|
|
|
|
|
|
[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 `<Dialog.Content style>` 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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[data-dialog-description] {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
font-family: var(--dialog-description-font-family);
|
|
|
|
|
|
font-size: var(--dialog-description-font-size);
|
|
|
|
|
|
line-height: var(--dialog-description-line-height);
|
|
|
|
|
|
color: var(--dialog-description-color);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ── Close ─────────────────────────────────────────────────────────────────
|
|
|
|
|
|
* The close composes the canonical `<Button>` / `<IconButton>` (eidos
|
|
|
|
|
|
* `dialog-close.svelte`), so its chrome — layout, bg, hover, focus-ring,
|
|
|
|
|
|
* disabled, icon-only sizing — comes from the Button recipe. This recipe owns
|
|
|
|
|
|
* ONLY the dialog-specific concern: floating the close over Content when the
|
|
|
|
|
|
* consumer assigns `data-position`. Without `data-position` the button flows
|
|
|
|
|
|
* inline (e.g. a <Dialog.Close> in a Footer). */
|
|
|
|
|
|
[data-dialog-close][data-position] {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ── Close position (subset of canonical Position — corners + top/bottom centers) ── */
|
|
|
|
|
|
/* Default: top-right (matches the eidos wrapper's `closePosition` default). */
|
|
|
|
|
|
[data-dialog-close][data-position='top-right'] {
|
|
|
|
|
|
top: var(--dialog-close-inset);
|
|
|
|
|
|
right: var(--dialog-close-inset);
|
|
|
|
|
|
}
|
|
|
|
|
|
[data-dialog-close][data-position='top-left'] {
|
|
|
|
|
|
top: var(--dialog-close-inset);
|
|
|
|
|
|
left: var(--dialog-close-inset);
|
|
|
|
|
|
}
|
|
|
|
|
|
[data-dialog-close][data-position='top-center'] {
|
|
|
|
|
|
top: var(--dialog-close-inset);
|
|
|
|
|
|
left: 50%;
|
|
|
|
|
|
translate: -50% 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
[data-dialog-close][data-position='bottom-right'] {
|
|
|
|
|
|
bottom: var(--dialog-close-inset);
|
|
|
|
|
|
right: var(--dialog-close-inset);
|
|
|
|
|
|
}
|
|
|
|
|
|
[data-dialog-close][data-position='bottom-left'] {
|
|
|
|
|
|
bottom: var(--dialog-close-inset);
|
|
|
|
|
|
left: var(--dialog-close-inset);
|
|
|
|
|
|
}
|
|
|
|
|
|
[data-dialog-close][data-position='bottom-center'] {
|
|
|
|
|
|
bottom: var(--dialog-close-inset);
|
|
|
|
|
|
left: 50%;
|
|
|
|
|
|
translate: -50% 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ── data-last-action exit tinting ─────────────────────────────────────────
|
|
|
|
|
|
* The dialog morfo declares `prewrite` on every close-* event that writes
|
|
|
|
|
|
* `data-last-action` before `data-state` flips to 'closed'. Both attrs
|
|
|
|
|
|
* coexist during the exit animation; CSS tints the border-top by causa.
|
|
|
|
|
|
*/
|
|
|
|
|
|
[data-dialog-content][data-state='closed'][data-last-action='saved'] {
|
|
|
|
|
|
border-top-color: var(--color-fulfill-element);
|
|
|
|
|
|
}
|
|
|
|
|
|
[data-dialog-content][data-state='closed'][data-last-action='failed'] {
|
|
|
|
|
|
border-top-color: var(--color-threat-element);
|
|
|
|
|
|
}
|
|
|
|
|
|
[data-dialog-content][data-state='closed'][data-last-action='cancelled'],
|
|
|
|
|
|
[data-dialog-content][data-state='closed'][data-last-action='dismissed'],
|
|
|
|
|
|
[data-dialog-content][data-state='closed'][data-last-action='dismissed-outside'] {
|
|
|
|
|
|
border-top-color: var(--color-neutral-element);
|
|
|
|
|
|
}
|