Component Reference

This is the canonical API reference for StyleLab UI. Each section describes a component’s purpose, props (with types), and a working example. Use it when implementing features or when an AI needs accurate usage details. All components require ThemeProvider and the @raxrai/stylelab-ui/styles import — see Installation & Theming.

Global

Types, context, and utilities shared across the library. Import from @raxrai/stylelab-ui.

Themes

  • StyleLabTheme — Union: "minimal" | "night" | "glass" | "neubrutal" | "clay" | "cyberpunk" | "retro" | "motion"
  • THEMES — Readonly array of all theme values (for dropdowns and validation)

Context

  • ThemeProviderdefaultTheme?: StyleLabTheme, children: ReactNode. Wrap your app so components receive the active theme.
  • useTheme() — Returns { theme: StyleLabTheme, setTheme: (theme) => void }. Use inside a provider.

Utilities

  • cn(...inputs) — Merges class names (Tailwind-aware). Accepts strings, objects, arrays.
  • getThemeClass(theme, component, variant?) — Returns the theme-specific class string for a given component and optional variant. Use when building custom components that follow StyleLab themes.
  • getNextListIndex(current, direction, length) — Returns the next index for list keyboard nav (direction: "up" | "down").

Accordion

A set of expandable panels. Only one panel is open at a time by default; set allowMultiple to true for multiple open panels. Each item has a unique id, a title (clickable header), and content (body).

When to use: FAQs, product details, or any collapsible sections where you have a list of title + content pairs.

Props

PropTypeRequiredDescription
itemsAccordionItem[]YesArray of { id, title: ReactNode, content: ReactNode }
allowMultiplebooleanNoIf true, multiple panels can be open at once. Default: false.
classNamestringNoAdditional CSS classes for the container.
themeStyleLabThemeNoOverride the context theme for this component.

Example

import { Accordion } from "@raxrai/stylelab-ui";

<Accordion
  items={[
    { id: "1", title: "Section 1", content: <p>Content here.</p> },
    { id: "2", title: "Section 2", content: <p>More content.</p> },
  ]}
  allowMultiple={false}
/>

Notes

  • ·AccordionItem.title and content can be React nodes (strings, elements, or fragments).
  • ·Supports theme prop for per-instance styling.

Alert

An inline alert or callout box. Use the intent prop to get the right semantic styling (info, success, warning, danger). Renders as a div with role='alert' by default.

When to use: Form errors, success messages, warnings, or informational banners above or below content.

Props

PropTypeRequiredDescription
intent"default" | "info" | "success" | "warning" | "danger"NoVisual and semantic variant. Default: "default".
titleReactNodeNoOptional heading above the alert body.
childrenReactNodeNoMain alert message or content.
classNamestringNoAdditional CSS classes.
themeStyleLabThemeNoOverride theme for this instance.

Example

import { Alert } from "@raxrai/stylelab-ui";

<Alert intent="warning" title="Heads up">
  This action cannot be undone.
</Alert>
<Alert intent="success">Saved successfully.</Alert>

Notes

  • ·Supports standard div HTML attributes (e.g. role, aria-*).

Avatar & AvatarGroup

Avatar shows a user's image or initials in a circle. When no image is provided, use fallback (e.g. initials "JD") or alt text (initials are derived from alt). AvatarGroup stacks multiple avatars and shows a +N badge when there are more than max.

When to use: User profiles, comment authors, team lists, or anywhere you need a compact user identity.

Props

PropTypeRequiredDescription
Avatar: srcstring | nullNoImage URL. When null/undefined, fallback or alt is used.
Avatar: altstringNoAccessible description; also used to derive initials when no fallback.
Avatar: fallbackstringNoShown when no image (e.g. initials). Overrides derived initials from alt.
AvatarGroup: childrenReactNodeYesOne or more Avatar elements.
AvatarGroup: maxnumberNoMax avatars to show before +N. Default: 4.
themeStyleLabThemeNoBoth support theme override.

Example

import { Avatar, AvatarGroup } from "@raxrai/stylelab-ui";

<Avatar src="/user.jpg" alt="Jane Doe" />
<Avatar fallback="JD" />
<AvatarGroup max={3}>
  <Avatar fallback="A" /><Avatar fallback="B" /><Avatar fallback="C" /><Avatar fallback="D" />
</AvatarGroup>

Notes

  • ·Avatar forwards a ref to the root div.
  • ·AvatarGroup wraps children in a flex container with overlap styling.

Badge

Small label or status pill. Renders as a span. Use variant for semantic color and dot for a leading indicator.

Props

  • ·variant?: "default" | "success" | "warning" | "error"
  • ·dot?: boolean — show a small dot before the label
  • ·children: ReactNode — badge text
  • ·className?, theme?

