Advanced Components
Complex UI components for building sophisticated interfaces.
Command
Command palette / search interface with keyboard navigation.
Preview
Live Editor
function CommandDemo() { const [search, setSearch] = React.useState(''); const [open, setOpen] = React.useState(false); const items = [ { group: 'Suggestions', items: ['Calendar', 'Search Emoji', 'Calculator'] }, { group: 'Settings', items: ['Profile', 'Billing', 'Settings'] }, ]; const filteredItems = items.map(group => ({ ...group, items: group.items.filter(item => item.toLowerCase().includes(search.toLowerCase()) ), })).filter(group => group.items.length > 0); return ( <div> <button onClick={() => setOpen(true)} style={{ padding: '10px 20px', borderRadius: '8px', background: 'linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%)', color: 'white', border: 'none', cursor: 'pointer', fontWeight: 600, display: 'flex', alignItems: 'center', gap: '8px', }} > <span>Open Command</span> <span style={{ padding: '2px 6px', background: 'rgba(255,255,255,0.2)', borderRadius: '4px', fontSize: '12px', }}>⌘K</span> </button> {open && ( <div style={{ position: 'fixed', inset: 0, display: 'flex', alignItems: 'flex-start', justifyContent: 'center', paddingTop: '15vh', backgroundColor: 'rgba(0,0,0,0.4)', zIndex: 50, }}> <div onClick={() => setOpen(false)} style={{ position: 'absolute', inset: 0 }} /> <div style={{ position: 'relative', background: 'white', borderRadius: '12px', boxShadow: '0 20px 50px -12px rgba(0,0,0,0.25)', width: '450px', overflow: 'hidden', }}> <div style={{ display: 'flex', alignItems: 'center', padding: '12px 16px', borderBottom: '1px solid #e2e8f0', }}> <span style={{ marginRight: '8px', color: '#64748b' }}>🔍</span> <input autoFocus placeholder="Type a command or search..." value={search} onChange={(e) => setSearch(e.target.value)} style={{ flex: 1, border: 'none', outline: 'none', fontSize: '14px', }} /> </div> <div style={{ maxHeight: '300px', overflow: 'auto', padding: '8px' }}> {filteredItems.length === 0 ? ( <div style={{ padding: '40px', textAlign: 'center', color: '#64748b' }}> No results found. </div> ) : ( filteredItems.map((group) => ( <div key={group.group}> <div style={{ padding: '8px 8px', fontSize: '12px', fontWeight: 600, color: '#64748b', }}> {group.group} </div> {group.items.map((item) => ( <div key={item} onClick={() => { setOpen(false); setSearch(''); }} style={{ padding: '10px 12px', borderRadius: '6px', cursor: 'pointer', fontSize: '14px', display: 'flex', alignItems: 'center', gap: '8px', }} onMouseEnter={(e) => e.currentTarget.style.background = '#f8fafc'} onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'} > <span>📄</span> {item} </div> ))} </div> )) )} </div> </div> </div> )} </div> ); }
Result
Loading...
Usage
import {
Command,
CommandDialog,
CommandInput,
CommandList,
CommandEmpty,
CommandGroup,
CommandItem,
CommandSeparator,
CommandShortcut,
} from "@cpod/react";
// Inline command menu
<Command className="rounded-lg border shadow-md">
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem>Calendar</CommandItem>
<CommandItem>Search Emoji</CommandItem>
<CommandItem>Calculator</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Settings">
<CommandItem>Profile</CommandItem>
<CommandItem>Billing</CommandItem>
<CommandItem>Settings</CommandItem>
</CommandGroup>
</CommandList>
</Command>
// Dialog version (⌘K)
function CommandMenu() {
const [open, setOpen] = useState(false);
useEffect(() => {
const down = (e) => {
if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
e.preventDefault();
setOpen((open) => !open);
}
};
document.addEventListener("keydown", down);
return () => document.removeEventListener("keydown", down);
}, []);
return (
<CommandDialog open={open} onOpenChange={setOpen}>
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem>
<CalendarIcon className="mr-2 h-4 w-4" />
<span>Calendar</span>
<CommandShortcut>⌘C</CommandShortcut>
</CommandItem>
</CommandGroup>
</CommandList>
</CommandDialog>
);
}
Carousel
Image and content carousel with touch support.
Preview
Live Editor
function CarouselDemo() { const [currentIndex, setCurrentIndex] = React.useState(0); const items = [ { bg: '#8b5cf6', text: 'Slide 1' }, { bg: '#06b6d4', text: 'Slide 2' }, { bg: '#22c55e', text: 'Slide 3' }, { bg: '#f59e0b', text: 'Slide 4' }, ]; const prev = () => setCurrentIndex(i => i === 0 ? items.length - 1 : i - 1); const next = () => setCurrentIndex(i => i === items.length - 1 ? 0 : i + 1); return ( <div style={{ position: 'relative', maxWidth: '400px' }}> <div style={{ overflow: 'hidden', borderRadius: '12px', }}> <div style={{ display: 'flex', transition: 'transform 0.3s ease', transform: `translateX(-${currentIndex * 100}%)`, }}> {items.map((item, i) => ( <div key={i} style={{ flexShrink: 0, width: '100%', height: '200px', background: item.bg, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white', fontSize: '24px', fontWeight: 600, }} > {item.text} </div> ))} </div> </div> <button onClick={prev} style={{ position: 'absolute', left: '-20px', top: '50%', transform: 'translateY(-50%)', width: '40px', height: '40px', borderRadius: '50%', border: '1px solid #e2e8f0', background: 'white', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', boxShadow: '0 2px 8px rgba(0,0,0,0.1)', }} > ← </button> <button onClick={next} style={{ position: 'absolute', right: '-20px', top: '50%', transform: 'translateY(-50%)', width: '40px', height: '40px', borderRadius: '50%', border: '1px solid #e2e8f0', background: 'white', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', boxShadow: '0 2px 8px rgba(0,0,0,0.1)', }} > → </button> <div style={{ display: 'flex', justifyContent: 'center', gap: '8px', marginTop: '16px', }}> {items.map((_, i) => ( <button key={i} onClick={() => setCurrentIndex(i)} style={{ width: '8px', height: '8px', borderRadius: '50%', border: 'none', background: i === currentIndex ? '#8b5cf6' : '#e2e8f0', cursor: 'pointer', }} /> ))} </div> </div> ); }
Result
Loading...
Usage
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@cpod/react";
<Carousel className="w-full max-w-xs">
<CarouselContent>
{Array.from({ length: 5 }).map((_, index) => (
<CarouselItem key={index}>
<div className="p-1">
<Card>
<CardContent className="flex aspect-square items-center justify-center p-6">
<span className="text-4xl font-semibold">{index + 1}</span>
</CardContent>
</Card>
</div>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
// Multiple items per view
<Carousel
opts={{
align: "start",
}}
className="w-full"
>
<CarouselContent className="-ml-4">
{items.map((item, index) => (
<CarouselItem key={index} className="pl-4 md:basis-1/2 lg:basis-1/3">
<Card>{item}</Card>
</CarouselItem>
))}
</CarouselContent>
</Carousel>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | horizontal | vertical | horizontal | Carousel direction |
opts | CarouselOptions | - | Embla carousel options |
plugins | CarouselPlugin[] | - | Embla plugins (autoplay, etc) |
setApi | (api) => void | - | Access carousel API |
Collapsible
Expandable/collapsible content sections.
Preview
Live Editor
function CollapsibleDemo() { const [open, setOpen] = React.useState(false); return ( <div style={{ maxWidth: '400px' }}> <div style={{ border: '1px solid #e2e8f0', borderRadius: '8px', overflow: 'hidden', }}> <button onClick={() => setOpen(!open)} style={{ width: '100%', padding: '16px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', background: 'white', border: 'none', cursor: 'pointer', fontWeight: 600, fontSize: '14px', }} > <span>@peduarte starred 3 repositories</span> <span style={{ transform: open ? 'rotate(180deg)' : 'rotate(0deg)', transition: 'transform 0.2s', }}>▼</span> </button> {open && ( <div style={{ borderTop: '1px solid #e2e8f0', padding: '16px', background: '#f8fafc', }}> <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}> {['@radix-ui/primitives', '@radix-ui/colors', '@stitches/react'].map((repo) => ( <div key={repo} style={{ padding: '8px 12px', background: 'white', borderRadius: '6px', fontSize: '14px', fontFamily: 'monospace', }} > {repo} </div> ))} </div> </div> )} </div> </div> ); }
Result
Loading...
Usage
import {
Collapsible,
CollapsibleTrigger,
CollapsibleContent,
} from "@cpod/react";
import { Button } from "@cpod/react";
function CollapsibleDemo() {
const [isOpen, setIsOpen] = useState(false);
return (
<Collapsible open={isOpen} onOpenChange={setIsOpen}>
<div className="flex items-center justify-between space-x-4">
<h4 className="text-sm font-semibold">
@peduarte starred 3 repositories
</h4>
<CollapsibleTrigger asChild>
<Button variant="ghost" size="sm">
{isOpen ? "Hide" : "Show"}
</Button>
</CollapsibleTrigger>
</div>
<CollapsibleContent className="space-y-2">
<div className="rounded-md border px-4 py-3 font-mono text-sm">
@radix-ui/primitives
</div>
<div className="rounded-md border px-4 py-3 font-mono text-sm">
@radix-ui/colors
</div>
<div className="rounded-md border px-4 py-3 font-mono text-sm">
@stitches/react
</div>
</CollapsibleContent>
</Collapsible>
);
}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | - | Controlled open state |
defaultOpen | boolean | false | Default open state |
onOpenChange | (open: boolean) => void | - | Open state change handler |
disabled | boolean | false | Disable collapsible |
Resizable
Resizable panel layouts.
Preview
Live Editor
function ResizableDemo() { const [leftWidth, setLeftWidth] = React.useState(200); const [isDragging, setIsDragging] = React.useState(false); const handleMouseDown = (e) => { setIsDragging(true); const startX = e.clientX; const startWidth = leftWidth; const handleMouseMove = (e) => { const delta = e.clientX - startX; setLeftWidth(Math.max(100, Math.min(400, startWidth + delta))); }; const handleMouseUp = () => { setIsDragging(false); document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseup', handleMouseUp); }; document.addEventListener('mousemove', handleMouseMove); document.addEventListener('mouseup', handleMouseUp); }; return ( <div style={{ display: 'flex', height: '250px', border: '1px solid #e2e8f0', borderRadius: '8px', overflow: 'hidden', }}> <div style={{ width: leftWidth, background: 'linear-gradient(135deg, rgba(139, 92, 246, 0.1) 0%, rgba(34, 211, 238, 0.1) 100%)', padding: '16px', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '14px', color: '#64748b', }}> Sidebar ({leftWidth}px) </div> <div onMouseDown={handleMouseDown} style={{ width: '4px', background: isDragging ? '#8b5cf6' : '#e2e8f0', cursor: 'col-resize', display: 'flex', alignItems: 'center', justifyContent: 'center', transition: 'background 0.2s', }} onMouseEnter={(e) => e.currentTarget.style.background = '#8b5cf6'} onMouseLeave={(e) => !isDragging && (e.currentTarget.style.background = '#e2e8f0')} > <div style={{ width: '2px', height: '30px', background: 'currentColor', borderRadius: '1px', }} /> </div> <div style={{ flex: 1, background: '#f8fafc', padding: '16px', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '14px', color: '#64748b', }}> Content Area </div> </div> ); }
Result
Loading...
Usage
import {
ResizablePanelGroup,
ResizablePanel,
ResizableHandle,
} from "@cpod/react";
// Horizontal layout
<ResizablePanelGroup direction="horizontal" className="min-h-[200px]">
<ResizablePanel defaultSize={25}>
<div className="p-4">Sidebar</div>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel defaultSize={75}>
<div className="p-4">Content</div>
</ResizablePanel>
</ResizablePanelGroup>
// Vertical layout
<ResizablePanelGroup direction="vertical" className="min-h-[400px]">
<ResizablePanel defaultSize={25}>
<div className="p-4">Header</div>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel defaultSize={75}>
<div className="p-4">Main Content</div>
</ResizablePanel>
</ResizablePanelGroup>
// With handle grip
<ResizableHandle withHandle />
// Three panel layout
<ResizablePanelGroup direction="horizontal">
<ResizablePanel defaultSize={20} minSize={15}>
Sidebar
</ResizablePanel>
<ResizableHandle />
<ResizablePanel defaultSize={60}>
Main
</ResizablePanel>
<ResizableHandle />
<ResizablePanel defaultSize={20} minSize={15}>
Right Panel
</ResizablePanel>
</ResizablePanelGroup>
Props
ResizablePanelGroup:
| Prop | Type | Default | Description |
|---|---|---|---|
direction | horizontal | vertical | - | Panel direction |
autoSaveId | string | - | Persist sizes to localStorage |
ResizablePanel:
| Prop | Type | Default | Description |
|---|---|---|---|
defaultSize | number | - | Default size (percentage) |
minSize | number | - | Minimum size |
maxSize | number | - | Maximum size |
collapsible | boolean | false | Allow collapsing |
ResizableHandle:
| Prop | Type | Default | Description |
|---|---|---|---|
withHandle | boolean | false | Show grip handle |
Complete Example: IDE Layout
function IDELayout() {
return (
<ResizablePanelGroup direction="horizontal" className="h-screen">
{/* File Explorer */}
<ResizablePanel defaultSize={20} minSize={15} maxSize={30}>
<div className="h-full bg-slate-900 text-white p-4">
<h3 className="font-semibold mb-4">Explorer</h3>
<Collapsible defaultOpen>
<CollapsibleTrigger className="w-full text-left">
📁 src
</CollapsibleTrigger>
<CollapsibleContent className="pl-4 mt-2 space-y-1">
<div>📄 index.ts</div>
<div>📄 app.tsx</div>
</CollapsibleContent>
</Collapsible>
</div>
</ResizablePanel>
<ResizableHandle withHandle />
{/* Editor */}
<ResizablePanel defaultSize={60}>
<ResizablePanelGroup direction="vertical">
<ResizablePanel defaultSize={70}>
<div className="h-full bg-slate-800 text-white p-4">
Editor
</div>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel defaultSize={30}>
<Tabs defaultValue="terminal" className="h-full">
<TabsList>
<TabsTrigger value="terminal">Terminal</TabsTrigger>
<TabsTrigger value="output">Output</TabsTrigger>
</TabsList>
<TabsContent value="terminal" className="bg-black text-green-400 p-4 font-mono">
$ npm run dev
</TabsContent>
</Tabs>
</ResizablePanel>
</ResizablePanelGroup>
</ResizablePanel>
<ResizableHandle withHandle />
{/* AI Assistant */}
<ResizablePanel defaultSize={20} minSize={15} collapsible>
<div className="h-full bg-slate-50 p-4">
<h3 className="font-semibold mb-4">AI Assistant</h3>
<Command className="rounded-lg border shadow-sm">
<CommandInput placeholder="Ask anything..." />
</Command>
</div>
</ResizablePanel>
</ResizablePanelGroup>
);
}