Introduction
Beautifully designed components for Remix 3. A faithful port of shadcn/ui, works with the shadcn CLI.
shadcn-remix is shadcn/ui for Remix 3: the same components, the same API and the same styles, written with remix/component and its css() mixin, with behavior from the @remix-run/ui headless primitives.
Philosophy
shadcn-remix follows the shadcn model: copy-paste components you own, with zero lock-in and sensible defaults that work immediately. It is not a component library you install — it is the source, distributed through a shadcn registry.
Remix 3 components are not React components. A component is a setup function that returns a render function, styles are mixins instead of class names, and interactivity hydrates per clientEntry. shadcn-remix keeps the shadcn/ui API — names, props, variants and data-* attributes — and translates only what the runtime requires.
Why shadcn-remix?
- Own Your Code: Every component is one file in
app/ui. Change anything. - Exact Port: Tailwind classes are translated declaration by declaration, so components match ui.shadcn.com pixel for pixel.
- Server First: Components render on the server; only interactive ones hydrate.
- No Build Step: Styles are generated by
css()at render time — no Tailwind, no PostCSS.
Features
From shadcn/ui to Remix
| shadcn/ui (React) | shadcn-remix |
|---|---|
className="w-40" | mix={css({ width: '10rem' })} |
<Button asChild><a href="/" /></Button> | <a href="/" mix={buttonVariants()} /> |
<DialogTrigger asChild><Button /></DialogTrigger> | <DialogTrigger mix={buttonVariants({ variant: 'outline' })} /> |
useState + onCheckedChange | let checked = false + handle.update() |
lucide-react | #app/ui/icons.tsx (same icon names) |