Skip to main content

Overview

The @budgetbee/ui package provides a comprehensive library of reusable React components built with shadcn/ui, Radix UI, and Tailwind CSS.

Installation

pnpm add @budgetbee/ui --filter your-package
Or in your package.json:
{
  "dependencies": {
    "@budgetbee/ui": "workspace:*"
  }
}

Package Information

{
  "name": "@budgetbee/ui",
  "description": "Core ui package",
  "type": "module"
}

Exports

// UI components from shadcn/ui
import { Button } from "@budgetbee/ui/core/button";
import { Dialog } from "@budgetbee/ui/core/dialog";
import { Card } from "@budgetbee/ui/core/card";
import { Input } from "@budgetbee/ui/core/input";
import { Select } from "@budgetbee/ui/core/select";

Available Components

BudgetBee UI includes 30+ production-ready components:

Accordion

Collapsible content sections

Alert Dialog

Modal dialog for important actions

Avatar

User profile images with fallback

Badge

Small labels and tags

Breadcrumb

Navigation breadcrumbs

Button

Interactive buttons with variants

Calendar

Date picker calendar

Card

Content container

Carousel

Image and content carousel

Chart

Data visualization with Recharts

Checkbox

Checkboxes with tree support

Collapsible

Expandable content areas

Command

Command palette / search

Context Menu

Right-click context menu

Dialog

Modal dialogs

Drawer

Side drawer panels

Dropdown Menu

Dropdown menus

Empty State

Empty state placeholders

Input

Text input fields

Label

Form labels
And many more: menubar, navigation-menu, popover, progress, radio-group, resizable, select, separator, sheet, skeleton, slider, sonner, switch, table, tabs, textarea, toast, toggle, tooltip

Component Usage

Button

import { Button } from "@budgetbee/ui/core/button";

function MyComponent() {
  return (
    <div className="space-x-2">
      <Button>Default</Button>
      <Button variant="destructive">Delete</Button>
      <Button variant="outline">Outline</Button>
      <Button variant="ghost">Ghost</Button>
      <Button variant="link">Link</Button>
      <Button size="sm">Small</Button>
      <Button size="lg">Large</Button>
      <Button disabled>Disabled</Button>
    </div>
  );
}

Dialog

import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@budgetbee/ui/core/dialog";
import { Button } from "@budgetbee/ui/core/button";

function MyComponent() {
  return (
    <Dialog>
      <DialogTrigger asChild>
        <Button>Open Dialog</Button>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Are you sure?</DialogTitle>
          <DialogDescription>
            This action cannot be undone.
          </DialogDescription>
        </DialogHeader>
        <div className="flex justify-end gap-2">
          <Button variant="outline">Cancel</Button>
          <Button variant="destructive">Delete</Button>
        </div>
      </DialogContent>
    </Dialog>
  );
}

Card

import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@budgetbee/ui/core/card";
import { Button } from "@budgetbee/ui/core/button";

function MyComponent() {
  return (
    <Card>
      <CardHeader>
        <CardTitle>Budget Overview</CardTitle>
        <CardDescription>Your spending this month</CardDescription>
      </CardHeader>
      <CardContent>
        <p className="text-3xl font-bold">$2,450.00</p>
      </CardContent>
      <CardFooter>
        <Button>View Details</Button>
      </CardFooter>
    </Card>
  );
}

Input & Form

import { Input } from "@budgetbee/ui/core/input";
import { Label } from "@budgetbee/ui/core/label";
import { Button } from "@budgetbee/ui/core/button";

function MyComponent() {
  return (
    <form className="space-y-4">
      <div>
        <Label htmlFor="email">Email</Label>
        <Input 
          id="email" 
          type="email" 
          placeholder="[email protected]" 
        />
      </div>
      <div>
        <Label htmlFor="password">Password</Label>
        <Input 
          id="password" 
          type="password" 
        />
      </div>
      <Button type="submit">Sign In</Button>
    </form>
  );
}

Select

import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@budgetbee/ui/core/select";

function MyComponent() {
  return (
    <Select>
      <SelectTrigger className="w-[180px]">
        <SelectValue placeholder="Select a category" />
      </SelectTrigger>
      <SelectContent>
        <SelectItem value="groceries">Groceries</SelectItem>
        <SelectItem value="transport">Transport</SelectItem>
        <SelectItem value="entertainment">Entertainment</SelectItem>
      </SelectContent>
    </Select>
  );
}

Calendar

import { Calendar } from "@budgetbee/ui/core/calendar";
import { useState } from "react";

function MyComponent() {
  const [date, setDate] = useState<Date | undefined>(new Date());

  return (
    <Calendar
      mode="single"
      selected={date}
      onSelect={setDate}
      className="rounded-md border"
    />
  );
}

Toast Notifications

