shadcn/ui components
shadcn-style Tailwind components (@valora-ai/react/shadcn) built on the headless primitives.
@valora-ai/react/shadcn is a shadcn/ui-flavored skin — Tailwind-styled Button,
Toggle, and Select — built on the same headless primitives
as the Teams design system. If your app already uses shadcn/Tailwind, these drop in
with a familiar API.
npm install @valora-ai/reactimport { Button, Toggle, Select } from "@valora-ai/react/shadcn";Tailwind setup
The components ship Tailwind utility class names, so Tailwind must scan the package
or it will purge those classes in production. Add the dist bundle to your content:
// tailwind.config.js
export default {
darkMode: "class",
content: [
"./src/**/*.{ts,tsx}",
"./node_modules/@valora-ai/react/dist/shadcn.js", // ← required
],
};No stylesheet import is needed — Tailwind generates the CSS from the class names.
Components
Button
variant: default · secondary · outline · ghost · destructive · link.
size: default · sm · lg · icon. Supports asChild (renders onto your
element) and disabled. Built on ControlButtonPrimitive.
<Button>Save</Button>
<Button variant="outline" size="sm">Cancel</Button>
<Button variant="destructive">Leave call</Button>
<Button asChild><a href="/docs">Docs</a></Button>Toggle
Pressed state, controlled or uncontrolled. Visual state comes from the underlying
ControlButtonPrimitive's data-active attribute (data-[active]: Tailwind
variants), kept in sync with aria-pressed.
// controlled
<Toggle pressed={muted} onPressedChange={setMuted}>Mute</Toggle>
// uncontrolled
<Toggle defaultPressed variant="outline">Bold</Toggle>Select
A single-select dropdown built on PopoverPrimitive + ListboxPrimitive — so it
includes outside-click + Escape close and Arrow/Home/End keyboard navigation for
free. Controlled (value + onValueChange) or uncontrolled (defaultValue).
const voices = [
{ value: "aria", label: "Aria" },
{ value: "atlas", label: "Atlas" },
];
<Select options={voices} value={voice} onValueChange={setVoice} aria-label="Voice" />cn helper
cn(...classes) (exported) is a dependency-free class joiner. A className you
pass to a component is additive — it does not de-conflict Tailwind utilities the
way tailwind-merge does. If you need true override semantics, wrap with
tailwind-merge in your own cn.
Same behavior, different skin
| shadcn component | headless primitive(s) |
|---|---|
Button | ControlButtonPrimitive |
Toggle | ControlButtonPrimitive (data-active) |
Select | PopoverPrimitive + ListboxPrimitive |
See the runnable
examples/shadcn-react
app, and the headless layer it's built on.