Skip to main content

Display Components

Components for presenting information, data, and content.

Card

Container component for grouping related content.

Preview

Live Editor
function CardDemo() {
  return (
    <div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap' }}>
      <div style={{
        width: '300px',
        borderRadius: '12px',
        border: '1px solid #e2e8f0',
        background: 'white',
        overflow: 'hidden',
        boxShadow: '0 2px 8px rgba(0,0,0,0.04)',
      }}>
        <div style={{ padding: '20px 20px 12px' }}>
          <h3 style={{ margin: 0, fontSize: '18px', fontWeight: 600 }}>Project Overview</h3>
          <p style={{ margin: '4px 0 0', color: '#64748b', fontSize: '14px' }}>
            View and manage your active projects
          </p>
        </div>
        <div style={{ padding: '0 20px 20px' }}>
          <p style={{ margin: 0, fontSize: '14px', color: '#374151' }}>
            You have 3 active projects and 2 pending reviews.
          </p>
        </div>
        <div style={{ 
          padding: '16px 20px', 
          borderTop: '1px solid #f1f5f9',
          display: 'flex',
          gap: '8px',
        }}>
          <button style={{
            padding: '8px 16px',
            borderRadius: '6px',
            background: 'linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%)',
            color: 'white',
            border: 'none',
            cursor: 'pointer',
            fontWeight: 600,
            fontSize: '14px',
          }}>
            View Details
          </button>
          <button style={{
            padding: '8px 16px',
            borderRadius: '6px',
            background: 'white',
            border: '1px solid #e2e8f0',
            cursor: 'pointer',
            fontWeight: 500,
            fontSize: '14px',
          }}>
            Cancel
          </button>
        </div>
      </div>
    </div>
  );
}
Result
Loading...

Usage

import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter,
} from "@cpod/react";
import { Button } from "@cpod/react";

<Card>
<CardHeader>
<CardTitle>Project Overview</CardTitle>
<CardDescription>
View and manage your active projects
</CardDescription>
</CardHeader>
<CardContent>
<p>You have 3 active projects and 2 pending reviews.</p>
</CardContent>
<CardFooter>
<Button>View Details</Button>
<Button variant="outline">Cancel</Button>
</CardFooter>
</Card>

// Simple card
<Card className="p-6">
<p>Simple content card</p>
</Card>

// Interactive card
<Card className="hover:shadow-lg transition-shadow cursor-pointer">
<CardContent>
<p>Clickable card</p>
</CardContent>
</Card>

Sub-components

ComponentDescription
CardMain container with border and shadow
CardHeaderHeader section with padding
CardTitleTitle text (h3 by default)
CardDescriptionSubtitle/description text
CardContentMain content area
CardFooterFooter section for actions

Badge

Small labels for status indicators, tags, and counts.

Preview

Live Editor
function BadgeDemo() {
  const badges = [
    { label: 'Default', bg: '#8b5cf6', color: 'white' },
    { label: 'Secondary', bg: '#f1f5f9', color: '#374151' },
    { label: 'Destructive', bg: '#ef4444', color: 'white' },
    { label: 'Outline', bg: 'white', color: '#374151', border: '1px solid #e2e8f0' },
    { label: 'Success', bg: '#dcfce7', color: '#16a34a' },
    { label: 'Warning', bg: '#fef3c7', color: '#ca8a04' },
    { label: 'Info', bg: '#dbeafe', color: '#2563eb' },
  ];
  
  return (
    <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
      {badges.map((badge) => (
        <span
          key={badge.label}
          style={{
            padding: '4px 10px',
            borderRadius: '9999px',
            background: badge.bg,
            color: badge.color,
            fontSize: '12px',
            fontWeight: 500,
            border: badge.border || 'none',
          }}
        >
          {badge.label}
        </span>
      ))}
    </div>
  );
}
Result
Loading...

Usage

import { Badge } from "@cpod/react";

// Basic badge
<Badge>New</Badge>

// Variants
<Badge variant="default">Default</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="destructive">Error</Badge>
<Badge variant="outline">Outline</Badge>
<Badge variant="success">Success</Badge>
<Badge variant="warning">Warning</Badge>
<Badge variant="info">Info</Badge>

// In context
<div className="flex items-center gap-2">
<span>Status:</span>
<Badge variant="success">Active</Badge>
</div>

// With count
<Badge variant="secondary">3 new</Badge>

// In a button
<Button>
Messages <Badge className="ml-2">5</Badge>
</Button>

Props

PropTypeDefaultDescription
variantdefault | secondary | destructive | outline | success | warning | infodefaultBadge color
classNamestring-Additional CSS classes

Alert

Displays important messages and feedback.

Preview