import { Toaster } from "@budgetbee/ui/core/sonner";
import { toast } from "sonner";
import { Button } from "@budgetbee/ui/core/button";

function MyComponent() {
  return (
    <>
      <Button onClick={() => toast.success('Transaction added!')}>
        Add Transaction
      </Button>
      <Toaster />
    </>
  );
}

Charts

BudgetBee UI includes chart components powered by Recharts:
import { AreaChart } from "@budgetbee/ui/core/chart";

function MyComponent() {
  const data = [
    { month: 'Jan', amount: 1200 },
    { month: 'Feb', amount: 1500 },
    { month: 'Mar', amount: 1800 },
  ];

  return (
    <AreaChart 
      data={data}
      categories={['amount']}
      index="month"
      className="h-72"
    />
  );
}

Theming

BudgetBee UI supports dark mode via next-themes:
import { ThemeProvider } from "next-themes";

function App({ children }: { children: React.ReactNode }) {
  return (
    <ThemeProvider
      attribute="class"
      defaultTheme="system"
      enableSystem
      disableTransitionOnChange
    >
      {children}
    </ThemeProvider>
  );
}

Theme Toggle

import { useTheme } from "next-themes";
import { Button } from "@budgetbee/ui/core/button";

function ThemeToggle() {
  const { theme, setTheme } = useTheme();

  return (
    <Button
      variant="ghost"
      onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
    >
      Toggle Theme
    </Button>
  );
}

Utility Functions

cn() - Class Name Merger

Combine and merge Tailwind classes:
import { cn } from "@budgetbee/ui/lib/utils";

const className = cn(
  "text-lg font-bold",
  isActive && "text-blue-500",
  isDisabled && "opacity-50 cursor-not-allowed"
);

Styling with Tailwind

BudgetBee UI uses Tailwind CSS v4. Import the global styles in your app:
import "@budgetbee/ui/globals.css";

PostCSS Configuration

Use the shared PostCSS config:
import config from "@budgetbee/ui/postcss.config";

export default config;

Adding New Components

To add a new shadcn/ui component:
cd packages/ui
pnpm shadcn:add <component-name>
Example:
pnpm shadcn:add dropdown-menu
This will:
  1. Download the component from shadcn/ui
  2. Add it to packages/ui/core/
  3. Install any required dependencies
Components are added to packages/ui/core/ directory as specified in components.json

Dependencies

Key dependencies used by @budgetbee/ui:
{
  "dependencies": {
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "cmdk": "^1.1.1",
    "date-fns": "^4.1.0",
    "embla-carousel-react": "^8.6.0",
    "lucide-react": "^0.475.0",
    "next-themes": "^0.4.6",
    "radix-ui": "^1.4.3",
    "react-day-picker": "^9.11.1",
    "recharts": "2.15.4",
    "sonner": "^2.0.7",
    "tailwind-merge": "^3.3.1"
  }
}

Component Customization

All components accept className prop for customization:
import { Button } from "@budgetbee/ui/core/button";

// Add custom classes
<Button className="bg-gradient-to-r from-blue-500 to-purple-500">
  Gradient Button
</Button>

// Override default styles
<Button className="rounded-full px-8">
  Custom Shape
</Button>

Accessibility

All components follow accessibility best practices:
  • Keyboard navigation - Full keyboard support
  • ARIA attributes - Proper ARIA labels and roles
  • Focus management - Clear focus indicators
  • Screen reader support - Semantic HTML and labels
Components are built on Radix UI primitives which handle most accessibility concerns automatically.

Best Practices

Use cn() utility

Always use cn() to merge Tailwind classes safely

Import only what you need

Import specific components to keep bundle size small

Consistent spacing

Use Tailwind spacing scale consistently across components

Responsive design

Use responsive Tailwind classes for mobile-friendly UIs

Responsive Design

Use Tailwind’s responsive prefixes:
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
  <Card>...</Card>
  <Card>...</Card>
  <Card>...</Card>
</div>

Animation

Components include built-in animations via tw-animate-css:
import { Dialog } from "@budgetbee/ui/core/dialog";

// Animations are automatic
<Dialog>
  {/* Content animates in/out */}
</Dialog>

Documentation

For detailed component documentation, visit:

Troubleshooting

Styles not applying

Ensure you’ve imported the global CSS:
import "@budgetbee/ui/globals.css";

TypeScript errors

Make sure you have the correct React types installed:
pnpm add -D @types/react @types/react-dom

Dark mode not working

Wrap your app with ThemeProvider:
import { ThemeProvider } from "next-themes";

function App({ children }) {
  return (
    <ThemeProvider attribute="class">
      {children}
    </ThemeProvider>
  );
}

Next Steps

Core Package

Explore authentication and database utilities

Billing Package

Learn about subscription management

Build docs developers (and LLMs) love