Skip to content
Speed
Slow motion multiplier
1×
Reduced motion
Show

Live previews

The coverage work, each as a working before-and-after. Every control writes a real token, so a value settled here is settled everywhere. Turn the rail up to 4× to judge a curve, then back to 1× to judge whether it is too slow — those are different questions and they need different speeds.Decide here: Sliding indicators, disclosure convergence, the rail, chips, skeletons, lists.
Ordered by impact per unit of work
This is the brief’s where-to-start list with the presence work removed, since that has its own page and is the one thing here blocked on a policy decision. Everything below is unblocked and can start as soon as the tokens land.

Sliding indicators

ADD
TabList and SegmentedControl share one decision. A travelling indicator crossing five tabs feels different from one crossing two — judge it on the long jump, not the short one.
Today — per-item cross-fade
Core’s TabList. Each tab draws its own indicator and they cross-fade on opacity, so nothing travels and the eye has to re-find the selection after every change.
Proposed — one indicator travels
One indicator for the strip, moved with transform on --ease-move. Compositor-only, and the eye can follow it. Jump between distant tabs to judge the duration — a bar crossing five tabs feels different from one crossing two.
travel
310ms
Both panes here are core’s TabList. The right one is a swizzled copy of that same source with three changes — a hasTravellingIndicator prop, one indicator in the strip positioned over the selected tab, and a context flag telling each Tab to suppress the indicator it draws for itself. It lives at proposed/TabList/, so the difference you are watching is the diff. The position is measured from the DOM rather than tracked in state, because the tabs size themselves — that ResizeObserver is the only real cost the proposal adds, and is the part to review if it ships.The proposed pane uses --ease-move rather than the entry curve, because the indicator is already on screen: it needs a legible path, not an arrival accent. This is also the strongest candidate for the layout spring, since a travelling indicator is exactly the interruptible case.

Disclosure bake-off

PARTIAL — three techniques
Nine surfaces, three techniques, and the newest component uses the one nobody else does. Settle it before more disclosure surfaces get built.
Grid tracks — CodeBlock, Chat
Astryx ships nine duration tokens and one easing token.Nine surfaces disclose content, using three different techniques.
No measurement needed, and it survives content changing mid-transition. Cannot be used on a table row, which is why this may not be the single winner.
Height interpolation
Astryx ships nine duration tokens and one easing token.Nine surfaces disclose content, using three different techniques.
Needs a scrollHeight measurement on every open, so streaming content fights it. Works anywhere, including a table row.
Height + offset fade — Collapsible
Astryx ships nine duration tokens and one easing token.Nine surfaces disclose content, using three different techniques.
Height plus a delayed content fade. The newest component uses this, and it is the only one that does.
reveal
310ms
There is probably no single winner. A table row cannot be a grid container, so Table row expansion and Table tree cannot use the grid-track technique whatever the bake-off concludes. The realistic outcome is one default plus a documented exception — which is worth writing down as the decision, rather than discovering it halfway through the convergence work.

SideNav rail collapse

ADD
The rail's own width, not just the chevron. width is a layout property, so this is a deliberate criterion-6 exception — does it earn one?
Today — the rail snaps
Skip to content
ProjectsThe page beside the rail.
Today: the real SideNav snaps between its widths, so the page beside it jumps.
Proposed — the rail animates, the page follows its edge
Skip to content
ProjectsThe page beside the rail.
The rail’s width animates on the lab’s collapse-and-expand duration and decelerating curve. The content is AppShell’s flex sibling, so its edge follows the rail in the same frame, and the page is anchored to that edge, so it moves with the rail instead of half as far. Reduce Motion snaps.
Both panes are the real AppShell and SideNav, collapsed through SideNav’s own controlled collapsible config. The proposal animates the rail’s width on the lab’s collapse-and-expand duration (--duration-reveal) and decelerating curve (--ease-entry), so tuning either token reaches it. The content is AppShell’s flex sibling, so its edge follows the rail in the same frame with no script per frame. The page is anchored to that edge (margin-inline: 0 auto) rather than centered in its own widening space, so it moves with the rail instead of half as far, and never re-centers. Reduce Motion snaps.The transform alternative — translate the rail and clip it — keeps the animation on the compositor but leaves the content beside it un-reflowed until the end, which reads worse than the layout cost.

