UI Patterns
Common UI patterns and component compositions in mdxui
UI Patterns
Learn common patterns for composing mdxui components to build complete user interfaces.
Form Patterns
Login Form
Combine Input, Button, and Card for authentication:
import { Card, CardHeader, CardTitle, CardContent, CardFooter } from '@mdxui/primitives'
import { Input, Label, Button } from '@mdxui/primitives'
<Card className="w-96">
<CardHeader>
<CardTitle>Sign In</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div>
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="you@example.com" />
</div>
<div>
<Label htmlFor="password">Password</Label>
<Input id="password" type="password" />
</div>
</CardContent>
<CardFooter>
<Button className="w-full">Sign In</Button>
</CardFooter>
</Card>Multi-Step Wizard
Use Multi-Step Form or Onboarding Wizard for complex flows:
import { Wizard } from '@mdxui/widgets'
<Wizard
steps={[
{ id: 'account', title: 'Account', fields: [...] },
{ id: 'profile', title: 'Profile', fields: [...] },
{ id: 'confirm', title: 'Confirm', fields: [...] }
]}
onComplete={(data) => console.log(data)}
/>Form Validation
Combine Form Builder with Zod schemas:
import { FormBuilder } from '@mdxui/primitives'
import { z } from 'zod'
const schema = z.object({
name: z.string().min(2),
email: z.string().email(),
age: z.number().min(18)
})
<FormBuilder schema={schema} onSubmit={handleSubmit} />Layout Patterns
Dashboard Layout
Combine Dashboard Shell with Sidebar:
import { DashboardShell, Sidebar, SidebarNav } from '@mdxui/primitives'
<DashboardShell>
<Sidebar>
<SidebarNav items={navItems} />
</Sidebar>
<main className="flex-1 p-6">
{/* Dashboard content */}
</main>
</DashboardShell>Resizable Panels
Create split-pane layouts:
import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@mdxui/primitives'
<ResizablePanelGroup direction="horizontal">
<ResizablePanel defaultSize={30}>
{/* Sidebar */}
</ResizablePanel>
<ResizableHandle />
<ResizablePanel defaultSize={70}>
{/* Main content */}
</ResizablePanel>
</ResizablePanelGroup>Card Grid
Responsive card layouts:
import { Card } from '@mdxui/primitives'
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{items.map(item => (
<Card key={item.id}>
{/* Card content */}
</Card>
))}
</div>Navigation Patterns
Top Navigation
Combine Navigation Menu with Dropdown Menu:
import { NavigationMenu, NavigationMenuItem } from '@mdxui/primitives'
<NavigationMenu>
<NavigationMenuItem>
<NavigationMenuLink href="/products">Products</NavigationMenuLink>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuTrigger>Solutions</NavigationMenuTrigger>
<NavigationMenuContent>
{/* Dropdown content */}
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenu>Breadcrumb Navigation
Show hierarchical location:
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink } from '@mdxui/primitives'
<Breadcrumb>
<BreadcrumbItem>
<BreadcrumbLink href="/">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbItem>
<BreadcrumbLink href="/products">Products</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbItem isCurrentPage>
<BreadcrumbLink>API</BreadcrumbLink>
</BreadcrumbItem>
</Breadcrumb>Command Palette
Global search and actions:
import { Command } from '@mdxui/primitives'
<Command>
<CommandInput placeholder="Type to search..." />
<CommandList>
<CommandGroup heading="Suggestions">
<CommandItem>Calendar</CommandItem>
<CommandItem>Settings</CommandItem>
</CommandGroup>
</CommandList>
</Command>Data Display Patterns
Data Table
Sortable, filterable tables:
import { Table, TableHeader, TableBody, TableRow, TableCell } from '@mdxui/primitives'
<Table>
<TableHeader>
<TableRow>
<TableCell>Name</TableCell>
<TableCell>Email</TableCell>
<TableCell>Role</TableCell>
</TableRow>
</TableHeader>
<TableBody>
{users.map(user => (
<TableRow key={user.id}>
<TableCell>{user.name}</TableCell>
<TableCell>{user.email}</TableCell>
<TableCell>{user.role}</TableCell>
</TableRow>
))}
</TableBody>
</Table>Stats Cards
Dashboard metrics:
import { Card, CardHeader, CardTitle, CardContent } from '@mdxui/primitives'
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<Card>
<CardHeader>
<CardTitle>Total Users</CardTitle>
</CardHeader>
<CardContent>
<div className="text-3xl font-bold">1,234</div>
<p className="text-sm text-muted-foreground">+12% from last month</p>
</CardContent>
</Card>
{/* More stat cards */}
</div>Timeline
Activity feeds and timelines:
import { Accordion, AccordionItem } from '@mdxui/primitives'
<Accordion type="single" collapsible>
{activities.map(activity => (
<AccordionItem key={activity.id} value={activity.id}>
<AccordionTrigger>{activity.title}</AccordionTrigger>
<AccordionContent>{activity.description}</AccordionContent>
</AccordionItem>
))}
</Accordion>Feedback Patterns
Toast Notifications
Non-blocking notifications:
import { toast } from 'sonner'
// Success
toast.success('Settings saved successfully')
// Error
toast.error('Failed to save settings')
// Loading
toast.loading('Saving...')
// Promise
toast.promise(saveSettings(), {
loading: 'Saving...',
success: 'Saved!',
error: 'Failed to save'
})Confirmation Dialogs
Confirm destructive actions:
import { AlertDialog, AlertDialogTrigger, AlertDialogContent } from '@mdxui/primitives'
<AlertDialog>
<AlertDialogTrigger>Delete</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Are you sure?</AlertDialogTitle>
<AlertDialogDescription>
This action cannot be undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction onClick={handleDelete}>Delete</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>Loading States
Show loading feedback:
import { Skeleton, Button } from '@mdxui/primitives'
{isLoading ? (
<Skeleton className="h-20 w-full" />
) : (
<div>{content}</div>
)}
<Button disabled={isLoading}>
{isLoading ? 'Loading...' : 'Submit'}
</Button>Modal Patterns
Form Modal
Edit items in a modal:
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@mdxui/primitives'
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogContent>
<DialogHeader>
<DialogTitle>Edit Profile</DialogTitle>
</DialogHeader>
<form onSubmit={handleSubmit}>
{/* Form fields */}
<DialogFooter>
<Button type="submit">Save</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>Drawer for Mobile
Mobile-friendly side panel:
import { Drawer, DrawerContent, DrawerHeader } from '@mdxui/primitives'
<Drawer open={isOpen} onOpenChange={setIsOpen}>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Menu</DrawerTitle>
</DrawerHeader>
{/* Navigation items */}
</DrawerContent>
</Drawer>Search & Filter Patterns
Search with Filters
Combine SearchBox with Select filters:
import { SearchBox } from '@mdxui/widgets'
import { Select } from '@mdxui/primitives'
<div className="flex gap-4">
<SearchBox onSearch={handleSearch} className="flex-1" />
<Select value={category} onValueChange={setCategory}>
<SelectTrigger className="w-40">
<SelectValue placeholder="Category" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">All</SelectItem>
<SelectItem value="api">API</SelectItem>
<SelectItem value="sdk">SDK</SelectItem>
</SelectContent>
</Select>
</div>Faceted Search
Multi-facet filtering:
import { Checkbox, Label } from '@mdxui/primitives'
<div className="space-y-4">
<div>
<h3 className="font-medium mb-2">Category</h3>
{categories.map(cat => (
<div key={cat} className="flex items-center gap-2">
<Checkbox id={cat} />
<Label htmlFor={cat}>{cat}</Label>
</div>
))}
</div>
</div>Chat Patterns
AI Chat Interface
Use ChatBox widget for conversational UI:
import { ChatBox } from '@mdxui/widgets'
<ChatBox
messages={messages}
onSend={handleSend}
placeholder="Ask a question..."
streaming={isStreaming}
/>Next Steps
- Component Catalog - Browse all components
- Primitives - Explore primitive components
- Visit Storybook to see patterns in action