PluginUI

Pad Grid

pad-gridControls

Rows of rubber pads are labelled and lit from the state you pass in. Velocity depends on where the press lands: the top edge gives a full-force hit and the bottom edge the softest, so a player can aim a tap. Choke groups are both drawn and obeyed. Pads that cut each other share a tie mark based on the same membership function the engine uses to decide what to silence. A pad can be deliberately silent (pressed, no voice) or empty (drawn, not playable); both look different from idle. Layout, hit testing and the velocity law live in a pure geometry module beside the component.

Bone / Studio
Loading interactive preview…
Planar / Flat
Loading interactive preview…
Midnight / Minimal
Loading interactive preview…
Ember / Vintage
Loading interactive preview…
Ink / Studio
Loading interactive preview…
Mint / Flat
Loading interactive preview…

Install

Copies the source into your project. Anything it depends on comes with it.

$ pnpm dlx shadcn@latest add @pluginui/core-pad-grid

Pulls in

pad-grid-geometrycontrol-theme

First time? Add the registry to your components.json once:

components.json
{
  "registries": {
    "@pluginui": "https://pluginui.com/r/{name}.json"
  }
}

Usage

Connect the documented props to your application or host.

example.tsx
import { PadGrid } from "@/components/ui/pad-grid"

<PadGrid
  rows={4}
  columns={4}
  pads={pads.map((pad) => ({
    label: pad.role,
    sublabel: String(pad.note),
    state: held.get(pad.note) ? "active" : "idle",
    chokeGroup: pad.chokeGroup,
  }))}
  onPadDown={(index, strike) => noteOn(pads[index].note, strike.velocity)}
  onPadUp={(index) => noteOff(pads[index].note)}
/>

Props

PropTypeDefaultDescription
rows / columnsnumber—The layout; pads are index-aligned row-major from the top-left.
pads{ label?, sublabel?, state?, chokeGroup?, ariaLabel? }[]—Pad content and state: idle, active, silent or empty. Short arrays leave the rest empty.
onPadDown / onPadUp(index, strike) => void / (index) => void—Strike with velocity and landing position; release.
width / height / gap / padding / radiusnumber—viewBox geometry; the rendered size is CSS's business.
showChokeboolean—Draw the choke-group tie marks.

Interaction

  • Drag with pointer capture, so the gesture keeps tracking past the edge of the control.
  • Shift while dragging for a fine pass; release it mid-gesture and coarse tracking resumes.
  • Double-click resets to defaultValue.
  • Arrow keys step normally, Shift+arrow steps finely, PageUp/PageDown jump by ten, Home/End go to the extremes.
  • Proper slider and switch roles with live aria-valuetext, so a screen reader announces the formatted value rather than the raw number.
  • The scroll wheel adjusts the value while the pointer is over the control; stepped ranges move at least one declared step per notch by default.