Skip to content

Frontend

shadcn/ui — Why Aidxn Builds Every Project On Top of It

All articles
🧩 🎨

shadcn/ui isn't a component library. It's a code generator you control. Own your components. Radix under the hood, Tailwind for styling, TypeScript for type safety — accessibility and theming baked in. This is how production design systems ship in 2026.

Most teams use Material UI, Chakra, or Mantine and then spend three years fighting their design system instead of shipping features. Buttons look wrong, the grid doesn't align, and when you need a custom variant, you're digging into theme config that someone else wrote. The library owns your component, and when you need to deviate, you're overriding with `sx` or `styled` or inline CSS. By the time you're three projects deep, you've built a fragmented mess of design hacks.

shadcn/ui flips this. It's not a library you install and import from. It's a CLI that drops component source code directly into your project. You run `npx shadcn-ui@latest add button`, and it copies the Button component into `src/components/ui/button.tsx`. You own the code. Want to add a loading spinner to the button? Edit the file. Need a custom color variant? Modify the props. The component isn't a black box — it's your code, and you can read every line. This is why Aidxn builds every production project on top of shadcn, and why Velocity X's dashboard (Dialog, DropdownMenu, NavigationMenu, ContextMenu, Tabs) ships shadcn across the board.

Why shadcn Beats Material UI, Mantine, and Chakra

Material UI is heavy — 90KB minified. You bundle the entire library, the theme system, and hundreds of components you'll never use. Customization is indirect: reach for the `sx` prop or theme overrides, and you're editing config files instead of reading code. Chakra is lighter (30KB), and the theming is cleaner, but you're still importing from a library and trusting that their API is stable. Mantine ships beautiful components and good docs, but you're locked into Mantine's design language. Moving to a new brand means overriding colors everywhere or forking the library.

shadcn is different because there's no library to lock you into. The CLI copies Radix UI primitives (unstyled, accessible components) and pairs them with Tailwind CSS classes. The result: you get the accessibility for free (Radix handles ARIA attributes, keyboard navigation, focus management), and you style with Tailwind (no CSS-in-JS overhead, no runtime parsing). When you need to customize, you're editing your own code. When you onboard a new brand (HailHero, Staff Operations Dashboard, Rebuild Relief), you copy the components, update the color tokens, and ship. No theme config gymnastics. No library fighting back.

Bundle size: Material UI 90KB, Chakra 30KB, Mantine 40KB. shadcn components (alone) are 15–30KB depending on which ones you add. Radix + Tailwind are already in your deps, so the marginal cost is just the component code.

Customization: Material UI needs `sx` or theme config. Chakra needs `useStyleConfig`. Mantine needs style props. shadcn: edit the file.

Accessibility: Material, Chakra, Mantine all bundle Radix internally. shadcn uses Radix directly, so you're trusting the same source.

Installation and Setup

Start with a React + Tailwind project (or Astro with React islands). Install shadcn-ui CLI:

npx shadcn-ui@latest init

Answer the prompts: TypeScript? Yes. CSS variable setup? Yes (shadcn creates a `globals.css` with design tokens). Then add components as you need them:

npx shadcn-ui@latest add button
npx shadcn-ui@latest add dialog
npx shadcn-ui@latest add dropdown-menu
npx shadcn-ui@latest add tabs

Each command adds a new file to `src/components/ui/`. They're TypeScript by default, fully typed, and ready to customize. The CLI also sets up color tokens in `globals.css` using CSS variables — this is where theming lives. For Velocity X, every project re-exports these components from a central index:

// src/components/ui/index.ts
export { Button } from './button';
export { Dialog, DialogContent, DialogHeader } from './dialog';
export { DropdownMenu, DropdownMenuContent, DropdownMenuItem } from './dropdown-menu';
export { Tabs, TabsContent, TabsList, TabsTrigger } from './tabs';

Everywhere else: `import { Button, Dialog } from '@/components/ui'`. One place to see the catalog.

Four Essential Components, Explained

1. Button — The Fundamental

The Button component is tiny but dense. Radix provides no visual output — it's just a `

Let us make some quick suggestions?
Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.