Skip to content
Drivn logoDrivn
5 min read

Drivn vs shadcn/ui — Card Component Compared

Drivn and shadcn/ui Card components compared — dot notation vs six named exports, built-in hover lift, fixed showcase sizing, and zero runtime UI deps.

Drivn and shadcn/ui both ship a Card component, but the two are tuned for different jobs. shadcn/ui exposes a generic flex column with six named sub-exports — CardHeader, CardTitle, CardDescription, CardContent, CardFooter, plus CardAction — and lets you decide how big the card is, how it sits in a grid, and whether it should react to hover. Drivn collapses the same surface into two slots, Card.Preview and Card.Info, mounted on the root via dot notation, and bakes a fixed w-48 aspect-square showcase footprint into the base style.

That shape is opinionated on purpose. The Drivn Card is built for the pattern that comes up over and over in component galleries, design system docs, dashboards, and storefronts: an icon or illustration at the top, a title and short description at the bottom, and a hover lift that signals interactivity. Both libraries render plain divs with border and rounded classes. The difference is how much you write per card and how many imports you carry.

This page compares the two APIs side by side: import surface, sub-component count, hover behavior, sizing defaults, and the kind of layout each ships ready for. Every snippet is verbatim from the Card source the Drivn CLI writes into your repo, so you can read this page next to your editor and the imports line up without translation.

Side-by-side comparison

FeatureDrivnshadcn/ui
API styleDot notation (Card.Preview, Card.Info)Six named exports (CardHeader, CardTitle, …)
Sub-components2 slots6 components
Default sizew-48 aspect-square (fixed)Fluid, full-width
Built-in hover lifthover prop (default true)Add classes manually
Runtime UI depsNoneNone
Border radiusrounded-[20px]rounded-xl
Preview / info layoutBuilt-in flex splitCompose with utility classes
TypeScriptRequiredRequired
LicenseMITMIT
Copy-paste install

Import surface

shadcn/ui exports six named components from one file: Card, CardHeader, CardTitle, CardDescription, CardContent, and CardFooter. Each one is a styled div, and you compose them in the order the layout needs. Drivn exports a single object — Card — with two children mounted on it: Card.Preview and Card.Info. One import line covers the whole component, and the dot access lets a reader see at a glance which div is the visual area and which is the text area.

The trade-off is reach. shadcn's six exports cover blog cards, profile cards, dashboard widgets, settings panels — anything where a header, body, and footer compose differently. Drivn's two slots cover the pattern Drivn cares about: a square showcase tile with an illustration on top and a label on the bottom. If your card has a header bar, body paragraph, and footer button row, shadcn fits better. If your card is a gallery item or component preview, Drivn writes in fewer lines. Pick the one that matches the shape you actually render. The full Card docs cover both slots in detail.

1// shadcn/ui — six named exports
2import {
3 Card,
4 CardHeader,
5 CardTitle,
6 CardDescription,
7 CardContent,
8 CardFooter,
9} from '@/components/ui/card'
10
11// Drivn — one import, dot notation
12import { Card } from '@/components/ui/card'

Sizing and layout defaults

Drivn's Card carries a fixed w-48 aspect-square footprint plus a vertical flex layout where Card.Preview claims flex-1 and Card.Info sits below it with p-5 padding and a horizontal flex split. That makes a Drivn Card a 192px × 192px tile by default, with the preview filling whatever vertical space the info row leaves. shadcn/ui's Card has no width or height — it stretches to fill its parent and stacks children vertically with a gap-6 between them.

When you need a different tile size in Drivn, override the width with a className on the root: <Card className="w-64">…</Card>. The aspect-square stays in effect unless you also override it. shadcn requires no override because it has no defaults to fight, but the cost is more utility classes per usage to lock in a consistent grid. For a gallery of equal-sized tiles, Drivn's defaults save a grid template column dance. For a settings panel, shadcn's flexibility wins. The Card examples page shows the gallery pattern in full.

1// Drivn — fixed showcase tile, vertical flex split
2<Card>
3 <Card.Preview>
4 <span className="text-2xl"></span>
5 </Card.Preview>
6 <Card.Info>
7 <p className="text-sm font-semibold">Card title</p>
8 </Card.Info>
9</Card>
10
11// shadcn/ui — fluid width, six children
12<Card>
13 <CardHeader>
14 <CardTitle>Title</CardTitle>
15 <CardDescription>Description</CardDescription>
16 </CardHeader>
17 <CardContent>Body</CardContent>
18 <CardFooter>Footer</CardFooter>
19</Card>

