Install sensory-ui and add semantic sound to your shadcn/ui components.
Get sensory-ui running in your project in a few minutes. The entire process uses the shadcn CLI. No custom registry server required.
Before you begin, make sure you have:
components.json present)If you haven't set up shadcn/ui yet, run npx shadcn@latest init first and
follow the prompts.
Start with just a button. There is no reason to install all 24 components before you need them:
npx shadcn@latest add SatyamVyas04/sensory-ui/sensory-ui-buttonThis pulls the core engine (provider, config, all 9 sound packs) plus the Button. The registry is served directly from the public GitHub repository via registry.json. No custom registry server or URL required.
Add more pieces as you need them (sensory-ui-dialog, sensory-ui-tabs,
…) or install everything at once with
SatyamVyas04/sensory-ui/sensory-ui. One component is the recommended
starting point.
sensory-ui ships with 9 sound packs. The default is aero (clean, modern SaaS: filtered tones, balanced):
| Pack | Character |
|---|---|
soft | Warm, minimal: gentle sine tones, smooth fades |
aero | Clean, modern SaaS: filtered tones, balanced (default) |
arcade | 8-bit chiptune: square waves, stepped pitch, NES vibe |
organic | Natural, earthy: soft noise bursts, warm harmonics |
glass | Crystalline, delicate: bright resonant tones |
industrial | Mechanical, bold: raw waveforms, metallic edge |
minimal | Ultra-clean: pure tones, maximum restraint |
retro | Synthwave: dual detuned sawtooth, Moog vibe |
crisp | Precise, modern: clean attacks, tight envelopes |
Pass it to the provider: config={{ theme: "arcade" }} (or keep a theme field in your own sensory.config.js and spread it into the provider; see Configuration). All packs share the same roles, so switching is a one-line theme change.
With the Button install, only button.tsx lands alongside the core. Other components appear as you add them:
Audio is generated programmatically via the Web Audio API inside sensory-ui/sounds/. No files in public/, no asset serving, no base64 blobs. sensory.config.js is an optional user-owned convention: if you create one at the project root, spread it into the provider (<SensoryUIProvider config={config}>); deleting it simply falls back to the built-in defaults.
The provider must wrap the entire component tree so the AudioContext persists across navigations and all components have access to playSound.
// app/layout.tsx
import { SensoryUIProvider } from "@/components/ui/sensory-ui/config/provider";
import type { ReactNode } from "react";
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body>
<SensoryUIProvider>{children}</SensoryUIProvider>
</body>
</html>
);
}The provider is a client component. Your root layout can remain a server component, as Next.js allows client components to receive and render server component children transparently.
Import any component directly from sensory-ui and pass a sound prop:
import { Button } from "@/components/ui/sensory-ui/button";
export function SaveButton() {
return (
<Button sound="interaction.tap" onClick={handleSave}>
Save
</Button>
);
}The sound prop is the only required change from standard shadcn/ui usage. All other props, variants, and behaviour are identical.
Open the browser devtools console and look for any sensory-ui warnings. In development mode, the engine logs a warning if a sound cannot be resolved.
Validate the GitHub registry payload from the CLI:
npx shadcn@latest registry validate SatyamVyas04/sensory-ui
npx shadcn@latest list SatyamVyas04/sensory-uiOr build locally to validate:
bun run registry:buildTemporarily set volume: 1.0 in your provider config and click a Button with sound="interaction.tap". You should hear the tap sound.
If you hear nothing:
SensoryUIProvider wraps the component you are testingenabled: truecomponents/ui/sensory-ui/sounds/packs.ts and verify it exports sound pack objects)AudioContext. Chrome suspends it until a user gesture. The engine resumes it automatically on the first playSound() call.Browsers suspend AudioContext until a user gesture. The engine resumes it
automatically on the first playSound() call, but sounds triggered on mount
(without a click/tap) will be silent.
To update the engine and primitives to a newer version:
npx shadcn@latest add SatyamVyas04/sensory-ui/sensory-ui --overwriteThe --overwrite flag replaces the engine, config loader, primitive files, and the embedded sound modules in sounds/*.ts. No user-owned file is ever overwritten automatically.
There is no uninstall command. To remove sensory-ui:
components/ui/sensory-ui/sensory.config.js (if you created one)<SensoryUIProvider> from the root layout@/components/ui/sensory-ui/* back to their original shadcn imports| File/Directory | Owned by | Auto-updated |
|---|---|---|
components/ui/sensory-ui/config/engine.ts | sensory-ui | On add --overwrite |
components/ui/sensory-ui/config/provider.tsx | sensory-ui | On add --overwrite |
components/ui/sensory-ui/*.tsx | sensory-ui | On add --overwrite |
components/ui/sensory-ui/config/registry.ts | sensory-ui | On add --overwrite |
components/ui/sensory-ui/sounds/*.ts | sensory-ui (all packs) | On add --overwrite |
sensory.config.js | User | Never (user-owned) |