Live Editor
function AlertDemo() {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '12px', maxWidth: '500px' }}>
      <div style={{
        padding: '16px',
        borderRadius: '8px',
        border: '1px solid #e2e8f0',
        background: '#f8fafc',
      }}>
        <div style={{ fontWeight: 600, marginBottom: '4px' }}>Heads up!</div>
        <div style={{ fontSize: '14px', color: '#64748b' }}>
          You can add components to your app using the CLI.
        </div>
      </div>
      
      <div style={{
        padding: '16px',
        borderRadius: '8px',
        border: '1px solid rgba(239, 68, 68, 0.3)',
        background: '#fef2f2',
      }}>
        <div style={{ fontWeight: 600, marginBottom: '4px', color: '#ef4444' }}>Error</div>
        <div style={{ fontSize: '14px', color: '#ef4444' }}>
          Your session has expired. Please log in again.
        </div>
      </div>
    </div>
  );
}
Result
Loading...

Usage

import { Alert, AlertTitle, AlertDescription } from "@cpod/react";

// Default alert
<Alert>
<AlertTitle>Heads up!</AlertTitle>
<AlertDescription>
You can add components to your app using the CLI.
</AlertDescription>
</Alert>

// Destructive alert
<Alert variant="destructive">
<AlertTitle>Error</AlertTitle>
<AlertDescription>
Your session has expired. Please log in again.
</AlertDescription>
</Alert>

Props

PropTypeDefaultDescription
variantdefault | destructivedefaultAlert style

Avatar

Displays user avatars with fallback support.

Preview

Live Editor
function AvatarDemo() {
  return (
    <div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
      <div style={{
        width: '40px',
        height: '40px',
        borderRadius: '50%',
        overflow: 'hidden',
        background: '#8b5cf6',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        color: 'white',
        fontWeight: 600,
      }}>
        JD
      </div>
      <div style={{
        width: '48px',
        height: '48px',
        borderRadius: '50%',
        overflow: 'hidden',
        background: '#06b6d4',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        color: 'white',
        fontWeight: 600,
      }}>
        AB
      </div>
      <div style={{
        width: '56px',
        height: '56px',
        borderRadius: '50%',
        overflow: 'hidden',
        background: '#22c55e',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        color: 'white',
        fontWeight: 600,
        fontSize: '18px',
      }}>
        CP
      </div>
    </div>
  );
}
Result
Loading...

Usage

import { Avatar, AvatarImage, AvatarFallback } from "@cpod/react";

// With image
<Avatar>
<AvatarImage src="/avatar.jpg" alt="@username" />
<AvatarFallback>JD</AvatarFallback>
</Avatar>

// Fallback only
<Avatar>
<AvatarFallback>CP</AvatarFallback>
</Avatar>

// Custom size
<Avatar className="h-16 w-16">
<AvatarImage src="/avatar.jpg" />
<AvatarFallback>JD</AvatarFallback>
</Avatar>

Skeleton

Loading placeholder for content.

Preview

Live Editor
function SkeletonDemo() {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '16px', maxWidth: '350px' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>
        <div style={{
          width: '48px',
          height: '48px',
          borderRadius: '50%',
          background: 'linear-gradient(90deg, #e2e8f0 25%, #f1f5f9 50%, #e2e8f0 75%)',
          backgroundSize: '200% 100%',
          animation: 'shimmer 1.5s ease-in-out infinite',
        }} />
        <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: '8px' }}>
          <div style={{
            height: '16px',
            width: '50%',
            borderRadius: '4px',
            background: 'linear-gradient(90deg, #e2e8f0 25%, #f1f5f9 50%, #e2e8f0 75%)',
            backgroundSize: '200% 100%',
            animation: 'shimmer 1.5s ease-in-out infinite',
          }} />
          <div style={{
            height: '12px',
            width: '80%',
            borderRadius: '4px',
            background: 'linear-gradient(90deg, #e2e8f0 25%, #f1f5f9 50%, #e2e8f0 75%)',
            backgroundSize: '200% 100%',
            animation: 'shimmer 1.5s ease-in-out infinite',
          }} />
        </div>
      </div>
      <style>{`
        @keyframes shimmer {
          0% { background-position: -200% 0; }
          100% { background-position: 200% 0; }
        }
      `}</style>
    </div>
  );
}
Result
Loading...

Usage

import { Skeleton } from "@cpod/react";

// Basic skeleton
<Skeleton className="w-[100px] h-[20px]" />

// Card skeleton
<div className="flex items-center space-x-4">
<Skeleton className="h-12 w-12 rounded-full" />
<div className="space-y-2">
<Skeleton className="h-4 w-[250px]" />
<Skeleton className="h-4 w-[200px]" />
</div>
</div>

// Custom styling
<Skeleton width="100%" height="200px" rounded />

Progress

Progress bar for loading states.

