Drivn vs shadcn/ui — Button Component Compared
Side-by-side comparison of the Drivn and shadcn/ui React Button components — runtime deps, bundle size, API style, variants, and accessibility.
Both Drivn and shadcn/ui distribute their React components as copy-paste source code that lives in your repo. That is where the similarity ends. shadcn/ui's Button is a thin wrapper around Radix's Slot primitive with class-variance-authority for variant classes and clsx for merging. Drivn's Button is pure React plus Tailwind — no Radix, no cva, no clsx wrapper — with a const styles object holding every variant.
If you are choosing between the two for a new project or considering a migration, the practical differences are concrete: Drivn ships fewer runtime dependencies, a smaller per-component footprint, and a simpler variant API at the cost of a smaller ecosystem and fewer existing integrations. shadcn/ui has an enormous community with pre-built blocks, admin dashboards, and third-party integrations; Drivn does not, yet.
This page walks through each dimension — API shape, bundle footprint, customization story, accessibility model, and what Drivn does not do yet — with code on both sides so you can decide based on what you actually ship, not on which library has more GitHub stars or a longer sponsor list on the homepage.
Side-by-side comparison
| Feature | Drivn | shadcn/ui |
|---|---|---|
| Runtime UI dependencies | None (React + Tailwind) | @radix-ui/react-slot, cva, clsx |
| Variant API | const styles + keyof typeof | class-variance-authority (cva) |
| Icon prop | leftIcon / rightIcon (component) | children (JSX element) |
| Loading prop | ||
| Polymorphic (asChild) | ||
| Accessibility | Native button element | Radix Slot + native |
| License | MIT | MIT |
| Copy-paste install | ||
| TypeScript | Typed via keyof styles | Typed via VariantProps<typeof> |
| Next.js App Router | Works out of the box | Works out of the box |
API side-by-side
The two buttons converge on the same usage site: <Button variant="secondary">Click</Button>. Underneath, shadcn's Button uses cva to define variants and asChild to swap the rendered element via Slot. Drivn defines variants as a plain object indexed by variant and size, and renders a native <button> (see the Button docs).
For most buttons this is indistinguishable. The divergence shows up when you want to pass an icon or a loading state — Drivn accepts leftIcon={Plus} and loading={true} as first-class props, whereas shadcn expects you to embed icons and loading spinners as children.
1 // shadcn/ui 2 <Button variant="secondary"> 3 <Plus className="mr-2 h-4 w-4" /> New item 4 </Button> 5 6 // Drivn 7 <Button variant="secondary" leftIcon={Plus}> 8 New item 9 </Button>
Bundle size and runtime deps
shadcn/ui's Button imports @radix-ui/react-slot (~1.2 kB gzipped) plus class-variance-authority (~0.8 kB) plus clsx (~0.3 kB). Drivn's Button imports nothing beyond React and your cn() utility (which you likely already have). On a page with ten different components, the compounding difference is meaningful — tabs, dialog, and others in Drivn all skip these primitives.
None of this changes what ships in your node_modules. Both libraries copy source into your repo. The difference is what your final bundle pulls in when Next.js tree-shakes — Drivn pulls fewer modules because it imports fewer modules.
Customization
shadcn recommends extending variants via cva's cn() merge or by editing the buttonVariants function. Drivn recommends editing the styles object directly — add a key to variants, add a key to sizes, or change a class. Because the types read from keyof typeof styles, autocomplete updates on save.
For teams that prefer the cva pattern, shadcn will feel familiar. For teams that want fewer layers between "render a button" and the final markup, Drivn removes one level of indirection. Neither approach is objectively better — the question is which mental model matches your team.
What Drivn does not have
Drivn is younger and smaller than shadcn/ui. The ecosystem around shadcn — blocks, examples, community themes, third-party integrations — is larger by orders of magnitude. If you need a ready-made admin dashboard or marketing template built on your component library today, shadcn has more starting points.
Drivn also does not support asChild / polymorphic rendering. If your design system relies heavily on rendering the same props as different underlying elements (e.g., a button that is really a link), shadcn's Radix Slot pattern is more ergonomic. In Drivn you render a link and style it like a button, which some teams prefer for clarity.
Install Drivn in one command
Copy the source into your project and own every line. Zero runtime dependencies, pure React + Tailwind.
npx drivn@latest createRequires Node 18+. Works with npm, pnpm, and yarn.
Frequently asked questions
Only if you have concrete reasons — smaller bundle, preference for the dot notation API, or wanting to drop Radix from your dependency graph. If shadcn works well for your team and you are using its asChild pattern heavily, staying put is often the right call. Drivn is a better fit for teams starting fresh or replacing a handful of components at a time.
Yes. Drivn's Button renders a real <button> element with correct type, disabled, and aria-busy handling. Keyboard focus, native Enter/Space activation, and form submission work because the browser implements them on native elements. Drivn does not use Radix for accessibility — it relies on HTML semantics and adds ARIA only where needed.
Technically yes — both install into src/components/ui/ and both are copy-paste. You can gradually replace one with the other. In practice, maintaining two parallel component libraries creates style inconsistencies and doubles your bundle. Pick one and stick with it for the component families you care about.
Yes. The Button, like most Drivn primitives, works as a Server Component import unless it uses state or browser APIs. Components that need hooks are marked with "use client" at the top of the file — you can see which is which by opening the source in your repo. No wrapper or boundary configuration is needed.
The large shadcn ecosystem: third-party blocks, templates, community themes, and pre-built integrations. Drivn's library is smaller and newer. You also lose asChild polymorphism, which some teams use heavily for rendering links and menu items. For a greenfield project or a small surface area, the trade is usually acceptable.