Skip to content
AstroCraft Docs
On this theme

Components Reference

The complete inventory of src/components/ui/. Each entry lists what the folder exports, its variant axes with every option, and the defaults. For the contract these all follow, see UI Components.

Import either way:

import Button from "@components/ui/button";
import { Card, CardHeader, CardTitle } from "@components/ui/card";

Each folder also exports its tv() config as <Name>Variants for composition. A handful of components have no config of their own because they reuse another’s — those are noted.

Layout and surface

accordionAccordion, AccordionItem, AccordionTrigger, AccordionContent. No variants. Built on native <details>, so exclusive behaviour and keyboard support are free. The trigger renders a chevron that rotates on open.

cardCard, CardImage, CardHeader, CardTitle, CardDescription, CardAction, CardContent, CardFooter.

  • variant: default, elevated, outline, interactive — default default
  • size: sm, md, lg — default md

size works by setting a --card-p custom property that the padded parts read, so a per-part padding override still wins. CardHeader reflows to two columns automatically when a CardAction is present.

separatorSeparator. orientation: horizontal, vertical — default horizontal.

tableTable, TableHeader, TableBody, TableFooter, TableRow, TableHead, TableCell, TableCaption. No variants. Table wraps itself in a horizontally scrollable container.

listList, ListItem.

  • marker: none, disc, decimal — default none. decimal renders an <ol>.
  • orientation: vertical, horizontal — default vertical. Horizontal is dot-separated inline.

ListItem takes an icon slot; the icon variant is driven by slot presence rather than a prop, so passing icon={false} cannot silently swallow a provided slot.

skeletonSkeleton. No variants. aria-hidden, and stands down under reduced motion.

Actions and feedback

buttonButton.

  • variant: primary, secondary, outline, ghost — default primary
  • size: sm, md, lg — default md
  • icon: true — square, for icon-only buttons

Pass href and it renders an <a> instead. A <button> with no type defaults to "button" rather than submitting.

badgeBadge. variant: primary, secondary, muted, outline, info, success, warning, error — default primary.

alertAlert. variant: info, success, warning, error — default info.

spinnerSpinner. size: sm, md, lg — default md. Takes a label, defaulting to "Loading…", and carries role="status".

progressProgress. size: sm, md, lg — default md. Props value (default 0) and max (default 100). Determinate only.

tooltipTooltip. side: top, bottom, left, right — default top. Requires a text prop. CSS-only, using invisible rather than opacity alone so the text leaves the accessibility tree when hidden.

avatarAvatar. size: sm, md, lg — default md. Props src and alt.

Forms

All the text-entry primitives share a base and three states from _field.ts, so state behaves identically across them.

inputInput. size: sm, md, lg — default md. state: default, error, success — default default.

textareaTextarea. Same two axes, same defaults.

selectSelect. Same two axes, same defaults. A native <select> with a custom chevron.

labelLabel. size: sm, md, lg — default md.

checkboxCheckbox. No variants. A native input styled with appearance-none and peer.

radioRadio. No variants.

switchSwitch. No variants. A label wrapping a screen-reader-only checkbox with role="switch". Zero JavaScript.

sliderSlider. size: sm, md — default md. A native range input styled through its pseudo-elements. Note that WebKit has no progress pseudo-element, so only Firefox fills the track behind the thumb.

input-numberInputNumber. Reuses the input config, so it takes size and state. Its steppers reuse Button, and mark themselves aria-disabled rather than disabled at the bounds so they stay focusable.

passwordPasswordInput, PasswordStrength, plus the exported scorePassword function and Strength type.

PasswordInput reuses the input config. PasswordStrength takes a required for prop naming the input, and a size of sm or md (default md); it renders a four-segment meter.

comboboxComboBox, ComboBoxOption. ComboBox reuses the input config for size and state, plus name, placeholder (default "Search…") and emptyText (default "No results").

advanced-selectAdvancedSelect. size and state as above. Additional props: options, name, multiple (default false), search (default false), placeholder, searchPlaceholder, countText, emptyText. Backed by a visually hidden real <select>, so it submits in a plain form.

searchboxSearchbox, SearchboxItem. Props: id (required), label, placeholder, emptyText, shortcut (default "⌘K"). Built on the Dialog shell. The keyboard shortcut opens the first searchbox on the page.

navNav, NavItem, NavLink.

  • Navorientation: horizontal, vertical — default horizontal
  • NavLinkvariant: underline, pills, segment, glitch — default underline

glitch is the theme’s signature link treatment, used throughout the header and footer. The active state is the caller’s aria-current="page"; the primitive only styles it.

Nav is the one documented exception to the class-merge rule: your class merges onto the <ul> while data-slot and the rest of your props land on the <nav>, so aria-label reaches the landmark.

breadcrumbBreadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator. No variants. Note that no route in the theme uses these — and if you add one, add the visible navigation before adding BreadcrumbList schema.

paginationPagination, PaginationItem, PaginationLink, PaginationEllipsis. No variants; PaginationLink reuses Button and takes isActive.

dropdownDropdown, DropdownTrigger, DropdownMenu, DropdownItem. DropdownMenu takes a required id and an align of start or end (default start). DropdownTrigger reuses Button (default outline) and takes a for prop naming the menu. Built on the Popover API with arrow-key roving.

mega-menuMegaMenu, MegaMenuTrigger, MegaMenuPanel, MegaMenuItem. MegaMenuPanel takes columns: 1, 2 or 3 (default 3), plus a required id and an align. The trigger reuses NavLink.

dialogDialog, DialogTrigger, DialogClose, DialogHeader, DialogTitle, DialogDescription, DialogFooter. No variants. A native modal <dialog>, so the focus trap, page inertness and Escape handling come free. DialogTrigger takes a required for.

sheetSheet, plus re-exported SheetTrigger and SheetClose. side: right, left, top, bottom — default right. Content parts are Dialog’s.

tabsTabs, TabsList, TabsTrigger, TabsContent. No variants. TabsTrigger and TabsContent each take a required value. The one tab primitive that ships script: roving Arrow, Home and End keys, degrading to all panels visible without JavaScript.

theme-toggleThemeToggle. Reuses Button, defaulting to ghost at sm. The sun and moon flip is pure CSS; the click handler toggles the class and persists the choice. Pairs with the pre-paint script in BaseHead.

Motion and display

revealReveal. The scroll-entrance wrapper.

  • trigger: scroll, view, load — default scroll
  • animation: fade-in, fade-in-up, fade-in-down, fade-in-from-right, fade-in-from-left, fade-in-left, fade-in-right, zoom-in, blurred-fade-in, slide-up-fade, bounce-fade-in, flip-in-x, flip-in-y, rotate-360 — default fade-in-up
  • range: entry, cover, contain, gradual, moderate, brisk, rapid — default entry
  • delay: 0, 50, 100, 150, 200, 250, 300, 350, 400, 500, 600, 700, 800, 900, 1000 — default 0
  • Plus as (default div) and animate

text-revealTextReveal. No visual variants; behaviour rides on props. as, effect (scramble or words, default words), trigger (scroll or load, default scroll), delay, animate. Plain text only — the split reads textContent and rebuilds the element.

magneticMagnetic. radius: sm, md, lg — default md. Plus strength (default 0.4) and animate.

marqueeMarquee.

  • direction: left, right, up, down — default left
  • speed: slow (60s), normal (30s), fast (15s) — default normal
  • Plus pauseOnHover (default true) and repeat (default 4, clamped to at least 2)

circular-textCircularText. No variants. Props: label (required — it is both the ring text and the accessible name), href (renders a link when present), repeat (default 4).

Your class can set colour, weight and text transform. font-size and letter-spacing utilities look like they work and do nothing — the geometry is in viewBox units and the spacing is computed to close the ring.

ellipse-linkEllipseLink. size: sm, lg — default sm. Props: href (omit it and you get a <button>, in which case pass type="submit" explicitly), label (required, plain text), magnetic (default true).

Deliberately not built on Button. It wraps itself in Magnetic.

distort-imageDistortImage. No variants. A WebGL ripple frame around a slotted image.

  • grid — target cell size in pixels, default 44. Smaller is finer.
  • mouse — the radius the pointer disturbs, as a fraction of grid width, default 0.13
  • strength — multiplier on pointer velocity, default 1
  • relaxation — per-frame decay, 0 to 1, default 0.9. Higher lingers.
  • animate

You supply the image. The canvas only becomes visible once WebGL initialises, so an unsupported browser sees the untouched picture. Budget: one WebGL context per instance, and browsers drop the oldest past roughly sixteen. The home page mounts fifteen.

page-transitionPageTransition. No variants; takes animate. Mounted once in BaseLayout. Renders nothing unless both useAnimations and useViewTransitions are on.

toggle-countToggleCount, ToggleCountValue. ToggleCount takes a required id plus offLabel (default "Monthly") and onLabel (default "Annual"). ToggleCountValue takes for, min and max, all required, and swaps its text on toggle. Built on Switch.

Components with no config of their own

These reuse another primitive’s tv() config, which is why they have no variant axes to list: DialogTrigger, DialogClose, DropdownTrigger, MegaMenuTrigger, PaginationLink, PasswordInput, InputNumber, ThemeToggle.

Seeing them all

pnpm dev, then /examples/ui. Every primitive in every variant, with a theme toggle in the header, plus the icon registry and the motion catalog. It is development-only and ships no pages in production.

NEXT STEPCommands & Testing