Back to the Lab

NODE · node_browser18 Oct 2026In main · unreleased

Every chip has to show where it went

Pinning a keyword reorders the row. FLIP moves every chip from its old place to its new one, and keyboard focus goes with them.

Noticed

Keywords are what NODE searches with, so pinning or hiding one changes the search. renderKeys() deleted and rebuilt every chip on each change, so the whole row jumped at once and nothing showed what had moved or where it went. If you had tabbed to a chip’s × and used it, focus went back to the top of the window.

Made

Chips are kept now, one per keyword, and reordered with the CSS order property. Pinning fades the chip to violet over 200ms and slides every chip from its old place to its new one with FLIP — first, last, invert, play: note where each chip is, make the change, measure where it ended up, then draw it at the old spot and animate it to the new one. It lets a layout change look like movement without animating the layout itself. Hiding is two beats: the chip fades and scales to 0.9 where it is, so you see which one went, and only then do the others close the gap and the next keyword enter. Changes queue, so two quick clicks read as two steps instead of a tangle. If the × that had focus is removed, focus moves to the × now in its place, and when the motion ends the chips are put back in page order so Tab order matches what you see. Under reduced motion nothing slides or scales; chips leaving and arriving fade over 120ms.

At speed
4× slower

Recorded from the approval prototype, not the running app. The prototype runs the same CSS on copies of NODE’s own controls; app recordings replace these when they are made.

Tokens it uses

--motion-base
200ms — the colour fade, the slide, a chip entering
--motion-fast
120ms — a chip leaving
--ease-move
cubic-bezier(0.4, 0, 0.2, 1) — between two on-screen states
--ease-exit
cubic-bezier(0.4, 0, 1, 1) — things going away

Rules it follows

Enter and exit are not mirror images. Exits are faster

A chip leaves in 120ms on --ease-exit and arrives in 200ms on --ease-enter. Going is a fact; arriving is something to read.

Animate transform and opacity only

FLIP moves the chips on transform, which is why the row can reorder without the layout itself animating. The pin’s violet is the allowed exception: colour and border may fade on a state change, because they repaint rather than move.

Animate on user action only

Keywords that change because you scrolled or opened a page swap with none of this motion. Only your own pin and hide animate.

Keyboard and focus get the same care as hover and click

If the × that had focus is removed, focus moves to the × now in its place. When the motion ends the chips are put back in page order, so Tab order matches what you see rather than what CSS order did.

Hidden chips are removed, never greyed out

The exit plays in place first, so you see which one went, and only then does the row close the gap and the next keyword enter.

Reduced motion removes the movement and keeps the fade

Nothing slides or scales. Chips leaving and arriving fade over 120ms.

Still open

The chip itself is a <span>, so Tab reaches only its ×. Making the chip focusable would change behaviour, so it is left as its own decision rather than folded into a motion change.

Open the commit All of the Lab