
The slide-to-confirm button
Buttons, Physics, Transitions
NewFree
The ⌘K command palette of a project editor, as smooth as a native app: at rest it is a Search or jump to… pill with its shortcut drawn as keys, and pressed (or with ⌘K, Ctrl K) the pill itself grows into the palette. Typing filters the commands with a fuzzy score, the ones left slide to their places and the letters found light up; the band under the chosen row glides on a spring. A command with more inside opens its own page: the one before sinks back into depth, blurring, and breadcrumbs appear at the top. On the theme page, moving over a theme tries it on the palette at once.
A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React and Vue tabs hold the same demo as a ready component, which switches its animations off when it leaves the page.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>The command menu</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/geist@5.3.0/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/geist-mono@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the command menu of a project editor. At rest a search pill with its shortcut drawn as two little keys;
pressed (or with Cmd K / Ctrl K) the pill itself grows into the palette. Typing filters the commands, the
ones left slide to their places, the letters found light up; a command with more inside opens its own page,
the page before sinking back behind it. The rows are made by the script from the list in script.js -->
<div class="cmdk" data-cmdk data-autoclic>
<div class="cmdk__shell" data-shell>
<button class="cmdk__pill" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="cmdk-dialog" aria-keyshortcuts="Meta+K Control+K" data-pill>
<svg class="cmdk__lens" viewBox="0 0 24 24" aria-hidden="true"><path d="M10.5 4.5a6 6 0 1 0 0 12a6 6 0 1 0 0-12zM15 15l4.5 4.5"/></svg>
<span class="cmdk__pilltext" data-pilltext>Search or jump to…</span>
<span class="cmdk__keys" aria-hidden="true"><kbd class="cmdk__key" data-mod>⌘</kbd><kbd class="cmdk__key">K</kbd></span>
</button>
<div class="cmdk__dialog" id="cmdk-dialog" role="dialog" aria-modal="true" aria-label="Command menu" data-dialog hidden>
<div class="cmdk__head">
<svg class="cmdk__lens" viewBox="0 0 24 24" aria-hidden="true"><path d="M10.5 4.5a6 6 0 1 0 0 12a6 6 0 1 0 0-12zM15 15l4.5 4.5"/></svg>
<nav class="cmdk__crumbs" aria-label="Where you are in the menu" data-crumbs></nav>
<input class="cmdk__input" type="text" role="combobox" aria-expanded="true" aria-autocomplete="list" aria-label="Search commands" autocomplete="off" autocapitalize="off" spellcheck="false" enterkeyhint="go" placeholder="Search or jump to…" data-input>
<kbd class="cmdk__key cmdk__key--esc" aria-hidden="true">esc</kbd>
</div>
<div class="cmdk__body" data-body></div>
<div class="cmdk__foot" aria-hidden="true">
<span class="cmdk__tip"><kbd class="cmdk__key cmdk__key--icon"><svg viewBox="0 0 24 24"><path d="M12 18V6M7 11l5-5 5 5"/></svg></kbd><kbd class="cmdk__key cmdk__key--icon"><svg viewBox="0 0 24 24"><path d="M12 6v12M7 13l5 5 5-5"/></svg></kbd>Move</span>
<span class="cmdk__tip"><kbd class="cmdk__key cmdk__key--icon"><svg viewBox="0 0 24 24"><path d="M19 5v7.5H6M10 8.5l-4 4 4 4"/></svg></kbd>Open</span>
<span class="cmdk__tip" data-backtip><kbd class="cmdk__key cmdk__key--icon"><svg viewBox="0 0 24 24"><path d="M9 6h11v12H9l-5.5-6z"/></svg></kbd>Back</span>
</div>
</div>
</div>
<p class="sr" role="status" aria-live="polite" data-live></p>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/Flip.min.js"></script>
<script src="script.js"></script>
</body>
</html>Change values, colours and text with the controls and watch the animation respond live. Or write in the code yourself. Then download the folder with your changes.
25 values to change
With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:
Take “The command menu” from Animorio and fit it into my siteThe pill and the palette are the same element: a box with the background, the border and the shadow, whose position, width, height and corner radius GSAP moves from the size of the pill to the size of the panel (expo.out). Inside it sit the pill's button, anchored at the top, and the dialog: the first fades in 0.12 seconds, the second appears right after, with the field in the same place the words were, so the pill seems to have opened. Closing, the same in reverse.
Every letter typed must appear in the label, in order. For every possible starting point a score is worked out: one per letter, three more if it touches the one before, four if it starts a word, four if the match starts the label, and a little less for the gaps; the best wins, and its positions become the violet <mark>s. Each command's hidden words (dark, appearance…) find it even when the label does not match, with a lower score.
Before filtering, Flip takes a picture of the rows and group titles; then the ones that do not fit are hidden and Flip.from slides the rest from their old place to the new one. The rows keep their order, so they only move through the room left free and never overlap; the band goes to the best score. Rows coming back wait half of the others' travel before they appear, and the panel's height is measured from the last row (not from scrollHeight, which also counts rows still moved).
The band under the chosen row is a single element in the list: its position and its height are two springs (BAND) chasing the row, integrated in steps of 1/240 of a second; the height has a softer spring and grows a little with speed, so the band stretches as it runs and settles on arrival. When it arrives, the loop stops.
Every page has its own list (role listbox) stacked over the others. Going forward the page before shrinks by DEPTH, rises four pixels, blurs by BLUR pixels and fades, while the new one comes in from a little bigger and blurred and comes into focus; going back the opposite. The field gets the breadcrumbs (real buttons to go back), a new placeholder, and each page's search is kept for when you come back.
The field is a combobox with aria-controls on the page's list and aria-activedescendant on the chosen row; the rows are options with aria-selected. The window is a modal dialog: Tab only goes round the breadcrumbs and the field, Esc closes and the focus goes back to the pill. An announcement says how many results there are and what the command did.
| Name | File | Default | What it changes |
|---|---|---|---|
PILL | script.js | 300 | The width of the pill at rest, in pixels. |
OPEN | script.js | 0.55 | The seconds of the morph from the pill to the palette. |
DEPTH | script.js | 0.06 | How far a page sinks back behind the next one (0.06 = 6% smaller). |
BLUR | script.js | 6 | How blurred the page behind is, in pixels. |
SLIDE | script.js | 0.4 | The seconds the rows take to slide to their new places while you type. |
BAND | script.js | [520, 36] | The spring of the band under the chosen row: stiffness, and damping. |
SHORTCUT | script.js | 'k' | The key that opens it with ⌘ (Mac) or Ctrl. |
For an app with many actions and pages: an editor, an admin panel, a tool for developers or teams, a product's documentation. The inner pages are for choices with several options (theme, project, language, someone to assign); the commands and groups are changed in the list at the top of the script.
The box takes the width of the screen minus 32 pixels; the pill stays 300 wide. The row of hints at the bottom and the esc key disappear (a phone has no physical keyboard), the rows stay 42 pixels tall for the finger, the list scrolls with the finger inside the panel without scrolling the page, and a tap outside closes it.
No morph and no depth: the palette fades in already at its size and the pill disappears at once; the pages swap with a fade, without scale or blur. Filtered rows go straight to their places and the band jumps to the chosen row. Everything else, keys, themes, breadcrumbs, works the same.
GSAP 3.15.0, Flip (GSAP) 3.15.0, Geist (font variabile) 5.3.0, Geist Mono (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 13 KB; the libraries: GSAP + Flip 37 KB.
Tested on 5 October 2026
Use it in your own projects and in your clients’ projects. Do not resell it or redistribute it as is. GSAP stays under its own Standard license. Full license.
With your account’s email and password.
or with your email
You’re signed in as .
With your account, you can download the zip of every animation and every pack, for free.