Two-dimensional control surface for mapping and automating X/Y parameters with pointer, wheel, and keyboard input.
"use client";
import { useState } from "react";XY pad for simultaneous control of two values (for example filter cutoff/resonance, pan/mix, or macro controls). The registry component wraps XYPad primitives from @audio-ui/react and provides ready-to-use visuals (grid, crosshair, cursor, value display).
Overview
- Interaction model: Pointer drag, wheel nudging, and keyboard nudging over both axes.
- Axes: Independent ranges and steps for X (
minX,maxX,stepX) and Y (minY,maxY,stepY). - Feedback: Grid lines, crosshair, animated cursor, and optional value display overlay.
- Accessibility: Focusable interactive surface with ARIA labeling (
aria-label/aria-labelledby).
Installation
pnpm dlx shadcn@latest add @audio/xypad
Usage
import { XYPad } from "@/components/audio/xypad";Uncontrolled - initial value only:
<XYPad
defaultValue={{ x: 0, y: 0 }}
maxX={100}
maxY={1}
minX={-100}
minY={-1}
stepX={1}
stepY={0.01}
/>Controlled - drive value from state:
const [position, setPosition] = useState({ x: 50, y: 50 });
<XYPad
maxX={100}
maxY={100}
minX={0}
minY={0}
onValueChange={setPosition}
onValueCommit={(value) => console.log("Committed:", value)}
value={position}
/>Interaction
Pointer
| Behavior | Details |
|---|---|
| Click / drag on pad | Pointer position maps directly to X/Y in bounds. |
| Clamping | Values always clamp to configured axis ranges. |
| Commit event | onValueCommit fires when drag interaction ends. |
Keyboard
Focused XY pad:
| Key | Action |
|---|---|
ArrowLeft / ArrowRight | Decrease / increase X by stepX |
ArrowUp / ArrowDown | Increase / decrease Y by stepY |
PageUp / PageDown | Increase / decrease Y by stepY × 10 |
Home | Jump to top-left logical corner (x = minX, y = maxY) |
End | Jump to bottom-right logical corner (x = maxX, y = minY) |
Wheel
When focused, wheel deltas nudge both axes according to pad dimensions and axis ranges, then quantize with stepX and stepY.
API reference
XYPad accepts style props (size, formatValue, valueDisplay, className) plus primitive props from XYPadPrimitive.RootProps.
Value and state
| Prop | Type | Default | Description |
|---|---|---|---|
value | { x: number; y: number } | - | Controlled value. |
defaultValue | { x: number; y: number } | { x: 0, y: 0 } | Uncontrolled default value. |
minX | number | 0 | Minimum X value. |
maxX | number | 100 | Maximum X value. |
minY | number | 0 | Minimum Y value. |
maxY | number | 100 | Maximum Y value. |
stepX | number | 1 | Step increment for X axis. |
stepY | number | 1 | Step increment for Y axis. |
disabled | boolean | false | Whether the pad is disabled. |
onValueChange | (value: { x: number; y: number }) => void | - | Callback when value changes during interaction. |
onValueCommit | (value: { x: number; y: number }) => void | - | Callback when value is committed (on release). |
aria-label | string | "XY Pad" | Accessible name for the interactive surface. |
aria-labelledby | string | - | ID of a labeling element. |
Layout and display
| Prop | Type | Default | Description |
|---|---|---|---|
size | "sm" | "default" | "lg" | "xl" | "default" | Size variant (affects height). |
formatValue | (value: { x: number; y: number }) => React.ReactNode | - | Custom formatter for value display. |
valueDisplay | "visible" | "hidden" | "visible" | Controls value display visibility. Use "hidden" to hide overlay. |
className | string | - | Additional CSS classes. |
Additional valid HTML attributes passed to XYPad.Root are forwarded.
Examples
Live value readout
"use client";
import { useState } from "react";Size variants
sm
import { XYPad } from "@/components/audio/elements/xypad";
export function XYPadSizeSmDemo() {default
import { XYPad } from "@/components/audio/elements/xypad";
export function XYPadSizeDefaultDemo() {lg
import { XYPad } from "@/components/audio/elements/xypad";
export function XYPadSizeLgDemo() {xl
import { XYPad } from "@/components/audio/elements/xypad";
export function XYPadSizeXlDemo() {Disabled state
import { XYPad } from "@/components/audio/elements/xypad";
export function XYPadDisabledDemo() {Custom formatted display
"use client";
import { XYPad } from "@/components/audio/elements/xypad";
Hidden value display
"use client";
import { XYPad } from "@/components/audio/elements/xypad";
Bipolar ranges (pan and mix style)
"use client";
import { useState } from "react";Live value vs committed value callbacks
"use client";
import { useState } from "react";Channel strip
Filter pad
"use client";
import { useState } from "react";Reverb pad
"use client";
import { useId, useState } from "react";More Shadcn XY Pad components
Browse 10 production-ready audio/ui XY Pad components for players, mixers, and synth interfaces. These examples use Base UI primitives from @base-ui/react and stay fully compatible with Shadcn Create so radius, color, and typography match your configured theme.
Browse all 10 Shadcn XY Pad components for copy-ready layouts, dashboards, and forms built with Tailwind CSS in the audio/ui library.