๐Ÿ””Welcome

HaloLight multi-framework admin dashboard docs is now live!

Supports 12+ framework versions. Welcome to try.

Skip to content

Component Specification โ€‹

This document defines the UI component library specification for the HaloLight project, based on the shadcn/ui design system.

Component Library Overview โ€‹

Based on shadcn/ui โ€‹

All framework versions use the corresponding shadcn/ui implementation:

FrameworkComponent LibraryRepository
React/Next.jsshadcn/uishadcn/ui
Vue 3shadcn-vueshadcn-vue
Svelteshadcn-svelteshadcn-svelte
Angularspartan/uispartan
Solid.jssolid-uisolid-ui

Required Component Checklist โ€‹

Basic UI Components (30+) โ€‹

ui/
โ”œโ”€โ”€ accordion.tsx        # Accordion
โ”œโ”€โ”€ alert-dialog.tsx     # Alert dialog
โ”œโ”€โ”€ alert.tsx           # Alert
โ”œโ”€โ”€ avatar.tsx          # Avatar
โ”œโ”€โ”€ badge.tsx           # Badge
โ”œโ”€โ”€ breadcrumb.tsx      # Breadcrumb
โ”œโ”€โ”€ button.tsx          # Button
โ”œโ”€โ”€ calendar.tsx        # Calendar
โ”œโ”€โ”€ card.tsx            # Card
โ”œโ”€โ”€ checkbox.tsx        # Checkbox
โ”œโ”€โ”€ collapsible.tsx     # Collapsible
โ”œโ”€โ”€ command.tsx         # Command palette
โ”œโ”€โ”€ data-table.tsx      # Data table
โ”œโ”€โ”€ date-picker.tsx     # Date picker
โ”œโ”€โ”€ dialog.tsx          # Dialog
โ”œโ”€โ”€ dropdown-menu.tsx   # Dropdown menu
โ”œโ”€โ”€ form.tsx            # Form
โ”œโ”€โ”€ input.tsx           # Input
โ”œโ”€โ”€ label.tsx           # Label
โ”œโ”€โ”€ pagination.tsx      # Pagination
โ”œโ”€โ”€ popover.tsx         # Popover
โ”œโ”€โ”€ progress.tsx        # Progress
โ”œโ”€โ”€ radio-group.tsx     # Radio group
โ”œโ”€โ”€ scroll-area.tsx     # Scroll area
โ”œโ”€โ”€ select.tsx          # Select
โ”œโ”€โ”€ separator.tsx       # Separator
โ”œโ”€โ”€ sheet.tsx           # Sheet
โ”œโ”€โ”€ skeleton.tsx        # Skeleton
โ”œโ”€โ”€ slider.tsx          # Slider
โ”œโ”€โ”€ switch.tsx          # Switch
โ”œโ”€โ”€ table.tsx           # Table
โ”œโ”€โ”€ tabs.tsx            # Tabs
โ”œโ”€โ”€ textarea.tsx        # Textarea
โ”œโ”€โ”€ toast.tsx           # Toast
โ”œโ”€โ”€ tooltip.tsx         # Tooltip
โ””โ”€โ”€ sonner.tsx          # Toast notification

Layout Components โ€‹

layout/
โ”œโ”€โ”€ AdminLayout.tsx      # Admin main layout
โ”œโ”€โ”€ AuthLayout.tsx       # Auth page layout
โ”œโ”€โ”€ Sidebar.tsx          # Sidebar
โ”œโ”€โ”€ Header.tsx           # Header
โ”œโ”€โ”€ Footer.tsx           # Footer
โ”œโ”€โ”€ Breadcrumb.tsx       # Breadcrumb navigation
โ”œโ”€โ”€ TabsNav.tsx          # Tabs navigation
โ””โ”€โ”€ PageContainer.tsx    # Page container

Dashboard Components โ€‹

dashboard/
โ”œโ”€โ”€ DashboardGrid.tsx    # Draggable grid container
โ”œโ”€โ”€ WidgetWrapper.tsx    # Widget wrapper
โ”œโ”€โ”€ StatsWidget.tsx      # Stats card
โ”œโ”€โ”€ ChartWidget.tsx      # Chart widget
โ”œโ”€โ”€ TableWidget.tsx      # Table widget
โ”œโ”€โ”€ CalendarWidget.tsx   # Calendar widget
โ”œโ”€โ”€ TasksWidget.tsx      # Task list
โ””โ”€โ”€ QuickActionsWidget.tsx # Quick actions

Chart Components โ€‹

charts/
โ”œโ”€โ”€ LineChart.tsx        # Line chart
โ”œโ”€โ”€ BarChart.tsx         # Bar chart
โ”œโ”€โ”€ PieChart.tsx         # Pie chart
โ”œโ”€โ”€ AreaChart.tsx        # Area chart
โ”œโ”€โ”€ RadarChart.tsx       # Radar chart
โ””โ”€โ”€ GaugeChart.tsx       # Gauge

Component Design Specification โ€‹

1. Props Interface Design โ€‹

tsx
// Basic Props structure
interface ComponentProps {
  // Required props first
  children: React.ReactNode

  // Optional props in alphabetical order
  className?: string
  disabled?: boolean
  loading?: boolean
  size?: 'sm' | 'md' | 'lg'
  variant?: 'default' | 'outline' | 'ghost'

  // Event handlers
  onChange?: (value: T) => void
  onClick?: () => void
}

2. Style Variants โ€‹

Use cva (class-variance-authority) to define variants:

tsx
import { cva, type VariantProps } from 'class-variance-authority'