Preview

Live Editor
function ProgressDemo() {
  const [progress, setProgress] = React.useState(45);
  
  React.useEffect(() => {
    const timer = setInterval(() => {
      setProgress((prev) => (prev >= 100 ? 0 : prev + 5));
    }, 500);
    return () => clearInterval(timer);
  }, []);
  
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '16px', maxWidth: '400px' }}>
      <div>
        <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '8px' }}>
          <span style={{ fontSize: '14px', fontWeight: 500 }}>Uploading...</span>
          <span style={{ fontSize: '14px', color: '#64748b' }}>{progress}%</span>
        </div>
        <div style={{
          height: '8px',
          borderRadius: '4px',
          background: '#e2e8f0',
          overflow: 'hidden',
        }}>
          <div style={{
            height: '100%',
            width: `${progress}%`,
            background: 'linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%)',
            borderRadius: '4px',
            transition: 'width 0.3s ease',
          }} />
        </div>
      </div>
    </div>
  );
}
Result
Loading...

Usage

import { Progress } from "@cpod/react";

// Basic progress
<Progress value={33} />

// Custom styling
<Progress value={60} className="h-2" indicatorClassName="bg-green-500" />

// Controlled
const [progress, setProgress] = useState(0);
<Progress value={progress} />

Props

PropTypeDefaultDescription
valuenumber0Progress value (0-100)
indicatorClassNamestring-Custom indicator styles

Table

Data table component.

Preview