Skeleton → content

ADD
The archetypal hard swap. The failure is that it happens at a moment the user cannot predict.
Today — content hard-swaps
Astryx Motion48 of 104 core components animate something.Audited against core@0.5.0.
Content hard-swaps the instant it arrives, at a moment the user cannot predict.
Proposed — crossfade with overlap
Astryx Motion48 of 104 core components animate something.Audited against core@0.5.0.
Skeleton fades out while content fades in, overlapping just enough that the box is never empty.
crossfade
175ms

Chip add and remove

ADD
Tokenizer, Token and FileInput share this. Removal is the hard half: the chip has to leave while its neighbours close the gap.
Today — instant
designmotiontokens
Chips appear and disappear on a frame. The canonical scale-in case, unanimated.
Proposed — scale in, accelerate away
designmotiontokens
Scale-in with opacity; removal accelerates away and the neighbours close the gap.
add
230ms
remove
175ms

List add, remove and reorder

ADD
Reorder is movement the user did not initiate, so it has to be followable. This is the strongest argument for the layout spring.
Today — instant
Item 1Item 2Item 3Item 4
Reorder is instant, so the user has to re-read the list to find out what changed.
Proposed — FLIP on --ease-move
Item 1Item 2Item 3Item 4
FLIP: measure, move, invert, play. Rows travel on --ease-move, so a change the user did not initiate stays followable.
FLIP — measure, move, invert, play — is the technique here because the rows are genuinely re-laid-out and only the visual correction is animated. Try it at 4×: a shuffle that is legible at 4× and illegible at 1× means the duration is too short, not that the technique is wrong.

Checkbox tick

ADD
A high-frequency surface, so criterion 2 applies: the answer may be that it should be almost nothing.
Today — real CheckboxInput
Real CheckboxInput — the tick appears instantly
Draw
Draws along its path
Scale
Scales in

Stat value change

ADD
A change of 4 and a change of 4,000 look identical today. Needs a delta threshold, or a jump from 12 to 1,300,000 spins for a second.
Today — replaces itself
1,247The number replaces itself, so a change of 4 and a change of 4,000 look identical.
Proposed — counts
1,247Counts to the new value. Needs a delta threshold so a jump from 12 to 1,300,000 does not spin for a second.

NavItem hover tint

ADD
Hover a row in each pane. Today the tint snaps on; the proposal fades it on the state token, and narrows the hover gate to a fine pointer that hovers.
Today — snaps on hover
Overview
Projects
Settings
Today: the tint snaps on at once wherever the device hovers.
State token, fine pointers only
Overview
Projects
Settings
The theme's state token (--duration-fast on --ease-standard), only on a fine pointer that hovers.

ProgressBar fill

PARTIAL
Width against transform for the determinate fill. Width re-lays out the bar every frame; scaleX stays on the compositor but squashes the rounded ends.
Today — real ProgressBar, width
Uploading12%
Width is a layout property: every frame of every tick re-lays out the bar. A fast upload ticks often enough to behave like a layout loop.
Proposed — transform: scaleX
Uploading12%
The same fill on transform: scaleX, so it runs on the compositor. The cost shows at the ends: the rounded caps squash at small values, which is why this needs an exception or a different structure before it ships.

What is not here

Around twenty more previews are specified but not built — ContextMenu’s pointer-anchored origin, CommandPalette filter motion, TreeList depth, TransferList’s cross-container move, Carousel, Calendar month change, Slider keyboard step, Resizable snap. Each one has a written brief saying what it must demonstrate, on Preview plan. The ones above were built first because each settles a decision that blocks other work.