Skip to content

UI Component Library

Package: @nexischat/ui Design System: Atomic Design (Atoms → Molecules → Organisms) Styling: TailwindCSS 4 + Radix UI primitives Testing: Storybook 9 + Vitest + Chromatic Generated: 2026-01-04

The shared UI component library follows Atomic Design principles:

  • Atoms: Basic building blocks (buttons, inputs, badges)
  • Molecules: Combinations of atoms (form fields, cards with actions)
  • Organisms: Complex components (chat lists, subscription panels)

All components are built with:

  • TypeScript for type safety
  • Radix UI for accessible primitives
  • TailwindCSS 4 for styling
  • cva for variant management
  • Full dark mode support via CSS variables
Terminal window
pnpm add @nexischat/ui

Primary action component with multiple variants.

import { Button } from '@nexischat/ui/atoms/button'
;<Button variant="default" size="md" disabled={false}>
Click Me
</Button>

Variants: default, destructive, outline, secondary, ghost, link Sizes: sm, default, lg, icon


Text input with optional icon slots.

import { Input } from '@nexischat/ui/atoms/input'
;<Input type="text" placeholder="Enter text..." startIcon={<SearchIcon />} />

Status indicators and labels.

import { Badge } from '@nexischat/ui/atoms/badge'
<Badge variant="default">Active</Badge>
<Badge variant="secondary">Pending</Badge>
<Badge variant="destructive">Error</Badge>
<Badge variant="outline">Draft</Badge>

User/contact profile images with fallback.

import { Avatar, AvatarImage, AvatarFallback } from '@nexischat/ui/atoms/avatar'
;<Avatar>
<AvatarImage src={user.avatar} alt={user.name} />
<AvatarFallback>{user.initials}</AvatarFallback>
</Avatar>

Toggle inputs.

import { Checkbox } from '@nexischat/ui/atoms/checkbox'
import { Switch } from '@nexischat/ui/atoms/switch'
<Checkbox checked={value} onCheckedChange={setValue} />
<Switch checked={enabled} onCheckedChange={setEnabled} />

Form labels with accessibility.

import { Label } from '@nexischat/ui/atoms/label'
;<Label htmlFor="email">Email Address</Label>

Visual dividers.

import { Separator } from '@nexischat/ui/atoms/separator'
;<Separator orientation="horizontal" />

Loading placeholders.

import { Skeleton } from '@nexischat/ui/atoms/skeleton'
;<Skeleton className="h-4 w-[200px]" />

Loading indicators.

import { Spinner } from '@nexischat/ui/atoms/spinner'
;<Spinner size="md" />

Text components with semantic variants.

import { Heading, Text, Paragraph } from '@nexischat/ui/atoms/typography'
<Heading level={1}>Main Title</Heading>
<Paragraph>Body text content...</Paragraph>
<Text variant="muted">Secondary text</Text>

  • ScrollArea - Custom scrollbars
  • Textarea - Multi-line text input
  • Progress - Progress bars
  • Tooltip - Hover hints
  • KBD - Keyboard shortcuts display

Content containers with header, content, footer.

import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter
} from '@nexischat/ui/molecules/card'
;<Card>
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card description</CardDescription>
</CardHeader>
<CardContent>{/* Content */}</CardContent>
<CardFooter>
<Button>Action</Button>
</CardFooter>
</Card>

Modal dialogs with accessible focus management.

import {
Dialog,
DialogTrigger,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter,
DialogClose
} from '@nexischat/ui/molecules/dialog'
;<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Dialog Title</DialogTitle>
<DialogDescription>Description text</DialogDescription>
</DialogHeader>
{/* Content */}
<DialogFooter>
<DialogClose asChild>
<Button variant="outline">Cancel</Button>
</DialogClose>
<Button>Confirm</Button>
</DialogFooter>
</DialogContent>
</Dialog>

Context menus and action menus.

import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator
} from '@nexischat/ui/molecules/dropdown-menu'
;<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon">
<MoreVertical />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>Edit</DropdownMenuItem>
<DropdownMenuItem>Duplicate</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem variant="destructive">Delete</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>

Form handling with react-hook-form integration.

import {
Form,
FormField,
FormItem,
FormLabel,
FormControl,
FormDescription,
FormMessage
} from '@nexischat/ui/molecules/form'
;<Form {...form}>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormDescription>Your work email</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</Form>

Dropdown selection with search.

import {
Select,
SelectTrigger,
SelectValue,
SelectContent,
SelectItem
} from '@nexischat/ui/molecules/select'
;<Select value={value} onValueChange={setValue}>
<SelectTrigger>
<SelectValue placeholder="Select..." />
</SelectTrigger>
<SelectContent>
<SelectItem value="option1">Option 1</SelectItem>
<SelectItem value="option2">Option 2</SelectItem>
</SelectContent>
</Select>