Hover behavior

Drivn ships hover behavior as a prop. The base classes always carry transition-all duration-200, and when hover is true (the default) the component applies hover:bg-accent hover:border-border hover:-translate-y-1. That last class is the one that does the visible lift — a 4px upward translation that signals the tile is interactive. To opt out, pass hover={false} and the same Card renders as a static container.

shadcn/ui treats hover as styling you write per usage. The base Card has no transition or hover class, which means a Card inside a button is just as static as one inside a marketing section. Both approaches are valid: Drivn is opinionated about gallery and showcase contexts where hover signals affordance, and shadcn stays neutral so you can decide. If you want the Drivn behavior in shadcn, copy the hover: triplet onto your Card. If you want a static Drivn Card, set hover={false}.

1// Drivn — hover lift built in (toggle off with prop)
2<Card hover={false}>
3 <Card.Preview>Static preview</Card.Preview>
4 <Card.Info>No hover lift</Card.Info>
5</Card>
6
7// shadcn/ui — hover styling per usage
8<Card className="transition-all hover:bg-accent hover:-translate-y-1">
9 <CardHeader>
10 <CardTitle>Hover lift</CardTitle>
11 </CardHeader>
12</Card>

When each one fits

Reach for shadcn/ui's Card when the layout has a meaningful header / body / footer split — settings panels, blog post previews, dashboard metric cards with an action bar, profile summaries with avatar plus stats. The six-export surface is exactly the shape those layouts need, and the lack of size defaults lets the card flex to whatever container holds it.

Reach for Drivn's Card when you are rendering a uniform grid of square tiles with an illustration up top and a label below — component galleries, plugin marketplaces, product card grids, design system documentation. Drivn's defaults take the design decisions out of your hands so the grid stays visually consistent across every usage. If you find yourself overriding w-, aspect-, and hover: classes on every shadcn Card to land at the same showcase shape, switch. If you find yourself fighting the w-48 aspect-square default on every Drivn Card to make it stretch, switch back. The Drivn CLI installs the source either way, so the migration is a copy and replace.

1// Drivn — fits a square showcase grid
2<div className="grid grid-cols-3 gap-4">
3 {items.map((item) => (
4 <Card key={item.id}>
5 <Card.Preview>{item.icon}</Card.Preview>
6 <Card.Info>
7 <p className="text-sm font-semibold">{item.name}</p>
8 </Card.Info>
9 </Card>
10 ))}
11</div>
Get started

Install Drivn in one command

Copy the source into your project and own every line. Zero runtime dependencies, pure React + Tailwind.

npx drivn@latest create

Requires Node 18+. Works with npm, pnpm, and yarn.

Enjoying Drivn?
Star the repo on GitHub to follow new component releases.
Star →

Frequently asked questions

Drivn's Card is built for showcase grids — component galleries, plugin marketplaces, design system docs — where a square tile with an illustration on top and a label on the bottom is the dominant pattern. Two slots cover that shape with the fewest moving parts. If you need a richer card with header, body, and footer rows, override the slots with utility classes or use shadcn/ui's Card, which is tuned for that case.

Yes. The className prop on the Card root merges with the base classes via the cn utility, so passing <Card className="w-full aspect-auto"> overrides both width and aspect ratio. The flex layout, border, and rounded corners stay intact unless you also override them. The fixed defaults exist for the gallery use case — they are a starting point, not a constraint.

No. The component is plain React plus Tailwind. The source imports React and a cn class merger and that is it — no Radix slot, no cva, no floating-ui. Same is true of shadcn/ui's Card on this axis. Both pages render to ordinary divs, and the only difference at runtime is the tree shape and which classes you wrote.

Map shadcn's CardHeader plus CardContent onto Drivn's Card.Preview, and CardFooter onto Card.Info. Keep your existing className overrides; they merge through Drivn's cn utility the same way. If your card has more than two regions, fold the extra rows into either slot with utility classes — the slot is a div, so any flex or grid arrangement works inside it. The migration is mechanical for showcase tiles and harder for editorial layouts where shadcn's six-slot model is the better fit.