API documentation for all shared components included in the template.
At scale: The template ships 30 components. In production (Overtooled, 178+ features), this grew to 54. Key additions include chain system UI (ChainableOutput, ChainButton, ChainPopover, ChainStepCard, ChainParamForm, ChainSuggestionList), game support (GameShell), data display (StatCard, Table, CodeBlock), navigation (CommandPalette, SearchDropdown, RelatedTools), and file handling (FilePreview, GlobalDropZone).
<Button onClick={handler} variant="primary" size="md" disabled={false}>
Click me
</Button>| Prop | Type | Default | Options |
|---|---|---|---|
variant |
string |
'primary' |
'primary', 'secondary', 'danger', 'ghost' |
size |
string |
'md' |
'sm', 'md', 'lg' |
disabled |
boolean |
false |
|
className |
string |
Additional Tailwind classes |
<Input label="Name" value={name} onChange={setName} placeholder="Enter name" />| Prop | Type | Description |
|---|---|---|
label |
string |
Label text (auto-generates id for accessibility) |
value |
string |
Controlled value |
onChange |
(value) => void |
Change handler (receives value, not event) |
error |
string |
Error message displayed below input |
<Textarea label="Content" value={text} onChange={setText} rows={6} />Same API as Input, plus rows prop for height.
<Select label="Format" value={format} onChange={setFormat} options={[
{ value: 'json', label: 'JSON' },
{ value: 'csv', label: 'CSV' },
]} /><Toggle label="Dark mode" checked={isDark} onChange={setIsDark} /><Slider label="Volume" value={volume} onChange={setVolume} min={0} max={100} step={1} /><RadioGroup label="Size" value={size} onChange={setSize} options={[
{ value: 'sm', label: 'Small' },
{ value: 'md', label: 'Medium' },
{ value: 'lg', label: 'Large' },
]} />Content container with optional title, icon, and actions.
<Card title="Results" icon={BarChart} actions={<Button size="sm">Export</Button>}>
{children}
</Card>Status messages with variant styling.
<Alert variant="warning" title="Heads up">
This action cannot be undone.
</Alert>Variants: 'info', 'success', 'warning', 'error'
Placeholder for when there's no data to display.
<EmptyState icon={FileText} title="No results" description="Try a different search." />Centered loading indicator.
<LoadingSpinner />Display key-value pairs with optional copy buttons.
<KeyValueList items={[
{ key: 'Status', value: 'Active' },
{ key: 'Created', value: '2024-01-15' },
]} copyable />Output display box with built-in copy button.
<ResultDisplay value={output} label="Output" />Copy text to clipboard with visual feedback.
<CopyButton text={textToCopy} />Download data as a file.
<DownloadButton data={content} filename="output.json" mimeType="application/json">
Download JSON
</DownloadButton>Drag-and-drop file input with validation.
<FileUpload accept=".json,.csv" maxSize={5 * 1024 * 1024} onFile={handleFile}>
Drop a file here or click to browse
</FileUpload>Tab switcher for multiple views.
<TabGroup tabs={['Input', 'Output', 'Settings']} active={activeTab} onChange={setActiveTab} />Pill-button toggle for mode selection (encode/decode, format/minify, etc.).
<ModeToggle options={['Encode', 'Decode']} value={mode} onChange={setMode} />Quick-select filter pills.
<PresetButtons options={['All', 'Active', 'Completed']} value={filter} onChange={setFilter} />Modal confirmation with danger variant.
<ConfirmDialog
isOpen={showConfirm}
title="Delete item?"
message="This action cannot be undone."
confirmLabel="Delete"
variant="danger"
onConfirm={handleDelete}
onCancel={() => setShowConfirm(false)}
/>Modal with optional tabbed content.
<InfoDialog isOpen={showInfo} title="About" onClose={() => setShowInfo(false)}>
<p>Information content here.</p>
</InfoDialog>Context-based notifications. Use the useToast hook:
import { useToast } from '../contexts/ToastContext';
const { showToast } = useToast();
showToast('File saved successfully', 'success');
showToast('Something went wrong', 'error');Variants: 'success', 'error', 'info', 'warning'
Responsive two-column layout.
<SplitPane ratio="1:1">
<div>{/* Left */}</div>
<div>{/* Right */}</div>
</SplitPane>Stacks vertically on mobile, splits horizontally on desktop. Ratios: '1:1', '1:2', '2:1'
Standard page wrapper with title, description, and consistent spacing.
<FeatureLayout title="My Feature" description="What this feature does.">
{children}
</FeatureLayout>Collapsible content section.
<ToolSection title="Advanced Settings" defaultOpen={false}>
{children}
</ToolSection>Reusable history/list display with clear and custom rendering.
<HistoryPanel
items={history}
renderItem={(item) => <span>{item.value}</span>}
onClear={() => setHistory([])}
emptyMessage="No history yet"
/>Complete file-in/file-out processing pattern with drag-and-drop, progress, and batch download.
<FileProcessorLayout
accept=".png,.jpg"
processFile={handleFile}
outputExtension=".webp"
/>Multi-mode input for batch operations (list, range, CSV).
<BatchInput mode={mode} onModeChange={setMode} onSubmit={handleBatch} />Grid display for batch processing results.
<BatchPreviewGrid items={results} renderItem={(item) => <img src={item.url} />} />Platform-aware keyboard shortcut display.
<KeyboardShortcutHint keys={['Ctrl', 'S']} />
// Renders "Ctrl+S" on Windows, "Cmd+S" on Mac"Work in progress" banner for incomplete features.
<WipBanner message="This feature is still being built." />Visual indicator that data stays local.
<PrivacyBadge />