const buttonVariants = cva(
  // Base styles
  'inline-flex items-center justify-center rounded-md font-medium transition-colors',
  {
    variants: {
      variant: {
        default: 'bg-primary text-primary-foreground hover:bg-primary/90',
        outline: 'border border-input bg-background hover:bg-accent',
        ghost: 'hover:bg-accent hover:text-accent-foreground',
        destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
      },
      size: {
        sm: 'h-8 px-3 text-xs',
        md: 'h-9 px-4 text-sm',
        lg: 'h-10 px-6 text-base',
      },
    },
    defaultVariants: {
      variant: 'default',
      size: 'md',
    },
  }
)

export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {
  loading?: boolean
}

3. Accessibility (a11y) โ€‹

All components must support:

tsx
// ARIA attributes
<button
  role="button"
  aria-label={ariaLabel}
  aria-disabled={disabled}
  aria-busy={loading}
>

// Keyboard navigation
const handleKeyDown = (e: KeyboardEvent) => {
  if (e.key === 'Enter' || e.key === ' ') {
    onClick?.()
  }
  if (e.key === 'Escape') {
    onClose?.()
  }
}

// Focus management
const focusRef = useRef<HTMLElement>(null)
useEffect(() => {
  if (open) {
    focusRef.current?.focus()
  }
}, [open])

4. Responsive Design โ€‹

tsx
// Tailwind breakpoints
const breakpoints = {
  sm: '640px',   // Mobile landscape
  md: '768px',   // Tablet
  lg: '1024px',  // Small desktop
  xl: '1280px',  // Desktop
  '2xl': '1536px' // Large screen
}

// Responsive class example
<div className="
  grid
  grid-cols-1
  sm:grid-cols-2
  md:grid-cols-3
  lg:grid-cols-4
  gap-4
">

Layout Component Specification โ€‹

AdminLayout โ€‹

tsx
interface AdminLayoutProps {
  children: React.ReactNode
}

// Layout structure
<div className="min-h-screen bg-background">
  <Sidebar />
  <div className="flex flex-col lg:ml-64">
    <Header />
    <main className="flex-1 p-6">
      <PageContainer>
        {children}
      </PageContainer>
    </main>
    <Footer />
  </div>
</div>
tsx
interface SidebarState {
  collapsed: boolean      // Is collapsed
  mobileOpen: boolean    // Mobile open state
  activeMenu: string     // Current active menu
  openMenus: string[]    // Expanded submenus
}

// Collapse widths
const SIDEBAR_WIDTH = 256        // Expanded 16rem
const SIDEBAR_COLLAPSED = 64     // Collapsed 4rem

Header Component โ€‹

tsx
interface HeaderProps {
  showBreadcrumb?: boolean
  showSearch?: boolean
  showNotifications?: boolean
  showUserMenu?: boolean
}

// Component parts
<header className="h-16 border-b bg-background/95 backdrop-blur">
  <div className="flex items-center justify-between px-4 h-full">
    {/* Left side */}
    <div className="flex items-center gap-4">
      <SidebarTrigger />
      <Breadcrumb />
    </div>

    {/* Right side */}
    <div className="flex items-center gap-2">
      <GlobalSearch />
      <ThemeToggle />
      <NotificationDropdown />
      <UserDropdown />
    </div>
  </div>
</header>

Form Component Specification โ€‹

Form Field Structure โ€‹

tsx
<FormField
  control={form.control}
  name="email"
  render={({ field }) => (
    <FormItem>
      <FormLabel>Email</FormLabel>
      <FormControl>
        <Input placeholder="Enter email" {...field} />
      </FormControl>
      <FormDescription>
        We won't share your email
      </FormDescription>
      <FormMessage />
    </FormItem>
  )}
/>

Form Validation โ€‹

tsx
// Zod Schema
const formSchema = z.object({
  username: z.string().min(2, 'Username must be at least 2 characters').max(50),
  email: z.string().email('Please enter a valid email'),
  password: z.string().min(8, 'Password must be at least 8 characters'),
  confirmPassword: z.string(),
}).refine((data) => data.password === data.confirmPassword, {
  message: 'Passwords do not match',
  path: ['confirmPassword'],
})

Data Table Specification โ€‹

DataTable Features โ€‹

tsx
interface DataTableProps<T> {
  columns: ColumnDef<T>[]
  data: T[]

  // Pagination
  pagination?: boolean
  pageSize?: number

  // Sorting
  sorting?: boolean
  defaultSort?: { id: string; desc: boolean }

  // Filtering
  filtering?: boolean
  globalFilter?: boolean

  // Selection
  selection?: boolean
  onSelectionChange?: (rows: T[]) => void

  // Actions
  actions?: (row: T) => React.ReactNode
}

Column Definition Example โ€‹

tsx
const columns: ColumnDef<User>[] = [
  {
    id: 'select',
    header: ({ table }) => (
      <Checkbox
        checked={table.getIsAllPageRowsSelected()}
        onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
      />
    ),
    cell: ({ row }) => (
      <Checkbox
        checked={row.getIsSelected()}
        onCheckedChange={(value) => row.toggleSelected(!!value)}
      />
    ),
  },
  {
    accessorKey: 'name',
    header: 'Name',
    cell: ({ row }) => <span className="font-medium">{row.getValue('name')}</span>,
  },
  {
    accessorKey: 'email',
    header: ({ column }) => (
      <Button variant="ghost" onClick={() => column.toggleSorting()}>
        Email
        <ArrowUpDown className="ml-2 h-4 w-4" />
      </Button>
    ),
  },
  {
    accessorKey: 'status',
    header: 'Status',
    cell: ({ row }) => (
      <Badge variant={row.getValue('status') === 'active' ? 'default' : 'secondary'}>
        {row.getValue('status')}
      </Badge>
    ),
    filterFn: (row, id, value) => value.includes(row.getValue(id)),
  },
  {
    id: 'actions',
    cell: ({ row }) => <RowActions row={row.original} />,
  },
]