Form Components
Form input components for building interactive forms with CyberPod styling.
Button
Versatile button component with multiple variants and sizes.
Preview
Live Editor
function ButtonDemo() { const [loading, setLoading] = React.useState(false); const handleClick = () => { setLoading(true); setTimeout(() => setLoading(false), 1500); }; return ( <div style={{ display: 'flex', flexWrap: 'wrap', gap: '12px', alignItems: 'center' }}> <button style={{ padding: '10px 20px', borderRadius: '8px', background: 'linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%)', color: 'white', border: 'none', cursor: 'pointer', fontWeight: 600, }}> Primary </button> <button style={{ padding: '10px 20px', borderRadius: '8px', background: '#ef4444', color: 'white', border: 'none', cursor: 'pointer', fontWeight: 600, }}> Destructive </button> <button style={{ padding: '10px 20px', borderRadius: '8px', background: 'white', border: '1px solid #e2e8f0', cursor: 'pointer', fontWeight: 600, }}> Outline </button> <button style={{ padding: '10px 20px', borderRadius: '8px', background: '#f1f5f9', border: 'none', cursor: 'pointer', fontWeight: 600, }}> Secondary </button> <button style={{ padding: '10px 20px', borderRadius: '8px', background: 'transparent', border: 'none', cursor: 'pointer', fontWeight: 600, }}> Ghost </button> <button onClick={handleClick} disabled={loading} style={{ padding: '10px 20px', borderRadius: '8px', background: loading ? '#a78bfa' : 'linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%)', color: 'white', border: 'none', cursor: loading ? 'not-allowed' : 'pointer', fontWeight: 600, opacity: loading ? 0.7 : 1, }} > {loading ? '⏳ Loading...' : 'Click to Load'} </button> </div> ); }
Result
Loading...
Usage
import { Button } from "@cpod/react";
// Basic button
<Button>Click me</Button>
// Variants
<Button variant="default">Primary</Button>
<Button variant="destructive">Delete</Button>
<Button variant="outline">Cancel</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
// Sizes
<Button size="sm">Small</Button>
<Button size="default">Default</Button>
<Button size="lg">Large</Button>
<Button size="icon"><SearchIcon /></Button>
// Loading state
<Button loading disabled>Processing...</Button>
// As a link (using asChild)
<Button asChild>
<a href="/docs">View Docs</a>
</Button>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | default | destructive | outline | secondary | ghost | link | default | Visual style |
size | sm | default | lg | icon | default | Button size |
loading | boolean | false | Show loading spinner |
asChild | boolean | false | Render as child element |
disabled | boolean | false | Disable button |
Input
Form input component with error states and variants.
Preview
Live Editor
function InputDemo() { const [value, setValue] = React.useState(''); return ( <div style={{ display: 'flex', flexDirection: 'column', gap: '12px', maxWidth: '300px' }}> <input type="text" placeholder="Default input" value={value} onChange={(e) => setValue(e.target.value)} style={{ padding: '10px 12px', borderRadius: '8px', border: '1px solid #e2e8f0', fontSize: '14px', outline: 'none', }} /> <input type="email" placeholder="Email input" style={{ padding: '10px 12px', borderRadius: '8px', border: '1px solid #e2e8f0', fontSize: '14px', outline: 'none', }} /> <input type="text" placeholder="Error state" style={{ padding: '10px 12px', borderRadius: '8px', border: '1px solid #ef4444', fontSize: '14px', outline: 'none', background: '#fef2f2', }} /> <input type="text" placeholder="Disabled input" disabled style={{ padding: '10px 12px', borderRadius: '8px', border: '1px solid #e2e8f0', fontSize: '14px', outline: 'none', background: '#f8fafc', cursor: 'not-allowed', opacity: 0.6, }} /> </div> ); }
Result
Loading...
Usage
import { Input } from "@cpod/react";
// Basic input
<Input placeholder="Enter your email" />
// With type
<Input type="email" placeholder="user@example.com" />
<Input type="password" placeholder="••••••••" />
<Input type="number" placeholder="Enter amount" />
// Error state
<Input error placeholder="This field has an error" />
// Different sizes
<Input size="sm" placeholder="Small input" />
<Input size="md" placeholder="Medium input" />
<Input size="lg" placeholder="Large input" />
// Variants
<Input variant="default" placeholder="Default" />
<Input variant="outline" placeholder="Outline" />
<Input variant="ghost" placeholder="Ghost" />
// Disabled
<Input disabled placeholder="Disabled input" />
Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | default | outline | ghost | default | Visual style |
size | sm | md | lg | md | Input size |
error | boolean | false | Show error state |
type | string | text | HTML input type |
disabled | boolean | false | Disable input |
placeholder | string | - | Placeholder text |
Textarea
Multi-line text input component.
Preview
Live Editor
function TextareaDemo() { return ( <div style={{ display: 'flex', flexDirection: 'column', gap: '12px', maxWidth: '400px' }}> <textarea placeholder="Write your message here..." rows={4} style={{ width: '100%', padding: '12px', borderRadius: '16px', border: '1px solid #e2e8f0', fontSize: '14px', fontFamily: 'inherit', resize: 'vertical', }} /> </div> ); }
Result
Loading...
Usage
import { Textarea } from "@cpod/react";
// Basic textarea
<Textarea placeholder="Enter your message..." />
// With custom rows
<Textarea rows={5} placeholder="Longer text area" />
// Disabled state
<Textarea disabled placeholder="Read-only content" />
Props
| Prop | Type | Default | Description |
|---|---|---|---|
placeholder | string | - | Placeholder text |
rows | number | - | Number of visible rows |
disabled | boolean | false | Disable input |
className | string | - | Additional CSS classes |
Select
Dropdown select component with full keyboard navigation.
Preview
Live Editor
function SelectDemo() { return ( <div style={{ display: 'flex', flexDirection: 'column', gap: '12px', maxWidth: '300px' }}> <select style={{ width: '100%', padding: '10px 16px', borderRadius: '16px', border: '1px solid #e2e8f0', fontSize: '14px', fontFamily: 'inherit', backgroundColor: 'white', cursor: 'pointer', }}> <option value="">Select a fruit...</option> <option value="apple">Apple</option> <option value="banana">Banana</option> <option value="orange">Orange</option> <option value="grape">Grape</option> </select> </div> ); }
Result
Loading...
Usage
import {
Select,
SelectTrigger,
SelectValue,
SelectContent,
SelectItem,
SelectGroup,
SelectLabel,
SelectSeparator,
} from "@cpod/react";
// Basic select
<Select>
<SelectTrigger>
<SelectValue placeholder="Select a fruit..." />
</SelectTrigger>
<SelectContent>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
<SelectItem value="orange">Orange</SelectItem>
</SelectContent>
</Select>
// With groups
<Select>
<SelectTrigger className="w-[200px]">
<SelectValue placeholder="Select a category..." />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Fruits</SelectLabel>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
</SelectGroup>
<SelectSeparator />
<SelectGroup>
<SelectLabel>Vegetables</SelectLabel>
<SelectItem value="carrot">Carrot</SelectItem>
<SelectItem value="potato">Potato</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
Sub-components
| Component | Description |
|---|---|
Select | Root component |
SelectTrigger | Button that opens the select |
SelectValue | Displays selected value |
SelectContent | Dropdown content container |
SelectItem | Individual option |
SelectGroup | Group of options |
SelectLabel | Label for a group |
SelectSeparator | Visual separator |
Checkbox
Checkbox input for boolean values.
Preview
Live Editor
function CheckboxDemo() { const [checked, setChecked] = React.useState(false); return ( <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}> <label style={{ display: 'flex', alignItems: 'center', gap: '8px', cursor: 'pointer' }}> <input type="checkbox" checked={checked} onChange={(e) => setChecked(e.target.checked)} style={{ width: '16px', height: '16px', accentColor: '#8b5cf6' }} /> <span>Accept terms and conditions</span> </label> <label style={{ display: 'flex', alignItems: 'center', gap: '8px', cursor: 'pointer' }}> <input type="checkbox" defaultChecked style={{ width: '16px', height: '16px', accentColor: '#8b5cf6' }} /> <span>Subscribe to newsletter</span> </label> </div> ); }
Result
Loading...
Usage
import { Checkbox } from "@cpod/react";
// Basic checkbox
<Checkbox id="terms" />
// With label
<div className="flex items-center space-x-2">
<Checkbox id="terms" />
<label htmlFor="terms">Accept terms and conditions</label>
</div>
// Controlled
const [checked, setChecked] = useState(false);
<Checkbox
checked={checked}
onCheckedChange={setChecked}
/>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
checked | boolean | - | Controlled checked state |
defaultChecked | boolean | false | Default checked state |
onCheckedChange | (checked: boolean) => void | - | Change handler |
disabled | boolean | false | Disable checkbox |
RadioGroup
Radio button group for single selection.
Preview
Live Editor
function RadioGroupDemo() { const [value, setValue] = React.useState('option1'); return ( <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}> {['option1', 'option2', 'option3'].map((option) => ( <label key={option} style={{ display: 'flex', alignItems: 'center', gap: '8px', cursor: 'pointer' }}> <input type="radio" name="options" value={option} checked={value === option} onChange={(e) => setValue(e.target.value)} style={{ width: '16px', height: '16px', accentColor: '#8b5cf6' }} /> <span>Option {option.slice(-1)}</span> </label> ))} </div> ); }
Result
Loading...
Usage
import { RadioGroup, RadioGroupItem } from "@cpod/react";
import { Label } from "@cpod/react";
<RadioGroup defaultValue="option1">
<div className="flex items-center space-x-2">
<RadioGroupItem value="option1" id="r1" />
<Label htmlFor="r1">Option 1</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="option2" id="r2" />
<Label htmlFor="r2">Option 2</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="option3" id="r3" />
<Label htmlFor="r3">Option 3</Label>
</div>
</RadioGroup>
Props
RadioGroup:
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | - | Controlled value |
defaultValue | string | - | Default value |
onValueChange | (value: string) => void | - | Change handler |
disabled | boolean | false | Disable all items |
Switch
Toggle switch for on/off states.
Preview
Live Editor
function SwitchDemo() { const [enabled, setEnabled] = React.useState(false); return ( <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}> <label style={{ display: 'flex', alignItems: 'center', gap: '12px', cursor: 'pointer' }}> <button onClick={() => setEnabled(!enabled)} style={{ width: '42px', height: '22px', borderRadius: '11px', border: 'none', backgroundColor: enabled ? '#8b5cf6' : '#94a3b8', position: 'relative', cursor: 'pointer', transition: 'background-color 0.2s', }} > <span style={{ position: 'absolute', top: '3px', left: enabled ? '23px' : '3px', width: '16px', height: '16px', borderRadius: '50%', backgroundColor: 'white', transition: 'left 0.2s', boxShadow: '0 1px 2px rgba(0,0,0,0.25)', }} /> </button> <span>Enable notifications</span> </label> </div> ); }
Result
Loading...
Usage
import { Switch } from "@cpod/react";
import { Label } from "@cpod/react";
// Basic switch
<Switch />
// With label
<div className="flex items-center space-x-2">
<Switch id="airplane-mode" />
<Label htmlFor="airplane-mode">Airplane Mode</Label>
</div>
// Controlled
const [enabled, setEnabled] = useState(false);
<Switch
checked={enabled}
onCheckedChange={setEnabled}
/>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
checked | boolean | - | Controlled state |
defaultChecked | boolean | false | Default state |
onCheckedChange | (checked: boolean) => void | - | Change handler |
disabled | boolean | false | Disable switch |
Slider
Range slider for numeric values.
Preview
Live Editor
function SliderDemo() { const [value, setValue] = React.useState(50); return ( <div style={{ display: 'flex', flexDirection: 'column', gap: '16px', maxWidth: '300px' }}> <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: '14px' }}> <span>Volume</span> <span>{value}%</span> </div> <input type="range" min="0" max="100" value={value} onChange={(e) => setValue(parseInt(e.target.value))} style={{ width: '100%', height: '8px', borderRadius: '4px', accentColor: '#8b5cf6', }} /> </div> ); }
Result
Loading...
Usage
import { Slider } from "@cpod/react";
// Basic slider
<Slider defaultValue={[50]} max={100} step={1} />
// With range
<Slider defaultValue={[25, 75]} max={100} step={1} />
// Controlled
const [value, setValue] = useState([50]);
<Slider value={value} onValueChange={setValue} />
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | number[] | - | Controlled value |
defaultValue | number[] | - | Default value |
onValueChange | (value: number[]) => void | - | Change handler |
min | number | 0 | Minimum value |
max | number | 100 | Maximum value |
step | number | 1 | Step increment |
disabled | boolean | false | Disable slider |
Label
Form label component for accessibility.
Preview
Live Editor
function LabelDemo() { return ( <div style={{ display: 'flex', flexDirection: 'column', gap: '16px', maxWidth: '300px' }}> <div style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}> <label style={{ fontSize: '14px', fontWeight: 500 }}>Email</label> <input type="email" placeholder="you@example.com" style={{ padding: '10px 12px', borderRadius: '8px', border: '1px solid #e2e8f0', fontSize: '14px', }} /> </div> <div style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}> <label style={{ fontSize: '14px', fontWeight: 500 }}>Password</label> <input type="password" placeholder="••••••••" style={{ padding: '10px 12px', borderRadius: '8px', border: '1px solid #e2e8f0', fontSize: '14px', }} /> </div> </div> ); }
Result
Loading...
Usage
import { Label } from "@cpod/react";
import { Input, Checkbox } from "@cpod/react";
// With input
<div className="grid gap-2">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="Enter your email" />
</div>
// With checkbox
<div className="flex items-center space-x-2">
<Checkbox id="terms" />
<Label htmlFor="terms">Accept terms and conditions</Label>
</div>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
htmlFor | string | - | Associated input ID |
className | string | - | Additional CSS classes |
Complete Form Example
Here's a comprehensive example showing how all form components work together:
import {
Button,
Input,
Textarea,
Select,
SelectTrigger,
SelectValue,
SelectContent,
SelectItem,
Checkbox,
RadioGroup,
RadioGroupItem,
Switch,
Slider,
Label,
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter,
} from "@cpod/react";
function SettingsForm() {
const [notifications, setNotifications] = useState(true);
const [volume, setVolume] = useState([50]);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// Handle form submission
};
return (
<Card className="w-full max-w-lg">
<CardHeader>
<CardTitle>Account Settings</CardTitle>
<CardDescription>
Update your account preferences and settings.
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleSubmit} className="space-y-6">
{/* Text Input */}
<div className="space-y-2">
<Label htmlFor="name">Display Name</Label>
<Input id="name" placeholder="Enter your name" />
</div>
{/* Email Input */}
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="you@example.com" />
</div>
{/* Textarea */}
<div className="space-y-2">
<Label htmlFor="bio">Bio</Label>
<Textarea id="bio" placeholder="Tell us about yourself..." rows={3} />
</div>
{/* Select */}
<div className="space-y-2">
<Label>Timezone</Label>
<Select>
<SelectTrigger>
<SelectValue placeholder="Select timezone" />
</SelectTrigger>
<SelectContent>
<SelectItem value="utc">UTC</SelectItem>
<SelectItem value="est">Eastern Time</SelectItem>
<SelectItem value="pst">Pacific Time</SelectItem>
</SelectContent>
</Select>
</div>
{/* Radio Group */}
<div className="space-y-2">
<Label>Preferred Contact</Label>
<RadioGroup defaultValue="email">
<div className="flex items-center space-x-2">
<RadioGroupItem value="email" id="contact-email" />
<Label htmlFor="contact-email">Email</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="sms" id="contact-sms" />
<Label htmlFor="contact-sms">SMS</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="push" id="contact-push" />
<Label htmlFor="contact-push">Push Notification</Label>
</div>
</RadioGroup>
</div>
{/* Checkbox */}
<div className="flex items-center space-x-2">
<Checkbox id="marketing" />
<Label htmlFor="marketing">Receive marketing emails</Label>
</div>
{/* Switch */}
<div className="flex items-center justify-between">
<Label htmlFor="notifications">Enable Notifications</Label>
<Switch
id="notifications"
checked={notifications}
onCheckedChange={setNotifications}
/>
</div>
{/* Slider */}
<div className="space-y-2">
<div className="flex justify-between">
<Label>Notification Volume</Label>
<span className="text-sm text-muted-foreground">{volume[0]}%</span>
</div>
<Slider
value={volume}
onValueChange={setVolume}
max={100}
step={1}
/>
</div>
</form>
</CardContent>
<CardFooter className="flex justify-end gap-2">
<Button variant="outline">Cancel</Button>
<Button type="submit">Save Changes</Button>
</CardFooter>
</Card>
);
}
This example demonstrates:
- ✅ Text and email inputs with labels
- ✅ Textarea for longer content
- ✅ Select dropdown with options
- ✅ Radio buttons for single selection
- ✅ Checkbox for boolean toggles
- ✅ Switch for on/off settings
- ✅ Slider for numeric values
- ✅ Card container for form layout
- ✅ Proper form submission handling