Arrangement
Transport and mixer
EQ and filters
Modulation
Utility
Instruments
Audio UI
Controls two values at once, such as filter cutoff and resonance, pan and mix, or two macros. The registry component wraps the XYPad primitive from @audio-ui/react and adds a grid, a crosshair, a cursor and a value display.
Overview
- Input: press or drag on the pad, or use the mouse wheel, a trackpad or the keyboard, on both axes.
- Axes: X and Y have their own range and step (
minX,maxX,stepX;minY,maxY,stepY). - Display: grid lines, a crosshair, a cursor and an optional value display. The position is exposed as the CSS variables
--xy-pad-x(from the left) and--xy-pad-y(from the top). - Accessibility: the cursor holds one native
<input type="range">per axis. Both carry the accessible name (aria-labelbecomes "… X" and "… Y", or set each withgetAriaLabelon the primitive'sThumb). The X input takes focus, and the arrow keys move both axes.
Installation
pnpm dlx shadcn@latest add @audio-ui/xypad
Anatomy
Import the primitive and assemble its parts.
import { XYPad } from "@audio-ui/react";
<XYPad.Root>
<XYPad.Label />
<XYPad.Control>
<XYPad.Thumb />
</XYPad.Control>
<XYPad.Value />
</XYPad.Root>Usage
import { XYPad } from "@/components/audio-ui/xypad";Uncontrolled: set only the initial value.
<XYPad
defaultValue={{ x: 0, y: 0 }}
maxX={100}
maxY={1}
minX={-100}
minY={-1}
stepX={1}
stepY={0.01}
/>Controlled: drive the value from state.
const [position, setPosition] = useState({ x: 50, y: 50 });
<XYPad
maxX={100}
maxY={100}
minX={0}
minY={0}
onValueChange={setPosition}
onValueCommitted={(value, details) => console.log("Committed:", value, details.reason)}
value={position}
/>Interaction
Pointer
Behavior · 4
eventDetails.reason "press" then "drag".stepX / stepY.onValueCommitted fires when a gesture that changed the value ends.value updates late. Reject a value with eventDetails.cancel().Keyboard
On the focused pad:
Keys · 5
stepXstepYstepY × 10minX / maxXWheel
Wheel and trackpad input over the pad moves the point by the scrolled distance: scrolling up raises Y, scrolling right raises X. Reported as eventDetails.reason === "wheel".
API reference
Root
Groups all parts of the pad and owns its two-dimensional value. Exposes the value position as CSS variables for crosshairs and guides: --xy-pad-x (from the left) and --xy-pad-y (from the top), as percentages. Renders a <div> element.
Props · 14
XYPad.Value and the inputs' aria-valuetext.name.x and name.y.Data attributes · 2
data-disableddata-draggingControl
The pad surface: a press jumps the value to the pointer and a drag follows it; the mouse wheel / trackpad moves it too. Sets touch-action: none so touch drags don't scroll the page. Renders a <div> element.
Data attributes · 2
data-disableddata-draggingThumb
Marks the value on the pad (left/top as percentages, centered with translate). Holds two native <input type="range">s, one per axis: the X input takes focus, both carry the accessible name, and the arrow keys move both axes. Renders a <div> element.
Props · 2
aria-label followed by "X" / "Y".aria-valuetext. Defaults to the formatted value.Data attributes · 2
data-disableddata-draggingValue
The formatted value (format/locale on Root), "x, y" by default. Renders a <output> element.
Props · 1
Data attributes · 2
data-disableddata-draggingLabel
Accessible label, associated with both axis inputs. Renders a <div> element.
Data attributes · 2
data-disableddata-draggingRegistry component
XYPad accepts style props (size, formatValue, valueDisplay, className) plus primitive props from XYPadPrimitive.Root.Props. aria-label, aria-labelledby, and aria-describedby are forwarded to the axis inputs.
Value and state
Props · 12
XYPad.Value and the inputs' aria-valuetext.format.Layout and display
Props · 4
"hidden" to hide the overlay.@audio-ui/react/xypad exposes XYPad.Root, XYPad.Control (the pad surface), XYPad.Thumb (positioned at the value, holds the axis inputs), XYPad.Value (formatted <output>), and XYPad.Label. Every part accepts a render prop, className / style as functions of state, and exposes data-disabled / data-dragging. Draw grids and crosshairs with your own elements and the --xy-pad-x / --xy-pad-y variables.
Examples
Live value readout
Audio UI
Bipolar ranges (pan and mix style)
Audio UI
Pocket synth
An oscillator, a filter and an XY pad that plays them: drag the pad to sweep the sound.
Audio UI
Wave shaper
Distortion, tone and detune on a synth, with the XY pad and knobs side by side.
Audio UI
More Shadcn XY Pad components
Browse 4 production-ready audio/ui XY Pad components for players, mixers, and synth interfaces. These examples use the headless primitives from @audio-ui/react and stay fully compatible with Shadcn Create so radius, color, and typography match your configured theme.
Browse all 4 Shadcn XY Pad components for copy-ready layouts, dashboards, and forms built with Tailwind CSS in the audio/ui library.