OTFotf

Composite

Opinionated, finished patterns built on top of the primitives.

These 16 components are higher-level than primitives — they're the patterns we'd otherwise hand-roll on every project. Each one bundles a few primitives + tokens + a sensible default behavior so you can drop it in and move on.

System-wide announcement bar. Supports dismissal, info / warning / error tones, and a CTA slot.

import { Banner } from '@otfdashkit/ui'

<Banner tone="info" dismissible>
  Heads up — we're moving to v2 next week. <a href="/changelog">Read more</a>
</Banner>

Slash-separated path with the last segment shown as plain text.

<Breadcrumb items={[
  { label: 'Workspace', href: '/' },
  { label: 'Settings', href: '/settings' },
  { label: 'Notifications' },
]} />

CommandItem

A single row inside a command palette — icon + label + optional shortcut hint.

<CommandItem icon={<Settings />} shortcut="⌘,">
  Open settings
</CommandItem>

DataGrid

Read-only data renderer for sparse / heterogeneous rows. For full table behavior (sort, filter, bulk-select), use DataTable.

<DataGrid
  columns={[
    { key: 'name', label: 'Name' },
    { key: 'role', label: 'Role' },
    { key: 'lastSeen', label: 'Last seen', render: (v) => <RelativeTime value={v} /> },
  ]}
  rows={users}
/>

DataTable

The tablestakes table — headers, sortable columns, optional row selection, optional bulk-action bar wired through to <BulkActions>. Columns are typed; rows are inferred.

<DataTable
  data={issues}
  columns={[
    { accessorKey: 'title', header: 'Title' },
    { accessorKey: 'status', header: 'Status' },
    { accessorKey: 'assignee', header: 'Assignee' },
  ]}
  enableRowSelection
  onRowSelectionChange={setSelected}
/>

EmptyState

Centered placeholder with an icon, title, description, and a CTA. Use it everywhere a list would otherwise be empty.

<EmptyState
  icon={<Inbox />}
  title="Inbox zero"
  description="You're all caught up. New notifications appear here."
  action={<Button>Configure alerts</Button>}
/>

Hotkeys

Render a keyboard chord with platform-correct symbols (⌘ on macOS, Ctrl elsewhere).

<Hotkeys keys={['mod', 'k']} />   {/* renders ⌘K on Mac, Ctrl+K on Windows */}

IconBadge

A square or pill background behind a Lucide icon — mostly used inside Persona, Stat, list rows.

<IconBadge icon={<Bell />} tone="primary" size="md" />

LoadingOverlay

Full-element overlay with spinner. Useful for "saving" / "syncing" states without unmounting the underlying form.

<div className="relative">
  <Form ... />
  {isSubmitting && <LoadingOverlay />}
</div>

Persona

Avatar + name + role on one row. Optional subtitle, status dot, and trailing actions.

<Persona
  name="Sarah Chen"
  subtitle="Product Lead, Northbeam"
  imageUrl="/avatars/sarah.jpg"
  size="md"
  ring
/>

PropertyList

Two-column key/value list — used for "details" panes (issue, project, settings).

<PropertyList
  items={[
    { label: 'Status', value: <Badge>Active</Badge> },
    { label: 'Created', value: 'Sep 24, 2024' },
    { label: 'Owner', value: <Persona name="Alex Rivera" size="sm" /> },
  ]}
/>

Stat

Big-number + label + optional delta with trend arrow. The KPI tile.

<Stat
  label="Active users"
  value="12,406"
  delta="+12% vs last week"
  trend="up"
/>

Stepper

Horizontal or vertical multi-step progress indicator with direction prop.

<Stepper
  steps={['Account', 'Workspace', 'Invite team', 'Done']}
  current={1}
  direction="horizontal"
/>

StructuredList

Vertically-stacked rows of (icon · title · subtitle · trailing). Used for settings, profile, notification feeds — anywhere you'd reach for a <ul> and end up styling it.

<StructuredList items={[
  { icon: <Bell />, title: 'Email notifications', trailing: <Switch /> },
  { icon: <Lock />, title: 'Two-factor auth', trailing: <Badge>Off</Badge> },
]} />

Timeline

Vertical activity feed with timestamps and optional avatars per entry.

<Timeline items={[
  { time: '2h ago', title: 'Sarah commented on #42', icon: <MessageSquare /> },
  { time: '5h ago', title: 'Alex resolved #41', icon: <Check /> },
]} />

Toaster

Mounted once at the root; pairs with the imperative toast() function.

import { Toaster, toast } from '@otfdashkit/ui'

<Toaster />
toast.success('Saved')
toast.error('Network error', { description: 'Check your connection and try again.' })

See also

  • Blocks — full-section blocks (sidebars, modals, dashboards)
  • Advanced — Kanban, Gantt, CommandBar, Filters, BulkActions, Rich Editor

On this page