Skip to content

shadcn/ui Component Collection - Quick Start Guide

You can add ALL 50+ shadcn/ui components to your monorepo in ~10 hours.

The NavigationMenu you already have proves your architecture works. Now scale it!


  • Radix UI understanding (it’s the foundation - not optional!)
  • NavigationMenu successfully integrated
  • Storybook running and configured
  • CSS variables setup complete
  • Tailwind config extended for shadcn/ui
  • Decision: Want ALL components or curated set?
  • Decision: Flat structure or categorized?

Section titled “🚀 Quick Start: Add All Components (Recommended)”
Terminal window
cd /Users/work-station/company/cloudalt-frontend
Terminal window
cd packages/ui-web
# Install ALL components at once
npx shadcn@latest add --all
# This installs:
# - 50+ component files
# - All Radix UI dependencies
# - All helper utilities
# - CSS variable updates

Time: 5-10 minutes Result: All components in packages/ui-web/src/components/ui/

Terminal window
cd packages/ui-web
# Core essentials (15 components)
npx shadcn@latest add button input textarea select checkbox radio-group switch label form badge avatar card alert dialog toast
# Navigation (5 components)
npx shadcn@latest add breadcrumb sidebar dropdown-menu
# Advanced (as needed)
npx shadcn@latest add table calendar chart carousel data-table

Time: 15-20 minutes Result: Curated set based on immediate needs

Section titled “Step 3: Organize Components (Optional but Recommended)”
Terminal window
# Run organization script
node scripts/organize-shadcn-components.js
# OR manually organize:
mkdir -p packages/ui-web/src/components/{forms,layout,feedback,data,navigation}
# Move components to categories
mv packages/ui-web/src/components/ui/button* packages/ui-web/src/components/forms/
mv packages/ui-web/src/components/ui/card* packages/ui-web/src/components/layout/
# ... etc
Terminal window
# Auto-generate stories for all components
node scripts/generate-shadcn-stories.js
# Result: 50+ .stories.tsx files in packages/storybook/stories/
packages/ui-web/src/index.ts
export * from './components/forms';
export * from './components/layout';
export * from './components/feedback';
export * from './components/data';
export * from './components/navigation';
export * from './lib/utils';
// OR if using flat structure:
export * from './components/ui';
Terminal window
# Restart Storybook
pkill -f storybook && yarn storybook
# Navigate to http://localhost:6006
# Look for new components in sidebar

  • 50+ Production-Ready Components
  • Full Accessibility (WCAG 2.1 AA compliant)
  • Keyboard Navigation (built-in)
  • Dark Mode Support (via CSS variables)
  • Responsive Design (mobile-first)
  • TypeScript Types (full type safety)
  • Customizable (own the code, modify anything)
  • Storybook Docs (interactive examples)
{
"@radix-ui/react-*": "~40 packages (primitives)",
"date-fns": "^4.1.0",
"react-day-picker": "^9.4.3",
"embla-carousel-react": "^8.5.2",
"recharts": "^2.15.0",
"sonner": "^1.7.3",
"vaul": "^1.1.2"
}

Bundle Impact: ~500KB gzipped (tree-shakeable)


  • Breadcrumb, Navigation Menu, Menubar, Command
  • Context Menu, Dropdown Menu, Pagination
  • Button, Input, Textarea, Select, Checkbox
  • Radio Group, Switch, Form, Label, Button Group
  • Toggle, Toggle Group, Slider
  • Card, Separator, Sheet, Drawer, Sidebar
  • Resizable, Scroll Area, Tabs, Collapsible, Aspect Ratio
  • Alert, Alert Dialog, Dialog, Toast, Sonner
  • Tooltip, Hover Card, Popover, Progress
  • Skeleton, Spinner
  • Table, Badge, Avatar, Calendar, Chart
  • Carousel, Accordion, Date Picker, Input OTP

