axi0motion

Wheel picker

A curved picker that spins with a drag, the scroll wheel or the arrow keys, tilting the options away from the chosen one; it drives the real select underneath.

  • enhancer
  • select
  • picker
  • wheel
  • listbox
  • scroll
  • since 0.2

Background Studio: tune it below, then copy the code

Your system asks for reduced motion: the demo shows its final state and nothing moves.

Live demo

Wheel picker example

Controls

5
22 deg

Code

It follows the controls above: change an option and the code changes with it.

<link rel="stylesheet" href="/axi0/motion/motion.css?v=6">
<script src="/axi0/motion/motion.js?v=10" defer></script>

<div class="demo-card">
<label for="genre">Genre</label>
<select id="genre" data-motion="wheel-picker">
  <option>Ambient</option>
  <option>House</option>
  <option>Techno</option>
  <option selected>Jazz</option>
  <option>Lo-fi</option>
  <option>Synthwave</option>
  <option>Soul</option>
</select>
</div>

The wrappers: WheelPicker.tsx (React, TypeScript) and WheelPicker.vue (Vue). Both render the same attributes as the HTML; the loader does the rest.

Options

AttributeDefaultWhat it does
data-motion-rows5how many rows show (odd)
data-motion-tilt22how far each row tilts away

Accessibility

- The wheel is a single-select listbox named by the page's label; selection follows focus, so Up and Down pick the next option, Page Up and Page Down jump a wheel's height, Home and End go to the ends, and a typed letter jumps to the next option that starts with it. aria-activedescendant points at the chosen option. - It sets the real select's value and fires its input and change events; without JavaScript the plain select shows. - Dragging, flicking and the scroll wheel spin it; a click on a row picks it. - Reduced motion turns the wheel in one step. Reduced motion shows every state at once, with no movement, and stops anything that would move on its own. Frame loops and CSS animations pause off screen and in hidden tabs. Only transform, opacity and paint animate, so nothing around it moves.

Size

wheel-picker.js is 2.0 KB gzip, with components-kit.js 3.9 KB it needs. A page loads the loader (2.7 KB) and core.js (1.4 KB) once, whatever it uses.