@raxrai/stylelab-ui
v0.4.1
Published
Themeable UI library with 8 themes: Minimal, Night, Glass, Neubrutal, Clay, Cyberpunk, Retro, Motion
Downloads
746
Maintainers
Readme
StyleLab UI
A themeable, accessible React UI library with 8 themes: Minimal, Night, Glass, Neubrutal, Clay, Cyberpunk, Retro, and Motion. Built with Tailwind CSS v4, CVA, and Lucide icons. Zero extra dependencies at install time — only React and React DOM as peers; everything else is bundled.
Live site (demo, gallery, docs): https://stylelab.rajarai.com
Installation
Next.js or any existing React app (you already have React):
npm install @raxrai/stylelab-uiNew project without React (e.g. empty folder):
npm install @raxrai/stylelab-ui react react-domThe package lists react and react-dom as peer dependencies (>=18). Next.js and Create React App already include them, so you don’t install them again. Other runtime deps (cva, clsx, tailwind-merge, lucide-react, framer-motion) are bundled, so no extra install is required.
1. Tailwind + styles
Your app must use Tailwind CSS v4. Import StyleLab design tokens in your global CSS after Tailwind:
@import "tailwindcss";
@import "@raxrai/stylelab-ui/styles";2. ThemeProvider
Wrap your app so components receive the active theme:
import { ThemeProvider } from "@raxrai/stylelab-ui";
export default function RootLayout({ children }) {
return (
<html>
<body>
<ThemeProvider defaultTheme="minimal">{children}</ThemeProvider>
</body>
</html>
);
}Optional props: storageKey (default "stylelab-theme") for the localStorage key; persistTheme (default true). When persistTheme={false}, the provider does not read or write localStorage (theme is fixed to defaultTheme unless you change it in memory).
3. Use components
import { Button, Card, useTheme } from "@raxrai/stylelab-ui";
export function MyPage() {
const { theme, setTheme } = useTheme();
return (
<div>
<Button variant="primary">Click me</Button>
<Card>Content</Card>
</div>
);
}Themes: minimal | night | glass | neubrutal | clay | cyberpunk | retro | motion
What’s in the package
Components: Accordion, Alert, Avatar, AvatarGroup, Badge, BentoGrid, Breadcrumbs, Button, Calendar, Card, CommandPalette, DashboardShell, DataTable, DocumentAccordion, Dropdown, Flashcard, GraphicCard, Input, Modal, Navbar, PricingCard, ProgressBar, SectionHeader, Sidebar, Skeleton, Slider, StatsCard, Tabs, Terminal, Timeline, Toast, Toggle, Tooltip.
Global: ThemeProvider, useTheme, getThemeClass, THEMES, StyleLabTheme, cn, mergeRefs, getNextListIndex, useFocusTrap, useClickOutside, useKeyboardNavigation. Component roots support ref forwarding and style / className (consumer className applied last for overrides).
- See all components and try themes: stylelab.rajarai.com
- Full API (props, types, hooks): docs/COMPONENTS.md in this repo.
Component API (overview)
Button
| Prop | Type | Default | Description |
|------------|--------------------------|------------|--------------------------------------|
| as | "button" | "a" | "button" | Polymorphic root element |
| variant | "primary" | "secondary" | "ghost" | "primary" | Visual variant |
| size | "sm" | "md" | "lg" | "md" | Size |
| isLoading| boolean | false | Shows spinner and disables |
| leftIcon | ReactNode | — | Icon before children |
| rightIcon| ReactNode | — | Icon after children |
| className| string | — | Merged with CVA classes |
| ref | ForwardedRef | — | Forwarded to root DOM element |
Input
| Prop | Type | Default | Description |
|-------------|------------|---------|--------------------------------|
| label | string | — | Accessible label |
| error | string | — | Error message (role="alert") |
| helperText| string | — | Hint below input |
| prefix | ReactNode| — | Left addon |
| suffix | ReactNode| — | Right addon |
| size | "sm" | "md" | "lg" | "md" | Size (CVA) |
| className | string | — | Merged with CVA |
Toggle
| Prop | Type | Default | Description |
|-------------------|------------|---------|--------------------------------|
| checked | boolean | — | Controlled state |
| defaultChecked | boolean | false | Uncontrolled initial state |
| onCheckedChange| (v: boolean) => void | — | Callback on change |
| aria-label | string | "Toggle" | Accessible name |
Uses a hidden <input type="checkbox"> for semantics and form compatibility.
Badge
| Prop | Type | Default | Description |
|------------|----------|-----------|----------------------|
| variant | "default" | "success" | "warning" | "error" | "default" | Style variant |
| dot | boolean| false | Leading dot indicator |
Slider
| Prop | Type | Default | Description |
|-----------------|----------|---------|--------------------------|
| min / max | number | 0 / 100 | Range bounds |
| step | number | 1 | Step value |
| value | number | — | Controlled value |
| defaultValue | number | 50 | Uncontrolled initial |
| onValueChange | (v: number) => void | — | Change callback |
| size | "sm" | "md" | "lg" | "md" | Track size |
Tabs
| Prop | Type | Default | Description |
|----------------|-------------------------|---------|----------------------------|
| items | { label, value, content }[] | — | Tab list |
| value | string | — | Controlled active tab |
| defaultValue | string | — | Uncontrolled initial |
| onValueChange| (value: string) => void | — | Callback on tab change |
Arrow keys (Left/Right) move focus and change tab; theme from context or theme prop.
Card
| Prop | Type | Default | Description |
|--------------|------------|---------|--------------------------|
| header | ReactNode| — | Optional header slot |
| footer | ReactNode| — | Optional footer slot |
| padding | "none" | "sm" | "md" | "md" | Inner padding |
| isHoverable| boolean | false | Hover shadow transition |
Accordion
| Prop | Type | Default | Description |
|----------------|----------|---------|-----------------------------|
| items | { id, title, content }[] | — | Items |
| allowMultiple| boolean| false | Allow multiple panels open |
Uses manual height animation (no external libs).
Modal
| Prop | Type | Default | Description |
|----------|------------|---------|----------------------------|
| open | boolean | — | Visibility |
| onClose| () => void | — | Close handler |
| title | string | — | Optional title (and close) |
| size | "sm" | "md" | "lg" | "md" | Max width |
Implements focus trap and scroll lock when open.
Tooltip
| Prop | Type | Default | Description |
|-------------|----------|---------|--------------------|
| content | ReactNode | — | Tooltip body |
| placement | "top" | "bottom" | "left" | "right" | "top" | Position |
Dropdown
Two usage patterns: (1) Default trigger — omit trigger; the component shows a button with the selected label or placeholder. (2) Custom trigger — pass trigger with your own element (e.g. a Button or icon); the same list opens on activation.
| Prop | Type | Default | Description |
|----------------|-------------------------|---------|--------------------------|
| trigger | ReactNode | — | Custom trigger; omit for default (placeholder/selected label) |
| placeholder | string | "Select…" | Shown when no value selected (default trigger only) |
| items | { value, label, disabled? }[] | — | Options |
| value / defaultValue | string | — | Controlled / initial |
| onValueChange| (value: string) => void | — | Selection callback |
| disabled | boolean | false | When true, does not open; trigger is non-interactive |
Keyboard: Enter/Space to open, Arrows to move, Enter to select, Escape to close.
Utilities & hooks
import { cn, mergeRefs, useFocusTrap, useClickOutside, useKeyboardNavigation, getNextListIndex } from "@raxrai/stylelab-ui";- cn(...) – clsx + tailwind-merge for class names.
- mergeRefs(...refs) – Combines multiple refs (e.g. forwarded ref + internal ref). Use when a component needs to forward a ref and also attach its own ref.
- useFocusTrap(active, options?) – Traps focus in a container ref (e.g. Modal).
- useClickOutside(ref(s), handler, options?) – Fires when click is outside ref(s).
- useKeyboardNavigation({ onEscape, onArrowLeft, onArrowRight, ... }) – Document-level key handlers.
- getNextListIndex(current, direction, length) – Index for arrow-key list/tab navigation.
Changelog
[0.4.1]
- Navbar — Mobile menu: click-outside ref now wraps both the bar and the dropdown panel so taps on nav links or buttons (e.g. Log out) run the action instead of only closing the menu. Mobile panel uses an explicit opaque theme-aware background in all themes (readable with glass/clay). Optional
mobileMenuExtraprop renders content at the bottom of the hamburger overlay (e.g. a Log out button); clicking it closes the menu.
[0.4.0]
- Overrides + refs — Component roots consistently support
style, consumerclassNameoverrides (consumer class last), and ref forwarding across the library. - Theme fixes — Card no longer forces text color; Button
ghostusestext-inheritso it can inherit parent text color. - Accessibility — ProgressBar now supports ARIA progress attributes; Toast supports Escape-to-dismiss; Tooltip uses
aria-describedbywhen visible. - Exports —
mergeRefsand common component prop types are re-exported from the package entry.
[0.3.2]
- ThemeProvider — Optional
persistThemeprop (defaulttrue). WhenpersistTheme={false}, the provider does not read from or write to localStorage: theme stays atdefaultThemeunless changed in memory. Use for fixed-theme pages (e.g. landing, docs) or nested providers where only the inner tree should persist. OptionalstorageKey(default"stylelab-theme") still applies whenpersistThemeis true.
[0.3.1]
- Dropdown —
disabledprop: when true, the dropdown does not open and the trigger is non-interactive (opacity, cursor, no popover). Use for empty or loading state.
[0.2.0]
- Navbar — Optional responsive API: pass
logo,items({ href, label }[]), andright(e.g. theme switcher). On small screens nav links become a hamburger menu that opens as an overlay (no layout shift), with the theme’s navbar background; glass and clay use an opaque panel so content doesn’t show through. Desktop shows full nav row. Menu closes on link click or outside click. You can still passchildrenfor a custom layout. Exported types:NavbarItem,NavbarProps. - ThemeProvider — Restores theme from
localStorageon mount;setThemepersists the new theme. OptionalstorageKeyprop (default"stylelab-theme"). - Dropdown — Popover is portaled to
document.bodyand positioned with open-up/down logic. Optionaltriggerandplaceholder(default trigger shows selected/placeholder label).classNamesfor trigger, popover, and item. Theme-aware hover/focus styles. Exported types:DropdownItem,DropdownProps,DropdownClassNames. - Card —
classNamesfor root, header, body, footer. Cyberpunk no longer uses the clip-path “glitch cut” (avoids weird look on different backgrounds); neon border and glow remain. Exported types:CardProps,CardClassNames. - Badge —
bgOverrideandtextOverride(e.g. hex) when you need specific colors. - ProgressBar —
trackColorandactiveColoroverrides (e.g. hex). - DashboardShell — Header, nav links, and mobile panel use theme-based styling (no
dark:; works with StyleLab themes). - GraphicCard — In night and cyberpunk themes, content text inherits the card’s text color so children with hardcoded dark text still display correctly.
- Docs — Installation: Next.js/existing React apps install the package only; add
react/react-domonly for new projects without React. - Types —
StyleLabTheme,ComponentName,ThemeRecommendationfromlib/types; component prop typesNavbarItem,NavbarProps,CardProps,CardClassNames,DropdownItem,DropdownProps,DropdownClassNamesre-exported from the package.
Links
- Live demo & docs: https://stylelab.rajarai.com
- Full component API (this repo): docs/COMPONENTS.md
