Skip to content
AstroCraft Docs
On this theme

Components Reference

Thirty-seven primitives in src/components/ui/, 84 components in total once compound parts are counted. Each is a folder with an index.ts and an exported tv() recipe. /examples/ui renders every one in every variant; the contract is in Components.

Used by real pages (13): accordion, badge, breadcrumb, button, card, input, nav, pagination, password, reveal, select, sheet, skeleton — plus dialog, reached through sheet. The rest ship for you to reach for.

Basics

Primitive Parts JS
button Button —
input Input —
label Label —
textarea Textarea —
badge Badge —
card Card, CardImage, CardHeader, CardTitle, CardDescription, CardAction, CardContent, CardFooter —
alert Alert —
separator Separator —
skeleton Skeleton —
avatar Avatar —

card is the compound worth knowing: four of Indexa’s seven card compositions build on it. skeleton uses Tailwind’s built-in animate-pulse rather than a catalog entry.

Disclosure and navigation

Primitive Parts JS
accordion Accordion, AccordionItem, AccordionTrigger, AccordionContent — (<details>)
tabs Tabs, TabsList, TabsTrigger, TabsContent own script
tooltip Tooltip — (CSS only)
breadcrumb Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator —
pagination Pagination, PaginationItem, PaginationLink, PaginationEllipsis —
nav Nav, NavItem, NavLink —
mega-menu MegaMenu, MegaMenuTrigger, MegaMenuPanel, MegaMenuItem shared _popover.ts
list List, ListItem —
progress Progress —
spinner Spinner —

PaginationLink reuses button’s recipe rather than defining a second one. MegaMenu is click-to-open only — hover triggers are hostile to touch and keyboard, and the file says so in a ponytail: note. Tabs degrades to all-panels-visible without JavaScript.

Overlays

Primitive Parts JS
dialog Dialog, DialogTrigger, DialogClose, DialogHeader, DialogTitle, DialogDescription, DialogFooter shared _dialog.ts
sheet Sheet (+ Dialog’s trigger/close/content parts) shared _dialog.ts
dropdown Dropdown, DropdownTrigger, DropdownMenu, DropdownItem shared _popover.ts

All three are native: dialog and sheet are modal <dialog> (a Sheet is a Dialog pinned to an edge by a side variant), dropdown is the Popover API, so its menu renders in the top layer and cannot be clipped. Escape, light-dismiss and focus return are the platform’s. The entry and exit transitions, the backdrop scrim and the modal scroll-lock live in _overlay.css as real @starting-style transitions that honour prefers-reduced-motion.

Form controls

Primitive Parts JS
select Select — (native <select>)
checkbox Checkbox —
radio Radio —
switch Switch —
slider Slider — (native range)
input-number InputNumber own script
toggle-count ToggleCount, ToggleCountValue — (built on Switch)
password PasswordInput, PasswordStrength own scripts
combobox ComboBox, ComboBoxOption own script
advanced-select AdvancedSelect own script — requires JS
searchbox Searchbox, SearchboxItem own script

checkbox, radio and switch are native inputs styled appearance-none with peer and :checked. PasswordStrength is a four-segment meter driven by the pure scorePassword, which has its own runnable check. AdvancedSelect is backed by a visually-hidden native <select> so it still submits, but it is the one primitive that does not work without JavaScript — the zero-JS alternative is select. Searchbox is a ⌘K palette reusing the Dialog shell.

Data and motion

Primitive Parts JS
table Table, TableHeader, TableBody, TableFooter, TableRow, TableHead, TableCell, TableCaption —
marquee Marquee — (CSS keyframes)
reveal Reveal — (native scroll timeline)

table is styling only — sorting and data-grid behaviour are out of scope. marquee’s seamless loop works by shifting one full copy width plus one gap, which is why --marquee-gap has to match the flex gap; its keyframes live in tailwind-theme.css beside that variable. reveal is the one primitive about motion: an entrance animation on animation-timeline: view(), zero JavaScript, following useAnimations with motion-reduce:animate-none for the case the global guard cannot reach. Motion explains that pair.

The shared internals

Not primitives, and not importable as components — the modules with a leading underscore that the primitives share:

_dialog.ts is the one delegated controller for every dialog and sheet. _popover.ts places and manages every Popover-API menu, driving both Dropdown and MegaMenu. _field.ts is the shared field recipe behind the text inputs, select and the advanced controls. _listbox.ts holds filterByText, nextIndex and createActiveDescendant for the three filterable controls. _client.ts is onReady — the load plus astro:after-swap re-init contract every scripted primitive follows. _overlay.css is the overlay animation and scroll-lock layer. _Chevron.astro is the single disclosure chevron glyph, with rotation left to the call sites.

If you are adding a scripted primitive, use onReady rather than a bare DOMContentLoaded listener — under view transitions the second one only works until the first in-site navigation.

NEXT STEPCommands