The universal selector for the CONTENT domain (RFC §D.12). `motionAttrs(preset)`
returns the attrs that make ANY element play a registered preset's enter on mount:
<div {...motionAttrs('scale-fade')}>…</div> // fades + scales in on mount
Resolves the open "how does content fire" decision — and reverses the §D.12 plan's
guess. Instead of a new `data-motion-play` trigger (which would need a generator
change + a base.css regen, currently entangled with an unrelated `press`/chronos
WIP), it reuses a constant presentation `data-state="open"` — the same mechanism
`<Cascade.Item>` already uses for content. The event/state/content line is about
who OWNS the animation (firma / state-machine / the prop directly), not about
whether the CSS trigger is `data-state`: content is "always shown" with no machine
to flip it. Reuses the enter/exit + reduced-motion rules verbatim; `'none'`/
undefined opts out; flash-free when spread in markup (`backwards` fill).
Verified in-browser: an element with the produced attrs gets `animation-name:
scale-in, fade-in`, enter progresses 0%(op0,scale .985)→50%(.84,.998)→100%(1,1);
`'none'` returns no attrs. `check` clean for the new file + export.
Step 2 (pending): a `<Motion>` wrapper (out: retention → exit) + wiring the
`motion` prop into real components.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
active-uix
parent
bfac34dd4f
commit
4f15be9f1b
@ -0,0 +1,24 @@
|
|||||||
|
import type { MotionPresetName } from './registry'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make ANY element a CONTENT-domain animation surface (RFC §D.12 / §D.13): spread
|
||||||
|
* these attrs and it plays the `preset`'s ENTER on mount. Reuses the existing
|
||||||
|
* state-preset enter rule via a constant presentation `data-state="open"` — the
|
||||||
|
* same mechanism `<Cascade.Item>` uses for content — so there is NO new trigger,
|
||||||
|
* no generator change, no JS. Flash-free when spread in markup: the attrs are
|
||||||
|
* present at insertion and the preset's `backwards` fill holds the from-state
|
||||||
|
* before the first paint.
|
||||||
|
*
|
||||||
|
* <div {...motionAttrs('scale-fade')}>…</div> // fades + scales in on mount
|
||||||
|
*
|
||||||
|
* `'none'` / `undefined` → no attrs (the explicit opt-out). Exit on unmount needs
|
||||||
|
* a retention primitive (`out:` / `Presence`) + flipping `data-state` to
|
||||||
|
* `'closed'`; that is the `<Motion>` wrapper's job, not a bare attr spread.
|
||||||
|
*
|
||||||
|
* For a STATEFUL component (its own `data-state` machine) or an EVENT firma, do
|
||||||
|
* NOT spread this — those own the trigger; this is the content domain only.
|
||||||
|
*/
|
||||||
|
export function motionAttrs(preset: MotionPresetName | undefined): Record<string, string> {
|
||||||
|
if (!preset || preset === 'none') return {}
|
||||||
|
return { 'data-animation-style': preset, 'data-state': 'open' }
|
||||||
|
}
|
||||||
Loading…
Reference in new issue