PluginUI

Components / Overview

A few good parts.
A complete interface.

Start with familiar controls, connect them to your state, and give them a style of your own. PluginUI supplies editable React source, shared gestures and reusable visual feedback.

01 / Choose the parts

Input, feedback and a little structure.

Most interfaces combine these three roles. Use the reference in the sidebar for APIs, the Controls gallery for custom designs, and Examples to see complete compositions.

Loading interactive preview…

Set a parameter

Knobs and faders edit continuous values. Switches and buttons handle on/off states and actions.

Explore Knob →
Loading interactive preview…

Make the result visible

An envelope, curve or meter helps explain what a parameter does. Feed it the same state as the controls.

Explore Envelope Editor →
Loading interactive preview…

Give the interface structure

Presets, mode selectors and readouts give the controls context and make a complete interface easier to use.

Explore Preset Selector →

02 / Connect the state

One value, every view.

Move the dial or slider. Both edit the same mix value, so the other control and readout follow. Your app owns the state; each control receives a value and a change callback.

Loading interactive preview…

Silent UI demo. Connect the callback to your existing parameter or audio host.

mix-controls.tsx
import { useState } from "react"
import { Knob } from "@/components/ui/knob"
import { Fader } from "@/components/ui/fader"

export function MixControls() {
  const [mix, setMix] = useState(0.5)

  return (
    <div>
      <Knob label="Mix" min={0} max={1} value={mix} onChange={setMix} />
      <Fader label="Mix" min={0} max={1} value={mix} onChange={setMix}
        orientation="horizontal" length={180} />
      <output>{Math.round(mix * 100)}%</output>
    </div>
  )
}

Drag to edit, use Shift for finer adjustments, or use the keyboard. The shared controls supply interaction; your application supplies parameter ranges and meaning.

03 / Give it a style

Change the appearance. Keep the wiring.

Palette changes color and type through CSS variables. Finish changes the control treatment. Apply them to a wrapper and the controls inherit them. Your mix value stays the same.

Palette
Finish
Loading interactive preview…
styled-panel.tsx
import type { ReactNode } from "react"
import { themeStyle, PRESET_THEMES } from "maruaudio/ui/shared/theme"
import { ControlSkinProvider } from "maruaudio/ui/shared/control-skin-context"

export function StyledPanel({ children }: { children: ReactNode }) {
  return (
    <ControlSkinProvider skin="flat">
      <div style={themeStyle({ ...PRESET_THEMES.bone, accent: "#353535" })}>
        {children}
      </div>
    </ControlSkinProvider>
  )
}

04 / Bring it into your project

Install source you can make your own.

Add the registry mapping to your existing components.json, preserving its settings. Install only the parts you need; shadcn resolves their shared helpers, CSS and npm dependencies.

components.json (merge registries)
{
  "registries": {
    "@pluginui": "https://pluginui.com/r/{name}.json"
  }
}
$ pnpm dlx shadcn@latest add @pluginui/core-knob @pluginui/core-fader

Import the installed components using your configured UI alias. Keep their companion styles, then adapt the source and callbacks to your application.

Read the installation guide →