Example

import { Badge } from "@raxrai/stylelab-ui";

<Badge>New</Badge>
<Badge variant="success" dot>Active</Badge>

BentoGrid

A grid container for bento-style layouts. You control the grid via className (e.g. grid-cols-3 gap-4). Children are rendered inside the grid.

Props

  • ·children: ReactNode
  • ·className?: string

Example

import { BentoGrid } from "@raxrai/stylelab-ui";

<BentoGrid className="grid-cols-3 gap-4">
  <div>...</div><div>...</div><div>...</div>
</BentoGrid>

Button

Primary action button. Polymorphic: by default it renders a button; pass as='a' to render a link (and provide href). Supports loading state (spinner), left/right icons, and three visual variants.

When to use: Submit actions, navigation links (with as='a'), secondary actions, or icon-only buttons. Use variant='ghost' for low emphasis.

Props

PropTypeRequiredDescription
asElementTypeNoRender as this element. Default: "button". Use "a" for links.
variant"primary" | "secondary" | "ghost"NoVisual style. Default: "primary".
size"sm" | "md" | "lg"NoSize of the button. Default: "md".
isLoadingbooleanNoShows a spinner and disables click. Default: false.
leftIconReactNodeNoIcon or element before the label.
rightIconReactNodeNoIcon or element after the label.
childrenReactNodeNoButton label or content.
classNamestringNoAdditional CSS classes.

Example

import { Button } from "@raxrai/stylelab-ui";

<Button variant="primary">Save</Button>
<Button as="a" href="/home" variant="ghost">Home</Button>
<Button isLoading>Loading...</Button>
<Button leftIcon={<Icon />}>With icon</Button>

Notes

  • ·When as='a', pass standard anchor props (href, target, etc.). When as='button', pass disabled, type, onClick, etc.
  • ·Deprecated: loading prop — use isLoading instead.

Calendar

Single-date picker. Use controlled mode (value + onSelect) or uncontrolled (defaultValue). Optional min / max constrain selectable dates.

Props

  • ·value?: Date | null — controlled selected date
  • ·defaultValue?: Date | null — initial date (uncontrolled)
  • ·onSelect?: (date: Date) => void — called when user selects a date
  • ·min?: Date, max?: Date — date range bounds
  • ·className?, theme?

Example

import { Calendar } from "@raxrai/stylelab-ui";

<Calendar defaultValue={new Date()} onSelect={(d) => console.log(d)} />
<Calendar value={selected} onSelect={setSelected} min={new Date()} />

Card

Content container with optional header and footer slots. Use padding to control inner spacing and isHoverable for hover styling.

Props

  • ·padding?: "none" | "sm" | "md"
  • ·isHoverable?: boolean — adds hover lift/shadow
  • ·header?: ReactNode, footer?: ReactNode
  • ·children: ReactNode — main body
  • ·className?, theme?

Example

import { Card } from "@raxrai/stylelab-ui";

<Card header="Title" footer={<Button>Action</Button>}>
  Body content
</Card>

CommandPalette

A modal command palette (e.g. ⌘K). The list is filterable by typing; each item has id, label, and onSelect. Optional shortcut is shown on the right. Keyboard: Arrow keys, Enter to run, Escape to close.

Props

  • ·open: boolean — visibility
  • ·onClose: () => void — called on Escape or overlay click
  • ·commands: CommandItem[] (required). Each: { id: string, label: string, shortcut?: string, onSelect: () => void }
  • ·placeholder?: string — input placeholder. Default: "Type a command..."
  • ·theme?

Example

import { CommandPalette } from "@raxrai/stylelab-ui";

<CommandPalette
  open={open}
  onClose={() => setOpen(false)}
  commands={[
    { id: "1", label: "New file", onSelect: () => {} },
    { id: "2", label: "Save", shortcut: "⌘S", onSelect: () => {} },
  ]}
  placeholder="Type a command..."
/>

DashboardShell

Full dashboard layout with sidebar navigation, main content area, optional admin nav, and user menu (email, role, logout). Pass currentPath to highlight the active nav item. When userRole is "ADMIN", adminNavItems are shown.

Props

  • ·children: ReactNode
  • ·navItems: { href: string, label: string }[] (required)
  • ·adminNavItems?: { href: string, label: string }[]
  • ·currentPath?: string (highlights active item)
  • ·userEmail?: string, userRole?: string ("ADMIN" shows adminNavItems)
  • ·onLogout?: () => void
  • ·logo?: ReactNode
  • ·className?

Example

import { DashboardShell } from "@raxrai/stylelab-ui";

