
The three-line menu
Menus, Transitions, Physics, Text
NewFree
The command palette of a podcast editor, where every command is a clip with its audio drawn under it: as you type it plays louder the closer it matches, and the loudest rise to the top. A row that has to jump over the others travels as sound, its words off, and finds them again in its new place; the command picked plays in amber and, once left, dies away slowly like the needle of a VU meter.
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 palette that plays</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/radio-canada@5.3.0/standard.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the command palette of a podcast editor. Every command is a clip of sound: the better it matches what is
typed, the louder its waveform plays, and the loudest go to the top. The command picked plays in amber;
moving on, its sound fades out behind you. The rows are made by the script from the list in script.js -->
<div class="desk" data-desk data-autoclic>
<button class="open" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="cmd-dialog" aria-keyshortcuts="Control+K Meta+K" data-open>
<svg class="open__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="open__text">Commands</span>
<span class="keys" aria-hidden="true"><kbd class="key" data-mod>Ctrl</kbd><kbd class="key">K</kbd></span>
</button>
<div class="pal" id="cmd-dialog" role="dialog" aria-modal="true" aria-label="Commands" data-pal hidden>
<div class="pal__head">
<svg class="pal__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>
<input class="pal__input" type="text" role="combobox" aria-expanded="true" aria-controls="cmd-list" aria-autocomplete="list" aria-label="Search commands" placeholder="Search commands…" autocomplete="off" autocapitalize="off" autocorrect="off" spellcheck="false" enterkeyhint="go" data-input>
<span class="pal__caret" aria-hidden="true" data-caret></span>
<kbd class="key key--word" aria-hidden="true">esc</kbd>
</div>
<div class="pal__list" id="cmd-list" role="listbox" aria-label="Commands" data-list>
<canvas class="pal__wave" aria-hidden="true" data-wave></canvas>
<div class="pal__none" aria-hidden="true" data-none>
<p class="none__what" data-none-what></p>
<p class="none__tip">Try a word like noise, chapter or export.</p>
</div>
</div>
<div class="pal__foot">
<p class="pal__hints" data-hints>
<span class="hint hint--keys"><kbd class="key key--icon"><svg viewBox="0 0 24 24"><path d="M12 18.5v-13M7 10l5-5 5 5"/></svg></kbd><kbd class="key key--icon"><svg viewBox="0 0 24 24"><path d="M12 5.5v13M7 14l5 5 5-5"/></svg></kbd>Move</span>
<span class="hint hint--keys"><kbd class="key key--icon"><svg viewBox="0 0 24 24"><path d="M18.5 5.5v7H6.5M10.5 8.5l-4 4 4 4"/></svg></kbd>Run</span>
<span class="hint hint--keys"><kbd class="key key--word">esc</kbd>Close</span>
<span class="hint hint--touch">Tap a command to run it</span>
</p>
<p class="pal__done" data-done>
<svg class="pal__tick" viewBox="0 0 24 24" aria-hidden="true" data-done-tick><path d="M5.5 12.5l4.2 4.2L18.5 7.5"/></svg>
<svg class="pal__info" viewBox="0 0 24 24" aria-hidden="true" data-done-info><path d="M12 3.5a8.5 8.5 0 1 0 0 17a8.5 8.5 0 1 0 0-17zM12 11v5.5M12 7.6v.4"/></svg>
<span data-done-text></span>
</p>
</div>
</div>
<p class="sr" role="status" aria-live="polite" data-said></p>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.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.
98 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 palette that plays” from Animorio and fit it into my siteEvery command has its own waveform, always the same: its name gives a number that seeds a random generator, which lines up syllables (bells of different width and height) and a few pauses. The shape is sampled in bars 2 pixels wide every 4, as many as fit in the row, and sampled again when the window changes size.
The search wants every letter typed in the name, in order, and picks with dynamic programming the way of finding them that scores most: a point a letter, four if it follows the letter before, three if it starts a word, two if it starts the name, a little less for every letter skipped. The score divided by the best one's, raised to 1.6, is the row's volume; commands are sorted by score within their group, and groups by their best command.
Every bar has its own height and its own heat (from grey to amber), which chase their target exponentially: fast going up (0.03 seconds) and slow coming down (TRAIL), like the meters that measure audio. The pick lights the bars from the left one after the other in SWEEP seconds. The bars are drawn on one canvas under the rows, adding up the light where two audios cross, and only while something moves; under the words they show at 32 percent, under the keys not at all.
At every letter the rows and the group names take their new place on a spring (SPRING). Among the ones that stay, the longest increasing run of their old places keeps its order and slides with its words on, since it cannot cross anything; the others turn their words off in 0.06 seconds and travel as audio alone. A row turns its words back on only once it has arrived and no word that is on is passing, or about to pass, where it is; the list's height follows the same spring and never cuts a word that is on.
Enter or a click start a timeline: the playhead crosses the row in RUN seconds, the audio behind it turns white, the keys fade and a tick draws itself with stroke-dashoffset, the foot says what was done, and after HOLD seconds the palette closes. Typing or moving the pick meanwhile stops the timeline and puts everything back.
The field has role combobox, aria-controls on the list and aria-activedescendant on the row picked; the list is a listbox with a group for each group and the rows are options with aria-selected, aria-disabled for the one that is off and aria-keyshortcuts. An aria-live region says how many commands there are and what was done. The window is a modal dialog: Tab stays in the field, Escape or a click outside close it and the focus goes back to the button, with its ring only for who uses the keys.
| Name | File | Default | What it changes |
|---|---|---|---|
SHOWN | script.js | 7 | How many commands the palette shows at most. |
RESTING | script.js | 2 | How many commands of each group it shows while the field is empty. |
TRAIL | script.js | 0.32 | How slowly a row’s sound dies away once the pick has left it, in seconds. |
SWEEP | script.js | 0.16 | The seconds the sound takes to run across the row picked. |
SPRING | script.js | [700, 50] | The spring that takes the rows to their new places: stiffness and damping. |
RUN | script.js | 0.45 | The seconds the playhead takes to cross a command that runs. |
HOLD | script.js | 0.8 | How long the palette says what was done before it closes, in seconds. |
COMMANDS | script.js | [['Clip', 'Split clip at playhead', 'S', 'Clip split at 12:48', 'split'], …] | The commands: group, name, shortcut (mod is Cmd on a Mac and Ctrl elsewhere), what the foot says once it runs, icon. |
LOCKED | script.js | ['Publish to feed', 'Export first', 'Export the episode before publishing it'] | A command not available yet: its name, the note on its right and why. |
For the command palette of an app that works with sound (podcasts, music, video, radio), or of any tool where you find an action by typing: the volume tells at a glance how close a command is to what you typed.
The palette takes the width of the screen minus the margins. On touch screens the shortcuts go (there is no keyboard to use) and their room goes to the audio; the foot says Tap a command to run it, the rows are 44 pixels tall and a tap runs one. The field’s text is 17 pixels, so iPhone does not zoom the page.
Nothing slides and nothing grows: the rows that change place fade out and back in at their new place, the audio comes and goes with the words without rising, the pick changes colour with a fade and the playhead does not run: the audio turns white all at once.
GSAP 3.15.0, Radio Canada (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 17 KB; the libraries: GSAP 28 KB.
Tested on 7 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.