packages/ui-stay-match/src/StayMatchButton/StayMatchButton.tsx
import { Button } from '@cloudalt-frontend/ui-web';
export function StayMatchButton(props: ButtonProps) {
return (
<Button
className="stay-match-brand"
variant="default"
{...props}
/>
);
}
packages/ui-web/src/components/forms/IconButton/IconButton.tsx
import { Button } from '../button';
import { LucideIcon } from 'lucide-react';
interface IconButtonProps extends ButtonProps {
icon: LucideIcon;
label?: string;
}
export function IconButton({ icon: Icon, label, ...props }: IconButtonProps) {
return (
<Button {...props}>
<Icon className="mr-2 h-4 w-4" />
{label}
</Button>
);
}
packages/ui-web/src/components/data/UserCard/UserCard.tsx
import { Card, CardHeader, CardContent } from '../../layout/card';
import { Avatar, AvatarImage, AvatarFallback } from '../avatar';
import { Badge } from '../badge';
export function UserCard({ user }: { user: User }) {
return (
<Card>
<CardHeader>
<Avatar>
<AvatarImage src={user.avatar} />
<AvatarFallback>{user.initials}</AvatarFallback>
</Avatar>
</CardHeader>
<CardContent>
<h3>{user.name}</h3>
<Badge>{user.role}</Badge>
</CardContent>
</Card>
);
}

import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/react';
import { Button } from './Button';
describe('Button', () => {
it('renders with text', () => {
render(<Button>Click me</Button>);
expect(screen.getByRole('button')).toHaveTextContent('Click me');
});
it('calls onClick handler', async () => {
const handleClick = vi.fn();
render(<Button onClick={handleClick}>Click me</Button>);
await userEvent.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledOnce();
});
});
import { axe } from 'jest-axe';
it('has no accessibility violations', async () => {
const { container } = render(<Button>Accessible</Button>);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
Terminal window
# Already configured in Storybook
yarn chromatic --project-token=<YOUR_TOKEN>

apps/docs/src/content/reference/components/[component-name].mdx
# Create docs in Astro site
node scripts/generate-component-docs.js
---
title: Button
description: A clickable button component with multiple variants
category: Forms
---
## Installation
\`\`\`bash
npx shadcn@latest add button
\`\`\`
## Usage
\`\`\`tsx
import { Button } from '@cloudalt-frontend/ui-web';
<Button variant="default">Click me</Button>
\`\`\`
## API Reference
...

Terminal window
# Check for updates
npx shadcn@latest diff
# Update specific component
npx shadcn@latest add button --overwrite
# Update all components
npx shadcn@latest add --all --overwrite
Terminal window
# Analyze bundle
yarn nx build ui-web --with-deps
yarn bundle-analyzer
# Check specific component impact
yarn bundle-buddy

A: No! Start with core set (20-25 components), add more as needed.

A: Yes! You own the code. Modify directly in packages/ui-web/src/.

A: Use npx shadcn@latest diff to see changes, manually merge updates.

A: Tree-shaking eliminates unused code. Only imported components are bundled.

A: No, shadcn/ui is web-only. Consider NativeWind for similar approach.

A: Basic understanding helps, but not required. shadcn/ui abstracts complexity.


  1. Decision Time: All components or selective?
  2. Run Installation: Choose approach (CLI bulk or selective)
  3. Generate Stories: Auto-create Storybook documentation
  4. Test in App: Import into one app (homestay) to verify
  5. Roll Out: Make available to all app divisions
  6. Document: Update Astro docs with usage examples
  7. Train Team: Show developers how to use component library

  • Radix UI is NOT optional - it’s the foundation
  • CSS variables must be configured - already done!
  • Tailwind config must extend shadcn theme - already done!
  • React 18+ required - you have it!
  • ⚠️ Test each component before production use
  • ⚠️ Commit working state before bulk changes
  • ⚠️ Update dependencies regularly for security patches


Ready to proceed? Let’s add all the components! 🚀