<DashboardShell
  navItems={[{ href: "/", label: "Home" }, { href: "/settings", label: "Settings" }]}
  currentPath={pathname}
  userEmail="u@example.com"
  onLogout={() => {}}
>
  <main>Page content</main>
</DashboardShell>

DataTable

Generic table: define columns (key, header, optional custom render) and data array. Use getRowKey for stable keys when rows can change.

Props

  • ·columns: Column<T>[] (required). Column: { key: keyof T | string, header: string, render?: (row: T) => ReactNode }
  • ·data: T[] (required)
  • ·getRowKey?: (row: T, index: number) => string | number
  • ·className?

Example

import { DataTable } from "@raxrai/stylelab-ui";

<DataTable
  columns={[
    { key: "name", header: "Name" },
    { key: "email", header: "Email", render: (r) => r.email },
  ]}
  data={[{ name: "Jane", email: "j@x.com" }]}
  getRowKey={(r) => r.email}
/>

DocumentAccordion

A single expandable section with title and content. When pdfUrl is provided, an inline PDF viewer is shown with an “Open PDF” link. Use defaultOpen to start expanded.

Props

  • ·title: ReactNode (required)
  • ·content?: ReactNode
  • ·pdfUrl?: string
  • ·defaultOpen?: boolean
  • ·className?, theme?

Example

import { DocumentAccordion } from "@raxrai/stylelab-ui";

<DocumentAccordion title="Syllabus" content="<p>Rich text...</p>" />
<DocumentAccordion title="PDF" pdfUrl="/doc.pdf" defaultOpen />

Flashcard

A flip card: one side shows the question, the other the answer. User interaction flips between them. Use for quizzes or learning UIs.

Props

  • ·question: string (required)
  • ·answer: string (required)
  • ·className?: string

Example

import { Flashcard } from "@raxrai/stylelab-ui";

<Flashcard question="What is 2+2?" answer="4" />

GraphicCard

A card with emphasis styling (e.g. gradient, shadow) for hero sections or feature callouts. Content is passed as children.

Props

  • ·children: ReactNode
  • ·className?: string

Example

import { GraphicCard } from "@raxrai/stylelab-ui";

<GraphicCard><p>Highlighted content</p></GraphicCard>

Input

Text input with optional label, error, helperText, and prefix / suffix. Forwards ref to the native input. Supports all standard input attributes (placeholder, value, onChange, disabled, etc.); the component’s size overrides the HTML size attribute.

Props

  • ·size?: "sm" | "md" | "lg"
  • ·label?: string
  • ·error?: string, helperText?: string
  • ·prefix?: ReactNode, suffix?: ReactNode
  • ·className?, theme?
  • ·Plus standard input HTML attributes (placeholder, value, onChange, disabled, etc.). Component size overrides HTML size.

Example

import { Input } from "@raxrai/stylelab-ui";

<Input label="Email" placeholder="you@example.com" />
<Input label="Name" error="Required" />

PricingCard

A card for a pricing tier. Pass a tier object: name, price, description, features array, cta label, and optional highlighted. Use onSelect when the user clicks the CTA.

Props

  • ·tier: Tier (required). Tier: { name: string, price: string, description?: string, features: string[], cta: string, highlighted?: boolean }
  • ·onSelect?: () => void
  • ·className?

Example

import { PricingCard } from "@raxrai/stylelab-ui";

<PricingCard
  tier={{
    name: "Pro",
    price: "$20/mo",
    features: ["Feature 1", "Feature 2"],
    cta: "Get started",
    highlighted: true,
  }}
  onSelect={() => {}}
/>

ProgressBar

Progress indicator. Fill is determined by value / max (max defaults to 100). Use segmented for a step-style bar.

Props

  • ·value: number (required)
  • ·max?: number (default 100)
  • ·segmented?: boolean
  • ·className?

Example

import { ProgressBar } from "@raxrai/stylelab-ui";

<ProgressBar value={60} />
<ProgressBar value={7} max={10} segmented />

SectionHeader

Section title with optional subtitle and a bottom border. Content is prop-based only (no children). Use for page or section headings.

Props

  • ·title: string (required)
  • ·subtitle?: string
  • ·className?
  • ·style?

Example

import { SectionHeader } from "@raxrai/stylelab-ui";

<SectionHeader title="Getting started" subtitle="Follow these steps." />

Skeleton

Loading placeholder with a subtle shimmer. Use variant to match the shape of the content (rectangle, circle, or text line).

Props

  • ·variant?: "rectangle" | "circle" | "text"
  • ·className?, theme?
  • ·Plus standard div attributes

Example

import { Skeleton } from "@raxrai/stylelab-ui";