Live Editor
function TableDemo() {
  const data = [
    { id: 'INV-001', status: 'Paid', method: 'Credit Card', amount: '$250.00' },
    { id: 'INV-002', status: 'Pending', method: 'PayPal', amount: '$150.00' },
    { id: 'INV-003', status: 'Unpaid', method: 'Bank Transfer', amount: '$350.00' },
  ];
  
  return (
    <div style={{ 
      border: '1px solid #e2e8f0', 
      borderRadius: '8px', 
      overflow: 'hidden',
      fontSize: '14px',
    }}>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead style={{ background: '#f8fafc' }}>
          <tr>
            <th style={{ padding: '12px 16px', textAlign: 'left', fontWeight: 600, fontSize: '12px', textTransform: 'uppercase', color: '#64748b' }}>Invoice</th>
            <th style={{ padding: '12px 16px', textAlign: 'left', fontWeight: 600, fontSize: '12px', textTransform: 'uppercase', color: '#64748b' }}>Status</th>
            <th style={{ padding: '12px 16px', textAlign: 'left', fontWeight: 600, fontSize: '12px', textTransform: 'uppercase', color: '#64748b' }}>Method</th>
            <th style={{ padding: '12px 16px', textAlign: 'right', fontWeight: 600, fontSize: '12px', textTransform: 'uppercase', color: '#64748b' }}>Amount</th>
          </tr>
        </thead>
        <tbody>
          {data.map((row, i) => (
            <tr key={row.id} style={{ borderTop: '1px solid #e2e8f0' }}>
              <td style={{ padding: '12px 16px', fontWeight: 500 }}>{row.id}</td>
              <td style={{ padding: '12px 16px' }}>
                <span style={{
                  padding: '2px 8px',
                  borderRadius: '9999px',
                  fontSize: '12px',
                  fontWeight: 500,
                  background: row.status === 'Paid' ? '#dcfce7' : row.status === 'Pending' ? '#fef3c7' : '#fee2e2',
                  color: row.status === 'Paid' ? '#16a34a' : row.status === 'Pending' ? '#ca8a04' : '#dc2626',
                }}>
                  {row.status}
                </span>
              </td>
              <td style={{ padding: '12px 16px', color: '#64748b' }}>{row.method}</td>
              <td style={{ padding: '12px 16px', textAlign: 'right', fontWeight: 500 }}>{row.amount}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}
Result
Loading...

Usage

import {
Table,
TableHeader,
TableBody,
TableFooter,
TableHead,
TableRow,
TableCell,
TableCaption,
} from "@cpod/react";

<Table>
<TableCaption>A list of recent invoices.</TableCaption>
<TableHeader>
<TableRow>
<TableHead>Invoice</TableHead>
<TableHead>Status</TableHead>
<TableHead>Method</TableHead>
<TableHead className="text-right">Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{invoices.map((invoice) => (
<TableRow key={invoice.id}>
<TableCell className="font-medium">{invoice.id}</TableCell>
<TableCell>{invoice.status}</TableCell>
<TableCell>{invoice.method}</TableCell>
<TableCell className="text-right">{invoice.amount}</TableCell>
</TableRow>
))}
</TableBody>
</Table>

Tabs

Tab navigation component.

Preview

Live Editor
function TabsDemo() {
  const [activeTab, setActiveTab] = React.useState('account');
  
  return (
    <div style={{ maxWidth: '400px' }}>
      <div style={{
        display: 'inline-flex',
        padding: '4px',
        background: '#f1f5f9',
        borderRadius: '8px',
        marginBottom: '16px',
      }}>
        {['account', 'password'].map((tab) => (
          <button
            key={tab}
            onClick={() => setActiveTab(tab)}
            style={{
              padding: '8px 16px',
              borderRadius: '6px',
              border: 'none',
              background: activeTab === tab ? 'white' : 'transparent',
              boxShadow: activeTab === tab ? '0 1px 3px rgba(0,0,0,0.1)' : 'none',
              cursor: 'pointer',
              fontWeight: 500,
              fontSize: '14px',
              textTransform: 'capitalize',
            }}
          >
            {tab}
          </button>
        ))}
      </div>
      
      <div style={{ padding: '16px', border: '1px solid #e2e8f0', borderRadius: '8px' }}>
        {activeTab === 'account' && (
          <div>
            <h4 style={{ margin: 0, marginBottom: '8px' }}>Account</h4>
            <p style={{ margin: 0, color: '#64748b', fontSize: '14px' }}>
              Make changes to your account here.
            </p>
          </div>
        )}
        {activeTab === 'password' && (
          <div>
            <h4 style={{ margin: 0, marginBottom: '8px' }}>Password</h4>
            <p style={{ margin: 0, color: '#64748b', fontSize: '14px' }}>
              Change your password here.
            </p>
          </div>
        )}
      </div>
    </div>
  );
}
Result
Loading...

Usage

import { Tabs, TabsList, TabsTrigger, TabsContent } from "@cpod/react";

<Tabs defaultValue="account" className="w-[400px]">
<TabsList>
<TabsTrigger value="account">Account</TabsTrigger>
<TabsTrigger value="password">Password</TabsTrigger>
</TabsList>
<TabsContent value="account">
<p>Make changes to your account here.</p>
</TabsContent>
<TabsContent value="password">
<p>Change your password here.</p>
</TabsContent>
</Tabs>

Navigation breadcrumb trail.

Preview

Live Editor
function BreadcrumbDemo() {
  const items = ['Home', 'Components', 'Breadcrumb'];
  
  return (
    <nav>
      <ol style={{
        display: 'flex',
        alignItems: 'center',
        gap: '8px',
        listStyle: 'none',
        margin: 0,
        padding: 0,
        fontSize: '14px',
      }}>
        {items.map((item, i) => (
          <React.Fragment key={item}>
            <li>
              <a 
                href="#" 
                style={{ 
                  color: i === items.length - 1 ? '#1e293b' : '#64748b',
                  textDecoration: 'none',
                  fontWeight: i === items.length - 1 ? 500 : 400,
                }}
              >
                {item}
              </a>
            </li>
            {i < items.length - 1 && (
              <li style={{ color: '#94a3b8' }}>/</li>
            )}
          </React.Fragment>
        ))}
      </ol>
    </nav>
  );
}
Result
Loading...

Usage

import {
Breadcrumb,
BreadcrumbList,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbPage,
BreadcrumbSeparator,
BreadcrumbEllipsis,
} from "@cpod/react";

<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="/components">Components</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>

ScrollArea

Custom scrollbar container.

Preview

Live Editor
function ScrollAreaDemo() {
  const items = Array.from({ length: 15 }, (_, i) => `Item ${i + 1}`);
  
  return (
    <div style={{
      height: '200px',
      width: '200px',
      border: '1px solid #e2e8f0',
      borderRadius: '8px',
      overflow: 'auto',
    }}>
      <div style={{ padding: '16px' }}>
        <h4 style={{ margin: 0, marginBottom: '16px', fontSize: '14px', fontWeight: 600 }}>Tags</h4>
        {items.map((item) => (
          <div
            key={item}
            style={{
              padding: '8px 0',
              borderBottom: '1px solid #f1f5f9',
              fontSize: '14px',
            }}
          >
            {item}
          </div>
        ))}
      </div>
    </div>
  );
}
Result
Loading...

Usage

import { ScrollArea, ScrollBar } from "@cpod/react";

<ScrollArea className="h-72 w-48 rounded-md border">
<div className="p-4">
<h4 className="mb-4 text-sm font-medium">Tags</h4>
{tags.map((tag) => (
<div key={tag} className="text-sm py-2">
{tag}
</div>
))}
</div>
</ScrollArea>

// Horizontal scroll
<ScrollArea className="w-96 whitespace-nowrap rounded-md border">
<div className="flex w-max space-x-4 p-4">
{items.map((item) => (
<div key={item} className="shrink-0">
{item}
</div>
))}
</div>
<ScrollBar orientation="horizontal" />
</ScrollArea>