React component library — 309 components built on Radix UI primitives, Tailwind CSS, and CVA.
See CHANGELOG.md for release history.
pnpm add @vllnt/ui
Required:
pnpm add react react-dom tailwindcss
Optional (only if using ThemeProvider, NavbarSaas, or other Next.js-specific components):
pnpm add next next-themes
The library provides a Tailwind preset that includes all required theme colors, animations, and utilities.
// tailwind.config.ts
import uiPreset from "@vllnt/ui/tailwind-preset";
export default {
presets: [uiPreset],
content: [
"./src/**/*.{ts,tsx}",
// The preset auto-includes @vllnt/ui content paths
],
};
The preset configures:
- Colors:
primary, secondary, muted, accent, destructive, background, foreground, card, popover, border, input, ring — all as oklch(var(--name) / <alpha-value>) for theming
- Border radius:
lg, md, sm via --radius CSS variable
- Animations:
accordion-down, accordion-up, shimmer
- Font:
mono family via --font-mono variable
- Dark mode: class-based (
darkMode: ["class"])
- Plugin:
tailwindcss-animate
// app/layout.tsx or your main entry
import "@vllnt/ui/styles.css";
This imports Tailwind base/components/utilities + default theme variables + safe-area utilities.
import { Button, Card, Badge } from "@vllnt/ui";
export function Example() {
return (
<Card>
<Badge variant="secondary">New</Badge>
<Button variant="default">Click me</Button>
</Card>
);
}
| Import Path |
What |
@vllnt/ui |
All components, types, and utilities |
@vllnt/ui/tailwind-preset |
Tailwind CSS preset config |
@vllnt/ui/styles.css |
Full styles (Tailwind base + theme variables + utilities) |
@vllnt/ui/themes/default.css |
Theme CSS variables only (no Tailwind base) |
@vllnt/ui/themes/presets.css |
Built-in color presets (applied via data-theme) |
All colors are OKLCH channel CSS variables (L C H), consumed as
oklch(var(--name) / <alpha-value>). Override them after importing styles:
/* Light theme */
:root {
--background: 1 0 0;
--foreground: 0.1445 0 0;
--primary: 0.2044 0 0;
--primary-foreground: 0.9848 0 0;
--secondary: 0.9703 0 0;
--secondary-foreground: 0.2044 0 0;
--muted: 0.9703 0 0;
--muted-foreground: 0.5555 0 0;
--accent: 0.9703 0 0;
--accent-foreground: 0.2044 0 0;
--destructive: 0.6368 0.2078 25.326;
--destructive-foreground: 0.9848 0 0;
--border: 0.9219 0 0;
--input: 0.9219 0 0;
--ring: 0.1445 0 0;
--radius: 0.5rem;
--card: 1 0 0;
--card-foreground: 0.1445 0 0;
--popover: 1 0 0;
--popover-foreground: 0.1445 0 0;
}
/* Dark theme (applied via class="dark" on html/body) */
.dark {
--background: 0 0 0;
--foreground: 0.9848 0 0;
/* ... override other variables */
}
Use @vllnt/ui/themes/default.css instead of @vllnt/ui/styles.css if you only
want the variables without the Tailwind base layer.
Import @vllnt/ui/themes/presets.css and switch between built-in color presets
at runtime with <ThemeSwitcher /> (or setThemePreset / useThemePreset),
which set data-theme on the document root. Render <ThemePresetProvider />
once near the root to restore the saved preset before paint.
To design and export your own theme, use the visual editor at
/themes — it exports a CSS block, a
npx shadcn add command, or design tokens.
All components follow these conventions:
React.forwardRef — every component forwards refs
React.ComponentPropsWithoutRef — extends native HTML element props
cn() utility — merges Tailwind classes via clsx + tailwind-merge
- CVA variants — variant props defined with
class-variance-authority
- Radix primitives — accessible behavior (focus, keyboard, ARIA) via Radix UI
- Slot support —
asChild prop via @radix-ui/react-slot for render delegation
import { Button } from "@vllnt/ui";
// Button variants: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link"
// Button sizes: "default" | "sm" | "lg" | "icon"
<Button variant="outline" size="sm">Small Outline</Button>
import {
Dialog,
DialogTrigger,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
} from "@vllnt/ui";
<Dialog>
<DialogTrigger asChild>
<Button>Open</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Title</DialogTitle>
<DialogDescription>Description</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog>
| Component |
Import |
Notes |
Button |
{ Button, buttonVariants } |
Variants: default, destructive, outline, secondary, ghost, link. Sizes: default, sm, lg, icon |
Input |
{ Input } |
Standard text input |
Textarea |
{ Textarea } |
Multi-line text input |
Checkbox |
{ Checkbox } |
Radix checkbox |
RadioGroup |
{ RadioGroup, RadioGroupItem } |
Radix radio group |
Select |
{ Select, SelectTrigger, SelectValue, SelectContent, SelectItem, ... } |
Radix select |
Slider |
{ Slider } |
Radix slider |
Switch |
{ Switch } |
Radix switch |
Toggle |
{ Toggle, toggleVariants } |
Radix toggle |
ToggleGroup |
{ ToggleGroup, ToggleGroupItem } |
Radix toggle group |
InputOTP |
{ InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } |
OTP input via input-otp |
Label |
{ Label } |
Radix label |
Calendar |
{ Calendar } |
Date picker via react-day-picker |
| Component |
Import |
Notes |
Card |
{ Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } |
Content container |
AspectRatio |
{ AspectRatio } |
Radix aspect ratio |
ScrollArea |
{ ScrollArea, ScrollBar } |
Radix scroll area |
Separator |
{ Separator } |
Radix separator |
ResizablePanel |
{ ResizablePanel, ResizablePanelGroup, ResizableHandle } |
Via react-resizable-panels |
Collapsible |
{ Collapsible, CollapsibleTrigger, CollapsibleContent } |
Radix collapsible |
Carousel |
{ Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext } |
Via embla-carousel-react |
Tabs |
{ Tabs, TabsList, TabsTrigger, TabsContent } |
Tabbed content |
Accordion |
{ Accordion, AccordionItem, AccordionTrigger, AccordionContent } |
Collapsible sections |
| Component |
Import |
Notes |
Dialog |
{ Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose } |
Radix modal dialog |
AlertDialog |
{ AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogAction, AlertDialogCancel } |
Confirmation dialog |
Sheet |
{ Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetFooter, SheetClose } |
Slide-out panel |
Drawer |
{ Drawer, DrawerTrigger, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, DrawerFooter, DrawerClose } |
Bottom drawer via vaul |
Popover |
{ Popover, PopoverTrigger, PopoverContent } |
Radix popover |
Tooltip |
{ Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } |
Radix tooltip (wrap app in TooltipProvider) |
HoverCard |
{ HoverCard, HoverCardTrigger, HoverCardContent } |
Radix hover card |
Toast |
{ toast, Toaster } |
Toast notifications via sonner. Add <Toaster /> to layout, trigger with toast() |
Alert |
{ Alert, AlertTitle, AlertDescription, alertVariants } |
Static alert banner |
Badge |
{ Badge, badgeVariants } |
Inline status label. Variants: default, secondary, destructive, outline |
Skeleton |
{ Skeleton } |
Loading placeholder |
Spinner |
{ Spinner, UnicodeSpinner } |
Styled spinner + ASCII-art UnicodeSpinner for terminals / code blocks |
| Component |
Import |
Notes |
Command |
{ Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator } |
Command palette via cmdk |
DropdownMenu |
{ DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, ... } |
Radix dropdown |
ContextMenu |
{ ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ... } |
Radix right-click menu |
Menubar |
{ Menubar, MenubarMenu, MenubarTrigger, MenubarContent, MenubarItem, ... } |
Radix menu bar |
NavigationMenu |
{ NavigationMenu, NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger, NavigationMenuContent, NavigationMenuLink } |
Radix nav menu |
Breadcrumb |
{ Breadcrumb } |
Breadcrumb navigation |
Pagination |
{ Pagination } |
Page navigation |
| Component |
Import |
Notes |
Table |
{ Table, TableHeader, TableBody, TableRow, TableHead, TableCell, TableCaption, TableFooter } |
Data table (use with @tanstack/react-table for sorting/filtering) |
Avatar |
{ Avatar, AvatarImage, AvatarFallback } |
Radix avatar |
AreaChart |
{ AreaChart } |
Chart component |
BarChart |
{ BarChart } |
Chart component |
LineChart |
{ LineChart } |
Chart component |
CodeBlock |
{ CodeBlock } |
Syntax-highlighted code via react-syntax-highlighter |
FlowDiagram |
{ FlowDiagram, FlowControls, FlowFullscreen, FlowErrorBoundary, useFlowDiagram } |
Flow diagram via @xyflow/react. Extras: custom controls, fullscreen wrapper, error boundary, and the useFlowDiagram hook for imperative access. |
TableOfContents |
{ TableOfContents } |
Page table of contents |
| Component |
Import |
Notes |
ThemeProvider |
{ ThemeProvider } |
Requires next-themes. Wrap app root |
ThemeToggle |
{ ThemeToggle } |
Light/dark mode toggle. Requires ThemeProvider |
LangProvider |
{ LangProvider } |
Language context provider |
NavbarSaas |
{ NavbarSaas } |
Full-featured SaaS navbar. Requires next |
Sidebar |
{ Sidebar } |
Collapsible sidebar |
SidebarProvider |
{ SidebarProvider, useSidebar } |
Sidebar state management |
SidebarToggle |
{ SidebarToggle } |
Sidebar expand/collapse button |
SearchBar |
{ SearchBar } |
Search input with filtering |
SearchDialog |
{ SearchDialog } |
Full-screen search dialog |
| Component |
Import |
Notes |
MDXContent |
{ MDXContent } |
MDX renderer |
TutorialMDX |
{ TutorialMDX, mdxComponents } |
Tutorial MDX with custom components |
Callout |
{ Callout } |
Info/warning/error callout box |
ProTip |
{ ProTip, CommonMistake } |
Tip and mistake callouts |
Quiz |
{ Quiz } |
Interactive quiz |
Exercise |
{ Exercise } |
Interactive exercise |
StepByStep |
{ StepByStep, Step } |
Numbered step guide |
CodePlayground |
{ CodePlayground, FileTree } |
Code editor with file tree |
Terminal |
{ Terminal, SimpleTerminal } |
Terminal emulator UI |
VideoEmbed |
{ VideoEmbed } |
Responsive video embed |
Flashcard |
{ Flashcard } |
Flip-card for spaced repetition |
Stepper |
{ Stepper } |
Linear progress stepper |
Tour |
{ Tour } |
Guided product tour |
Annotation |
{ Annotation, Highlight } |
Inline annotation block + inline Highlight span for in-prose emphasis |
LearningObjectives |
{ LearningObjectives, Prerequisites, Summary } |
Objectives list plus companion Prerequisites and Summary blocks |
KeyConcept |
{ KeyConcept, Glossary } |
Concept callout + Glossary term list |
Comparison |
{ Comparison, BeforeAfter } |
Side-by-side compare block + BeforeAfter slider |
CompletionDialog |
{ CompletionDialog } |
End-of-flow celebration dialog |
TruncatedText |
{ TruncatedText } |
Expand-on-overflow text block |
TableOfContentsPanel |
{ TableOfContentsPanel } |
Sidebar TOC panel |
ThinkingBlock |
{ ThinkingBlock } |
Collapsible reasoning block |
| Component |
Import |
Notes |
AIChatInput |
{ AIChatInput } |
Chat composer with submit + attachments |
AIMessageBubble |
{ AIMessageBubble } |
User/assistant message bubble |
AIStreamingText |
{ AIStreamingText } |
Token-stream renderer |
AIToolCallDisplay |
{ AIToolCallDisplay } |
Tool-use invocation render |
AISourceCitation |
{ AISourceCitation } |
Inline citation reference |
ModelSelector |
{ ModelSelector } |
Model picker (provider-agnostic) |
| Component |
Import |
Notes |
CandlestickChart |
{ CandlestickChart } |
OHLC candlestick chart |
MarketTreemap |
{ MarketTreemap } |
Market-cap treemap |
OrderBook |
{ OrderBook } |
Bid/ask depth book |
TickerTape |
{ TickerTape } |
Horizontal ticker marquee |
SparklineGrid |
{ SparklineGrid } |
Grid of inline sparklines |
WalletCard |
{ WalletCard } |
Balance / portfolio card |
Watchlist |
{ Watchlist } |
Tracked-symbol list |
| Component |
Import |
Notes |
StatusBoard |
{ StatusBoard } |
Grid of service statuses |
StatusIndicator |
{ StatusIndicator } |
Inline dot + label |
LiveFeed |
{ LiveFeed } |
Append-only event feed |
WorldClockBar |
{ WorldClockBar } |
Multi-timezone clock bar |
SeverityBadge |
{ SeverityBadge } |
Severity-level badge |
RoleBadge |
{ RoleBadge } |
User-role badge |
ScopeSelector |
{ ScopeSelector } |
Scope / environment picker |
| Component |
Import |
Notes |
SubscriptionCard |
{ SubscriptionCard } |
Plan pricing / feature card |
PlanBadge |
{ PlanBadge } |
Tier indicator |
CreditBadge |
{ CreditBadge } |
Remaining-credit pill |
UsageBreakdown |
{ UsageBreakdown } |
Usage-by-category breakdown |
| Component |
Import |
Notes |
AnimatedText |
{ AnimatedText } |
Text enter-animations |
BorderBeam |
{ BorderBeam } |
Animated gradient border |
Marquee |
{ Marquee } |
Infinite scroll marquee |
NumberTicker |
{ NumberTicker } |
Animated number counter |
Spinner |
{ Spinner, UnicodeSpinner } |
Styled spinner + ASCII-art UnicodeSpinner for terminals / code blocks |
| Component |
Import |
Notes |
DatePicker |
{ DatePicker } |
Composed Calendar + Popover |
FileUpload |
{ FileUpload } |
Drag-drop file input |
NumberInput |
{ NumberInput } |
Numeric input w/ steppers |
PasswordInput |
{ PasswordInput } |
Input w/ show-password toggle |
InlineInput |
{ InlineInput } |
Click-to-edit inline input |
Combobox |
{ Combobox } |
Typeahead select |
Rating |
{ Rating } |
Star rating input |
| Component |
Import |
Notes |
DataTable |
{ DataTable } |
High-level table w/ sort/filter (TanStack) |
DataList |
{ DataList } |
Label/value list |
StatCard |
{ StatCard } |
KPI tile |
MetricGauge |
{ MetricGauge } |
Gauge chart |
ActivityHeatmap |
{ ActivityHeatmap } |
GitHub-style contribution grid |
ActivityLog |
{ ActivityLog } |
Audit-trail feed |
TableOfContents |
{ TableOfContents } |
Inline TOC |
| Component |
Import |
Notes |
CategoryFilter |
{ CategoryFilter } |
Chip-based category filter |
FilterBar |
{ FilterBar } |
Multi-facet filter row |
CookieConsent |
{ CookieConsent } |
Cookie-consent banner |
Slideshow |
{ Slideshow } |
Hero slideshow |
CountdownTimer |
{ CountdownTimer } |
Event countdown |
AvatarGroup |
{ AvatarGroup } |
Stacked avatar group |
FloatingActionButton |
{ FloatingActionButton } |
Anchored FAB |
SocialFAB |
{ SocialFab } |
Social-links FAB |
KeyboardShortcutsHelp |
{ KeyboardShortcutsHelp } |
Cmd-? shortcut dialog |
ShareDialog |
{ ShareDialog } |
Shareable-link dialog |
HorizontalScrollRow |
{ HorizontalScrollRow } |
Scroll-snap row |
ViewSwitcher |
{ ViewSwitcher } |
Grid/list toggle |
import { cn } from "@vllnt/ui";
// Merge Tailwind classes (clsx + tailwind-merge)
<div className={cn("p-4 bg-primary", isActive && "bg-accent", className)} />
| Hook |
Purpose |
useDebounce(value, delayMs) |
Returns the value after delayMs of idle — ideal for search inputs. |
useHorizontalScroll(ref) |
Drives the behavior used by HorizontalScrollRow — wheel → horizontal scroll, scroll-snap helpers. |
useMobile(breakpoint?) |
Boolean for "viewport is below breakpoint" (default 768). SSR-safe. |
useSidebar() |
Reads SidebarProvider state — { open, setOpen, toggle }. Throws outside a provider. |
useFlowDiagram(options) |
Imperative controller for FlowDiagram — fit view, zoom, export to PNG. |
useSocialFab() |
Drives the open/close state of SocialFab. |
import { useDebounce, useMobile } from "@vllnt/ui";
const query = useDebounce(input, 300);
const isMobile = useMobile();
import type {
Content,
ContentMeta,
ContentProgress,
ContentSection,
DifficultyLevel,
UISupportedLanguage,
} from "@vllnt/ui";
- React >= 18.0.0
- Tailwind CSS >= 3.0.0
- Next.js >= 14.0.0 (optional — only for
ThemeProvider, NavbarSaas, LangProvider)
next-themes >= 0.4.0 (optional — only for ThemeProvider, ThemeToggle)
MIT