COMPONENTS
90 pre-built components organized by category. All use design tokens and the terminal aesthetic.
[DESIGN RULES]
All FABRK components follow these rules. Apply them when composing components together.
import { Button, Card, Badge, BarChart, KPICard } from '@fabrk/components'
import { cn } from '@fabrk/core'
import { mode } from '@fabrk/design-system'// RULE 1: Full borders — ALWAYS add mode.radius
<Card className={cn("border border-border", mode.radius)}>
<div className={cn("border-2 border-border", mode.radius)}>
// RULE 2: Partial borders — NEVER add mode.radius
<div className="border-t border-border">
<div className="border-b border-border">
// RULE 3: Table cells — NEVER add mode.radius (breaks layout)
<td className="border-b border-border px-4 py-3">
// RULE 4: Switches — Always rounded-full (pill-shaped)
<Switch className="rounded-full">
// RULE 5: Button text — UPPERCASE with > prefix
<Button>> SUBMIT</Button>
<Button>> CONTINUE</Button>
// RULE 6: Labels — UPPERCASE in brackets
<Badge>[ACTIVE]</Badge>
<span>[SYSTEM]</span>
// RULE 7: Use design tokens — NEVER hardcode colors
className="bg-primary text-primary-foreground" // correct
className="bg-blue-500 text-white" // WRONGText: text-foreground, text-muted-foreground, text-primary, text-destructive, text-success
Borders: border-border, border-primary
[KEY COMPONENT EXAMPLES]
Code examples for the most commonly used components. See the full category listing below for all 90 components.
KPICARD
Key performance indicator card with value, label, and trend arrow.
import { KPICard } from '@fabrk/components'
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<KPICard title="REVENUE" value="$12,340" trend={12.5} />
<KPICard title="USERS" value="1,572" trend={8.3} />
<KPICard title="ERRORS" value="3" trend={-50.0} />
<KPICard title="UPTIME" value="99.9%" trend={0.1} />
</div>DATATABLE
Sortable, filterable data table with pagination. Accepts column definitions and row data.
import { DataTable } from '@fabrk/components'
const columns = [
{ key: 'name', label: 'NAME', sortable: true },
{ key: 'email', label: 'EMAIL', sortable: true },
{ key: 'role', label: 'ROLE' },
{ key: 'status', label: 'STATUS' },
]
const data = [
{ name: 'Jason', email: 'jason@example.com', role: 'Admin', status: 'Active' },
{ name: 'Sarah', email: 'sarah@example.com', role: 'Member', status: 'Active' },
{ name: 'Mike', email: 'mike@example.com', role: 'Member', status: 'Invited' },
]
<DataTable
columns={columns}
data={data}
onSort={(key, direction) => console.log(key, direction)}
onRowClick={(row) => router.push(`/users/${row.id}`)}
/>BARCHART AND LINECHART
Data visualization with theme-aware colors. All 8 chart types share a consistent API.
import { BarChart, LineChart, Card } from '@fabrk/components'
import { cn } from '@fabrk/core'
import { mode } from '@fabrk/design-system'
const revenueData = [
{ label: 'Jan', value: 4200 },
{ label: 'Feb', value: 5100 },
{ label: 'Mar', value: 4800 },
{ label: 'Apr', value: 6300 },
{ label: 'May', value: 7200 },
]
// Bar chart
<Card className={cn('p-6 border border-border', mode.radius)}>
<h3 className={cn('text-xs uppercase mb-4', mode.font)}>[MONTHLY REVENUE]</h3>
<BarChart data={revenueData} />
</Card>
// Line chart
<Card className={cn('p-6 border border-border', mode.radius)}>
<h3 className={cn('text-xs uppercase mb-4', mode.font)}>[TREND]</h3>
<LineChart data={revenueData} />
</Card>DONUTCHART AND GAUGE
import { DonutChart, Gauge } from '@fabrk/components'
// Donut chart with center label
<DonutChart
data={[
{ label: 'Desktop', value: 62 },
{ label: 'Mobile', value: 28 },
{ label: 'Tablet', value: 10 },
]}
centerLabel="TRAFFIC"
/>
// Circular gauge
<Gauge value={73} max={100} label="CPU USAGE" />CHAT COMPONENTS
Build AI chat interfaces with ChatInput, ChatMessageList, and TokenCounter.
import {
ChatInput, ChatMessageList, ChatSidebar, TokenCounter, UsageBar
} from '@fabrk/components'
function AIChat({ messages, conversations, onSend, onSelectConversation }) {
return (
<div className="flex h-screen">
{/* Conversation sidebar */}
<ChatSidebar
conversations={conversations}
onSelect={onSelectConversation}
onNew={() => createConversation()}
/>
{/* Main chat area */}
<div className="flex-1 flex flex-col">
<div className="flex items-center justify-between p-4 border-b border-border">
<h2 className="text-sm font-bold uppercase">[CHAT]</h2>
<TokenCounter used={1250} limit={4096} />
</div>
<ChatMessageList messages={messages} className="flex-1" />
<div className="p-4 border-t border-border">
<UsageBar used={23.50} limit={50} label="DAILY BUDGET" />
<ChatInput onSend={onSend} placeholder="Ask anything..." />
</div>
</div>
</div>
)
}NOTIFICATION CENTER
import {
NotificationCenter, NotificationBadge, NotificationList
} from '@fabrk/components'
// Dropdown notification center
<NotificationCenter
notifications={notifications}
onMarkRead={(id) => markAsRead(id)}
onMarkAllRead={() => markAllRead()}
/>
// Or build your own with parts
<div className="relative">
<NotificationBadge count={unreadCount} />
<NotificationList
notifications={notifications}
onDismiss={(id) => dismiss(id)}
/>
</div>MFA COMPONENTS
import { MfaCard, MfaSetupDialog, BackupCodesModal } from '@fabrk/components'
// MFA status card
<MfaCard
enabled={user.mfaEnabled}
onEnable={() => setShowSetup(true)}
onDisable={() => disableMfa()}
/>
// Setup dialog with QR code
<MfaSetupDialog
open={showSetup}
onOpenChange={setShowSetup}
onSetup={async (secret) => {
await api.post('/api/mfa/enable', { secret })
}}
renderQrCode={(uri) => <QRCode value={uri} />}
/>
// Backup codes modal
<BackupCodesModal
codes={backupCodes}
onRegenerate={() => api.post('/api/mfa/regenerate')}
/>PRICING AND MARKETING
import { PricingCard, UpgradeCTA, OnboardingChecklist } from '@fabrk/components'
// Pricing cards
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<PricingCard
title="FREE"
price="$0"
period="/month"
features={['5 projects', '1GB storage', 'Community support']}
onSelect={() => selectPlan('free')}
/>
<PricingCard
title="PRO"
price="$29"
period="/month"
features={['Unlimited projects', '100GB storage', 'Priority support', 'API access']}
highlighted={true}
onSelect={() => selectPlan('pro')}
/>
<PricingCard
title="ENTERPRISE"
price="Custom"
features={['Everything in Pro', 'SSO/SAML', 'Dedicated support', 'SLA']}
onSelect={() => contactSales()}
/>
</div>
// Onboarding checklist
<OnboardingChecklist
items={[
{ id: 'profile', label: 'Complete your profile', completed: true },
{ id: 'team', label: 'Invite team members', completed: true },
{ id: 'integration', label: 'Connect your first integration', completed: false },
{ id: 'deploy', label: 'Deploy to production', completed: false },
]}
onItemClick={(id) => router.push(`/onboarding/${id}`)}
/>TERMINAL FEEDBACK
import {
TerminalSpinner, AsciiProgressBar, StatusPulse,
Typewriter, LogStream
} from '@fabrk/components'
// Terminal loading spinner
<TerminalSpinner label="DEPLOYING..." />
// ASCII progress bar: [████████░░░░░░░░] 52%
<AsciiProgressBar value={52} max={100} />
// Status indicator with pulse animation
<StatusPulse status="healthy" label="API" />
<StatusPulse status="degraded" label="DATABASE" />
<StatusPulse status="down" label="QUEUE" />
// Typewriter text effect
<Typewriter text="Initializing FABRK framework..." speed={50} />
// Real-time log stream
<LogStream
entries={[
{ timestamp: '12:03:45', level: 'info', message: 'Server started on port 3000' },
{ timestamp: '12:03:46', level: 'info', message: 'Connected to database' },
{ timestamp: '12:03:47', level: 'warn', message: 'Rate limiter using in-memory store' },
]}
/>ERROR BOUNDARY
import { ErrorBoundary } from '@fabrk/components'
// Wrap your app or sections in ErrorBoundary
<ErrorBoundary
fallback={({ error, reset }) => (
<div className="p-6 text-center">
<div className="text-destructive text-sm font-bold uppercase">
[RUNTIME ERROR]
</div>
<p className="text-muted-foreground text-xs mt-2">{error.message}</p>
<button onClick={reset} className="mt-4 text-primary text-xs">
> RETRY
</button>
</div>
)}
>
<App />
</ErrorBoundary>[PROPS REFERENCE]
Prop definitions for the most commonly used components. For the full API, run pnpm docs:api.
BUTTON
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
| variant | "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | "default" | Visual style variant |
| size | "default" | "sm" | "lg" | "icon" | "default" | Button size |
| loading | boolean | false | Show loading spinner and disable button |
| loadingText | string | — | Accessible label shown during loading |
| asChild | boolean | false | Render as child element (Slot) |
CARD
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
| className | string | — | Additional CSS classes. Always add mode.radius for border radius. |
| children | ReactNode | — | Card content. Use CardHeader, CardContent, CardFooter for structure. |
KPICARD
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
| title | string | — | KPI label (renders UPPERCASE) |
| value | string | number | — | Display value |
| trend | number | — | Percentage change. Positive = green arrow up, negative = red arrow down. |
| icon | ReactNode | — | Optional icon beside the title |
DATATABLE
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
| columns | ColumnDef[] | — | TanStack Table column definitions |
| data | T[] | — | Row data array |
| searchKey | string | — | Column key to enable search filtering |
| onRowClick | (row: T) => void | — | Callback when a row is clicked |
| pageSize | number | 10 | Rows per page |
BARCHART
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
| data | { label: string; value: number }[] | — | Chart data points |
| height | number | 300 | Chart height in pixels |
| horizontal | boolean | false | Render as horizontal bar chart |
| stacked | boolean | false | Stack bars (for multi-series data) |
| colorByIndex | boolean | false | Use different colors per bar |
STARRATING
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
| value | number | — | Current rating value |
| max | number | 5 | Maximum number of stars |
| onChange | (value: number) => void | — | Callback when a star is clicked |
| readonly | boolean | false | Display-only mode, disables interaction |
| size | "sm" | "md" | "lg" | "md" | Star size |
NPSSURVEY
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
| onSubmit | (score: number, feedback?: string) => void | — | Callback with score (0-10) and optional feedback text |
| onDismiss | () => void | — | Callback when dismiss button is clicked |
| title | string | "How likely..." | Survey question text |
GAUGE
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
| value | number | — | Current value |
| max | number | 100 | Maximum value |
| label | string | — | Label below the gauge |
| unit | string | — | Unit suffix (e.g., "%") |
| segments | { color: string; end: number }[] | — | Color segments for the arc |
DIALOG
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
| open | boolean | — | Controlled open state |
| onOpenChange | (open: boolean) => void | — | Callback when open state changes |
| children | ReactNode | — | Use DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription |
SELECT
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
| value | string | — | Controlled selected value |
| onValueChange | (value: string) => void | — | Callback when selection changes |
| placeholder | string | — | Placeholder text when no value is selected |
| disabled | boolean | false | Disable the select |
CHATINPUT
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
| onSend | (message: string, attachments?: File[]) => void | — | Callback when message is sent (Enter key or button) |
| onStop | () => void | — | Callback when stop button is clicked during streaming |
| isLoading | boolean | false | Show stop button instead of send button |
| models | { id: string; name: string }[] | — | Available AI models for the model selector |
| selectedModelId | string | — | Currently selected model ID |
| onModelChange | (modelId: string) => void | — | Callback when model selection changes |
MFACARD
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
| twoFactorEnabled | boolean | — | Current 2FA status |
| onEnable2FA | () => void | — | Callback to start MFA setup |
| onDisable2FA | () => void | — | Callback to disable MFA |
| onViewBackupCodes | () => void | — | Callback to view backup codes |
| isEnabling2FA | boolean | — | Loading state for enable action |
| isDisabling2FA | boolean | — | Loading state for disable action |
COOKIECONSENT
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
| onAcceptAll | (prefs: CookiePreferences) => void | — | Callback when all cookies are accepted |
| onAcceptSelected | (prefs: CookiePreferences) => void | — | Callback when selected cookies are accepted |
| onRejectAll | (prefs: CookiePreferences) => void | — | Callback when all non-essential cookies are rejected |
| cookieKey | string | "cookie-consent" | localStorage key for persisting preferences |
SEGMENTEDCONTROL
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
| options | { value: T; label: string; disabled?: boolean }[] | — | Segment options |
| value | T | — | Currently selected value |
| onChange | (value: T) => void | — | Callback when selection changes |
| size | "sm" | "md" | "lg" | "md" | Control size |
PROGRESS
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
| value | number | — | Progress value (0-100) |
| label | string | — | Label text above the bar |
| showPercentage | boolean | true | Show percentage text |
| size | "sm" | "md" | "lg" | "md" | Bar height |
[ALL CATEGORIES]
[FORM CONTROLS]
Input components for forms and data entry.
[LAYOUT]
Structural layout components.
[DATA DISPLAY]
Components for displaying data and metrics.
[CHARTS]
8 chart types for data visualization. All use design tokens and support theming.
[FEEDBACK]
User interaction and feedback components.
[AI]
AI chat and interaction components.
[ADMIN]
Admin dashboard components.
[SECURITY]
Security and authentication UI.
[ORGANIZATION]
Team and organization management.
[MARKETING]
Marketing and onboarding.