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/uix/eidos/events.css

202 lines
6.5 KiB

/**
* Eidos — reactions to perceptual signals (`data-event*`).
*
* The VisualChannel of Sema writes signal attrs under the `data-event-*`
* namespace during a configurable hold window:
* - data-event (event name, e.g. 'announce', 'dismiss')
* - data-event-id (occurrence id from the engine)
* - data-event-phase ('active')
* - data-event-family (optional, e.g. 'signal')
* - data-event-intent (optional, e.g. 'loss')
*
* The channel never touches state attrs (`data-state`, `data-intent`,
* `data-disabled`, ...) — those are owned by the runtime/morfo. Read
* `data-event-intent` for signal-bound intent reactions; read
* `data-intent` for the persistent state of a component.
*
* Hold defaults per family (internal to chans/visual.ts):
* - emerge / commit / handle: 240ms
* - signal / shift / sustain: 600ms
* - contact: 120ms
* Authors override per signal via `signal.hold`, or globally via
* `new EngineSemantic({ visual: { defaultHold } })`.
*
* Even with the configured hold, prefer `animation: @keyframes` over
* `transition` for the visible response: the animation runs to completion
* independent of the signal's lifetime, so it works correctly with custom
* holds and won't reverse mid-flight if the signal is cleared early.
*
* Rule of thumb:
* - Use `animation: @keyframes` for visible reactions to signals.
* - Use `transition` for ongoing state attrs (data-state, data-disabled).
*/
/* ── Keyframes ──────────────────────────────────────────────────────────── */
@keyframes eidos-announce-pulse-neutral {
0%,
100% {
box-shadow: 0 0 0 0 transparent;
}
20% {
box-shadow: 0 0 0 var(--focus-ring-width) var(--color-neutral-element);
}
}
@keyframes eidos-announce-pulse-affirm {
0%,
100% {
box-shadow: 0 0 0 0 transparent;
}
20% {
box-shadow: 0 0 0 var(--focus-ring-width) var(--color-fulfill-element);
}
}
@keyframes eidos-announce-pulse-fulfill {
0%,
100% {
box-shadow: 0 0 0 0 transparent;
}
20% {
box-shadow: 0 0 0 var(--focus-ring-width) var(--color-fulfill-element);
}
}
@keyframes eidos-announce-pulse-risk {
0%,
100% {
box-shadow: 0 0 0 0 transparent;
}
15% {
box-shadow: 0 0 0 4px var(--color-risk-element);
}
30% {
box-shadow: 0 0 0 2px var(--color-risk-element);
}
}
@keyframes eidos-announce-pulse-threat {
0%,
100% {
box-shadow: 0 0 0 0 transparent;
}
10% {
box-shadow: 0 0 0 6px var(--color-threat-element);
}
35% {
box-shadow: 0 0 0 3px var(--color-threat-element);
}
}
@keyframes eidos-dismiss-fade {
to {
opacity: 0;
transform: translateX(8%);
}
}
@keyframes eidos-present-rise {
from {
opacity: 0;
transform: translateY(8px);
}
}
/* contact family — brief squeeze on press, ~120ms */
@keyframes eidos-press-squeeze {
0% {
transform: scale(1);
}
40% {
transform: scale(0.96);
filter: brightness(0.96);
}
100% {
transform: scale(1);
}
}
/* commit family — small settle bump as the new state lands, ~240ms */
@keyframes eidos-commit-settle {
0% {
box-shadow: 0 0 0 0 rgba(99, 102, 241, 0);
}
30% {
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.32);
}
100% {
box-shadow: 0 0 0 0 rgba(99, 102, 241, 0);
}
}
/* ── Base: any event signal during its active phase ──────────────────────
* Hint to the compositor; cleared automatically when the signal disappears.
*/
[data-event][data-event-phase='active'] {
will-change: opacity, transform, box-shadow;
}
/* ── Dismiss family — fade + slide out (animation runs 320ms) ──────── */
[data-event^='dismiss'][data-event-phase='active'],
[data-event^='close'][data-event-phase='active'] {
animation: eidos-dismiss-fade var(--duration-slow) var(--ease-default) forwards;
}
/* ── Present / open — rise into place ─────────────────────────────── */
[data-event^='present'][data-event-phase='active'],
[data-event^='open'][data-event-phase='active'] {
animation: eidos-present-rise var(--duration-slow) var(--ease-out);
}
/* ── Announce — intent-tinted pulse (visible 600-1000ms) ────────────
* Reads data-event-intent (signal-bound), NOT data-intent (state) —
* the channel writes only its own namespace.
*/
[data-event^='announce'][data-event-phase='active'][data-event-intent='neutral'] {
animation: eidos-announce-pulse-neutral 600ms var(--ease-default);
}
[data-event^='announce'][data-event-phase='active'][data-event-intent='affirm'] {
animation: eidos-announce-pulse-affirm 600ms var(--ease-default);
}
[data-event^='announce'][data-event-phase='active'][data-event-intent='fulfill'] {
animation: eidos-announce-pulse-fulfill 600ms var(--ease-default);
}
[data-event^='announce'][data-event-phase='active'][data-event-intent='risk'] {
animation: eidos-announce-pulse-risk 800ms var(--ease-spring);
}
[data-event^='announce'][data-event-phase='active'][data-event-intent='threat'] {
animation: eidos-announce-pulse-threat 1000ms var(--ease-spring);
}
/* ── Press / contact — quick squeeze acknowledgement ─────────────────
* Fired on any control whose morfo declares a `contact` event (toggle,
* switch, button…). Brief (~120ms), non-valenced. The sema visual
* channel writes data-event-family='contact' during the hold.
*/
[data-event-family='contact'][data-event-phase='active'] {
animation: eidos-press-squeeze 140ms var(--ease-default);
}
/* ── Commit — consolidation pulse on the landing of a new state ──────
* Fired by morfos that declare a `commit` event (toggle press, switch
* change, dialog close-save, etc.). The pulse uses the indigo accent;
* intent variants below tint by valence.
*/
[data-event-family='commit'][data-event-phase='active'] {
animation: eidos-commit-settle 260ms var(--ease-out);
}
[data-event-family='commit'][data-event-intent='fulfill'][data-event-phase='active'] {
animation: eidos-announce-pulse-fulfill 320ms var(--ease-out);
}
[data-event-family='commit'][data-event-intent='affirm'][data-event-phase='active'] {
animation: eidos-announce-pulse-affirm 320ms var(--ease-out);
}
[data-event-family='commit'][data-event-intent='threat'][data-event-phase='active'] {
animation: eidos-announce-pulse-threat 400ms var(--ease-spring);
}
/* `data-last-action` tinting lives in component recipes (e.g.
* dialog.css), not here. If a future second consumer appears with the
* same exit-tint pattern, factor out then — not before. */

Powered by TurnKey Linux.