UI Primitives
All UI primitives live in $lib/components/ui/ and are built on top of bits-ui with styling from tailwind-variants. Each component directory contains a barrel index.ts for clean imports.
Button
Section titled “Button”The most commonly used component. Supports rendering as a <button> or <a> depending on whether href is provided.
Import: $lib/components/ui/button
Variants: default | outline | secondary | ghost | destructive | link | glass | glass-outline
Sizes: default | xs | sm | lg | icon | icon-xs | icon-sm | icon-lg
<script lang="ts"> import { Button } from "$lib/components/ui/button";</script>
<!-- Standard button --><Button variant="default">Save</Button>
<!-- Link styled as a button --><Button href="/settings" variant="outline">Settings</Button>
<!-- Icon button --><Button variant="ghost" size="icon" aria-label="Search"> <SearchIcon /></Button>
<!-- Destructive action --><Button variant="destructive">Delete Account</Button>A single <input> component that handles both standard inputs and file inputs.
Import: $lib/components/ui/input
<script lang="ts"> import { Input } from "$lib/components/ui/input";
let name = $state(""); let files = $state<FileList>();</script>
<!-- Text input --><Input type="text" placeholder="Full name" bind:value={name} />
<!-- File input with bound FileList --><Input type="file" bind:files />Select
Section titled “Select”Accessible dropdown select built on bits-ui. Composed of multiple sub-components.
Import: $lib/components/ui/select
<script lang="ts"> import * as Select from "$lib/components/ui/select";</script>
<Select.Root> <Select.Trigger> <Select.Value placeholder="Choose a role" /> </Select.Trigger> <Select.Content> <Select.Group> <Select.GroupHeading>Roles</Select.GroupHeading> <Select.Item value="admin">Admin</Select.Item> <Select.Item value="editor">Editor</Select.Item> <Select.Item value="viewer">Viewer</Select.Item> </Select.Group> </Select.Content></Select.Root>Dialog
Section titled “Dialog”Modal dialog with overlay, header, footer, and close button.
Import: $lib/components/ui/dialog
<script lang="ts"> import * as Dialog from "$lib/components/ui/dialog"; import { Button } from "$lib/components/ui/button";</script>
<Dialog.Root> <Dialog.Trigger> {#snippet child({ props })} <Button {...props}>Open Dialog</Button> {/snippet} </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm Action</Dialog.Title> <Dialog.Description>This action cannot be undone.</Dialog.Description> </Dialog.Header> <p>Are you sure you want to proceed?</p> <Dialog.Footer> <Dialog.Close>Cancel</Dialog.Close> <Button variant="destructive">Confirm</Button> </Dialog.Footer> </Dialog.Content></Dialog.Root>Container component for grouping related content.
Import: $lib/components/ui/card
<script lang="ts"> import * as Card from "$lib/components/ui/card";</script>
<Card.Root> <Card.Header> <Card.Title>Monthly Revenue</Card.Title> <Card.Description>Revenue for the current billing period.</Card.Description> </Card.Header> <Card.Content> <p class="text-3xl font-bold">$12,450</p> </Card.Content> <Card.Footer> <Card.Action>View Details</Card.Action> </Card.Footer></Card.Root>Inline status indicator with variant support. Renders as <span> by default, or <a> when href is provided.
Import: $lib/components/ui/badge
Variants: default | secondary | destructive | outline
<script lang="ts"> import { Badge } from "$lib/components/ui/badge";</script>
<Badge>Active</Badge><Badge variant="secondary">Draft</Badge><Badge variant="destructive">Expired</Badge><Badge variant="outline">Preview</Badge>Tab navigation for switching between content panels.
Import: $lib/components/ui/tabs
<script lang="ts"> import * as Tabs from "$lib/components/ui/tabs";</script>
<Tabs.Root value="overview"> <Tabs.List> <Tabs.Trigger value="overview">Overview</Tabs.Trigger> <Tabs.Trigger value="analytics">Analytics</Tabs.Trigger> <Tabs.Trigger value="settings">Settings</Tabs.Trigger> </Tabs.List> <Tabs.Content value="overview">Overview content here.</Tabs.Content> <Tabs.Content value="analytics">Analytics content here.</Tabs.Content> <Tabs.Content value="settings">Settings content here.</Tabs.Content></Tabs.Root>Slide-in panel that can appear from any edge of the screen.
Import: $lib/components/ui/sheet
<script lang="ts"> import * as Sheet from "$lib/components/ui/sheet"; import { Button } from "$lib/components/ui/button";</script>
<Sheet.Root> <Sheet.Trigger> {#snippet child({ props })} <Button variant="outline" {...props}>Open Panel</Button> {/snippet} </Sheet.Trigger> <Sheet.Content side="right"> <Sheet.Header> <Sheet.Title>Filters</Sheet.Title> <Sheet.Description>Adjust your search filters.</Sheet.Description> </Sheet.Header> <!-- Filter controls here --> </Sheet.Content></Sheet.Root>Drawer
Section titled “Drawer”Mobile-friendly bottom drawer built on Vaul for touch interactions.
Import: $lib/components/ui/drawer
<script lang="ts"> import * as Drawer from "$lib/components/ui/drawer";</script>
<Drawer.Root> <Drawer.Trigger>Open</Drawer.Trigger> <Drawer.Content> <Drawer.Header> <Drawer.Title>Share Post</Drawer.Title> </Drawer.Header> <!-- Drawer body --> <Drawer.Footer> <Drawer.Close>Done</Drawer.Close> </Drawer.Footer> </Drawer.Content></Drawer.Root>Additional Primitives
Section titled “Additional Primitives”The following components are also available in $lib/components/ui/:
| Component | Path | Description |
|---|---|---|
| Avatar | ui/avatar | User avatar with fallback initials |
| Breadcrumb | ui/breadcrumb | Navigation breadcrumb trail |
| Calendar | ui/calendar | Date picker calendar |
| Checkbox | ui/checkbox | Checkbox input |
| Collapsible | ui/collapsible | Expandable/collapsible section |
| Command | ui/command | Command palette / combobox |
| Dropdown Menu | ui/dropdown-menu | Context and dropdown menus |
| Field | ui/field | Form field wrapper with label and error |
| Input Group | ui/input-group | Grouped input with addons |
| Label | ui/label | Form label |
| Separator | ui/separator | Horizontal or vertical divider |
| Skeleton | ui/skeleton | Loading placeholder |
| Switch | ui/switch | Toggle switch |
| Table | ui/table | Basic HTML table with styling |
| Textarea | ui/textarea | Multi-line text input |
| Toggle | ui/toggle | Pressable toggle button |
| Toggle Group | ui/toggle-group | Group of toggle buttons |
| Tooltip | ui/tooltip | Hover tooltip |
All components follow the same import pattern:
<script lang="ts"> // Single export components import { Checkbox } from "$lib/components/ui/checkbox";
// Multi-part components (use namespace import) import * as DropdownMenu from "$lib/components/ui/dropdown-menu";</script>