Tabbed interfaces.

import { Tabs, TabsList, TabsTrigger, TabsContent } from '@nexischat/ui/molecules/tabs'
;<Tabs defaultValue="tab1">
<TabsList>
<TabsTrigger value="tab1">Tab 1</TabsTrigger>
<TabsTrigger value="tab2">Tab 2</TabsTrigger>
</TabsList>
<TabsContent value="tab1">Content 1</TabsContent>
<TabsContent value="tab2">Content 2</TabsContent>
</Tabs>

Notifications and confirmation dialogs.

import { Alert, AlertTitle, AlertDescription } from '@nexischat/ui/molecules/alert'
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel
} from '@nexischat/ui/molecules/alert-dialog'
;<Alert variant="destructive">
<AlertTitle>Error</AlertTitle>
<AlertDescription>Something went wrong.</AlertDescription>
</Alert>

Toast notifications (via Sonner).

import { toast } from '@nexischat/ui/molecules/sonner'
toast.success('Message sent!')
toast.error('Failed to send message')
toast.loading('Sending...')

  • Accordion - Collapsible sections
  • Collapsible - Toggle visibility
  • Command - Command palette (cmdk)
  • Popover - Floating content
  • Sheet - Slide-out panels
  • Table - Data tables
  • Breadcrumb - Navigation path
  • Pagination - Page navigation
  • RadioGroup - Single selection
  • Slider - Range input
  • Calendar - Date picker
  • HoverCard - Rich hover content

Chat conversation preview card.

import { ConversationCard } from '@nexischat/ui/organisms/conversation-card'
;<ConversationCard
conversation={{
id: '123',
name: 'John Doe',
lastMessage: 'Hello!',
timestamp: new Date(),
unreadCount: 3,
avatar: '/avatars/john.jpg',
isOnline: true
}}
isSelected={selected}
onClick={() => selectConversation('123')}
/>

Individual chat message bubble.

import { MessageItem } from '@nexischat/ui/organisms/message-item'
;<MessageItem
message={{
id: 'msg1',
content: 'Hello, how are you?',
timestamp: new Date(),
sender: { name: 'John', avatar: '...' },
isOwn: false,
status: 'read'
}}
/>

Scrollable conversation list.

import { ChatList } from '@nexischat/ui/organisms/chat-list'
;<ChatList
conversations={conversations}
selectedId={selectedConversationId}
onSelect={setSelectedConversationId}
isLoading={isLoading}
/>

App navigation sidebar.

import {
Sidebar,
SidebarHeader,
SidebarContent,
SidebarFooter
} from '@nexischat/ui/organisms/sidebar'
;<Sidebar>
<SidebarHeader>
<Logo />
</SidebarHeader>
<SidebarContent>
<NavLinks />
</SidebarContent>
<SidebarFooter>
<UserMenu />
</SidebarFooter>
</Sidebar>

Pricing table component.

import { SubscriptionPlans } from '@nexischat/ui/organisms/subscription-plans'
;<SubscriptionPlans currentPlan="free" onSelectPlan={handleSelectPlan} isLoading={isCheckingOut} />

Full-featured data table with sorting, filtering, pagination.

import { DataTable } from '@nexischat/ui/organisms/data-table'
;<DataTable columns={columns} data={data} searchKey="name" pagination sorting />

  • AccountSelector - WhatsApp account switcher
  • FolderList - Chat folder management
  • TemplateEditor - Message template editing
  • QRCodeScanner - WhatsApp QR auth display
  • ProfileEditor - User profile form
import { cn } from '@nexischat/ui/lib/utils'
;<div className={cn('base-class', conditional && 'conditional-class')} />
import { ThemeProvider } from '@nexischat/ui/providers/theme'
;<ThemeProvider defaultTheme="system" storageKey="nexischat-theme">
<App />
</ThemeProvider>

Run Storybook locally:

Terminal window
cd packages/ui
pnpm storybook

Stories are located alongside components:

src/
atoms/
button/
button.tsx
button.stories.tsx
molecules/
card/
card.tsx
card.stories.tsx

Components are tested with:

  • Unit Tests: Vitest + Testing Library
  • Visual Regression: Chromatic
  • Accessibility: axe-core via Storybook
Terminal window
# Run unit tests
pnpm test
# Run Storybook tests
pnpm test:storybook

CSS variables are defined in src/styles/globals.css:

:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--primary: 142.1 76.2% 36.3%;
--primary-foreground: 355.7 100% 97.3%;
/* ... */
}
.dark {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
/* ... */
}