Skip to main content

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>
);
}

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

PropTypeDefaultDescription
orientationhorizontal | verticalhorizontalCarousel direction
optsCarouselOptions-Embla carousel options
pluginsCarouselPlugin[]-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

PropTypeDefaultDescription
openboolean-Controlled open state
defaultOpenbooleanfalseDefault open state
onOpenChange(open: boolean) => void-Open state change handler
disabledbooleanfalseDisable 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:

PropTypeDefaultDescription
directionhorizontal | vertical-Panel direction
autoSaveIdstring-Persist sizes to localStorage

ResizablePanel:

PropTypeDefaultDescription
defaultSizenumber-Default size (percentage)
minSizenumber-Minimum size
maxSizenumber-Maximum size
collapsiblebooleanfalseAllow collapsing

ResizableHandle:

PropTypeDefaultDescription
withHandlebooleanfalseShow 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>
);
}