<Skeleton />
<Skeleton variant="circle" className="size-10" />
<Skeleton variant="text" className="w-32" />

Slider

Numeric range input. Controlled: value + onValueChange. Uncontrolled: defaultValue. Supports min, max, step, and size.

Props

  • ·size?: "sm" | "md" | "lg"
  • ·min?: number, max?: number, step?: number
  • ·value?: number (controlled), defaultValue?: number
  • ·onValueChange?: (value: number) => void
  • ·className?, theme?

Example

import { Slider } from "@raxrai/stylelab-ui";

<Slider min={0} max={100} defaultValue={50} onValueChange={setValue} />

StatsCard

A small card for a single metric: label (e.g. “Revenue”), value (number or string), and optional trend (direction up/down and value string like “+8%”).

Props

  • ·label: string, value: string | number (required)
  • ·trend?: { direction: "up" | "down", value: string }
  • ·className?

Example

import { StatsCard } from "@raxrai/stylelab-ui";

<StatsCard label="Revenue" value="$12k" trend={{ direction: "up", value: "+8%" }} />

Tabs

Tabbed UI: each item has label, value, and content. Use value / onValueChange (controlled) or defaultValue.

Props

  • ·items: TabItem[] (required). TabItem: { label: string, value: string, content: ReactNode }
  • ·value?: string, defaultValue?: string
  • ·onValueChange?: (value: string) => void
  • ·className?, theme?

Example

import { Tabs } from "@raxrai/stylelab-ui";

<Tabs
  items={[
    { label: "Tab A", value: "a", content: <p>A</p> },
    { label: "Tab B", value: "b", content: <p>B</p> },
  ]}
  defaultValue="a"
/>

Terminal

Terminal-style block for commands or log output. Optional title (e.g. “bash”); children are the content inside the terminal.

Props

  • ·title?: string
  • ·children: ReactNode
  • ·className?: string

Example

import { Terminal } from "@raxrai/stylelab-ui";

<Terminal title="bash">
  <span>$ npm install @raxrai/stylelab-ui</span>
</Terminal>

Timeline

Vertical timeline. Each item has title (required) and optional description and time. Good for activity feeds or step lists.

Props

  • ·items: TimelineItem[] (required). TimelineItem: { title: ReactNode, description?: ReactNode, time?: ReactNode }
  • ·className?, theme?

Example

import { Timeline } from "@raxrai/stylelab-ui";

<Timeline
  items={[
    { title: "Step 1", description: "Done", time: "10:00" },
    { title: "Step 2", time: "11:00" },
  ]}
/>

Toast

Dismissible toast notification. Content is via message; onDismiss is called when the user closes it. No children; use for transient feedback.

Props

  • ·message: string (required)
  • ·onDismiss: () => void (required)
  • ·className?
  • ·style?

Example

import { Toast } from "@raxrai/stylelab-ui";

<Toast message="Saved successfully." onDismiss={() => setVisible(false)} />

Toggle

Checkbox-style toggle switch. Controlled: checked + onCheckedChange. Uncontrolled: defaultChecked. Forwards ref to the input.

Props

  • ·checked?: boolean, defaultChecked?: boolean
  • ·onCheckedChange?: (checked: boolean) => void
  • ·className?, theme?
  • ·Plus standard input attributes except value, type, onChange, size

Example

import { Toggle } from "@raxrai/stylelab-ui";

<Toggle checked={on} onCheckedChange={setOn} />
<Toggle defaultChecked />

Tooltip

Shows content on hover over the trigger (children). Use placement to control where the tooltip appears (top, bottom, left, right).

Props

  • ·content: ReactNode (required)
  • ·children: ReactNode (required) — trigger element
  • ·placement?: "top" | "bottom" | "left" | "right"
  • ·className?, theme?

Example

import { Tooltip } from "@raxrai/stylelab-ui";

<Tooltip content="Save the document" placement="top">
  <button>Save</button>
</Tooltip>

Hooks

Utility hooks for focus management, click-outside, and keyboard navigation. Import from @raxrai/stylelab-ui.

Reference

  • ·useFocusTrap(active: boolean, options?: { returnFocus?: boolean }): RefObject<HTMLElement | null> — attach ref to container to trap focus
  • ·useClickOutside(ref | ref[], handler: (e) => void, options?: { enabled?: boolean }): void — run handler when click is outside ref(s)
  • ·useKeyboardNavigation({ onEscape?, onArrowDown?, onArrowUp?, onArrowLeft?, onArrowRight?, enabled? }): void — attach to container for arrow/escape handling
  • ·getNextListIndex(current: number, direction: "up" | "down", length: number): number — for list keyboard nav