Skip to content

Weft / Components · Reference

Component catalogue

133 accessible, Tailwind-styled component families. Every example is live — click it, type in it, tab through it.

133 components

Layout

Box

A plain element with no classes of its own: a div, or another tag with as.

Box(as: "aside", class: "rounded-2xl bg-slate-100 p-6 text-center text-sm") "Only the classes you give it."
Props and events

Box

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Container

A centred column with responsive side padding.

A centred, padded column.
Container(size: "md", class: "rounded-2xl bg-slate-100 py-6 text-center text-sm") "A centred, padded column."
Props and events

Container

PropTypeDefaultDescription
sizesm | md | lg | xl | 2xl | fullxlMaximum width. Takes a value per breakpoint.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Section

A page section with vertical rhythm. With a label it's a named region.

Features

Section(label: "Features", class: "rounded-2xl bg-slate-100 px-6 text-center") { h2(class: "text-2xl font-bold") "Features" }
Props and events

Section

PropTypeDefaultDescription
labeltext—Accessible name (makes it a region).

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Stack

A flex row or column with a gap. Each prop takes a value per breakpoint: direction: "vertical md:horizontal".

Stack(direction: "vertical md:horizontal", gap: "2 md:4") {
    Button "One"
    Button(variant: "outline") "Two"
}
Props and events

Stack

PropTypeDefaultDescription
directionvertical | horizontalverticalMain axis.
gapnumber4Tailwind spacing step between children.
alignstart | center | end | stretch | baseline—Cross-axis alignment (centre for rows).
justifystart | center | end | between | around | evenly—Main-axis distribution.
wrapboolfalseLet children wrap.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Hero

A page-top hero: an optional shader background and overlay, then an eyebrow, title, description and actions.

8 parts

✦ New

Design at the speed of thought

Accessible, production-ready interfaces, rendered live.

Hero(class: "rounded-2xl text-white") {
    HeroBackground(preset: "aurora", colors: "#05010f #8b5cf6 #22d3ee #f472b6")
    HeroOverlay
    HeroContent(class: "py-16 sm:py-20") {
        HeroEyebrow "✦ New"
        HeroTitle(class: "text-4xl sm:text-5xl") "Design at the speed of thought"
        HeroDescription "Accessible, production-ready interfaces, rendered live."
        HeroActions {
            Button(variant: "gradient") "Start free"
            Button(variant: "glass") "Watch the demo"
        }
    }
}
Parts and props

Hero

The section (relative, isolated, clipped).

HeroBackground

An animated shader filling the hero.

PropTypeDefaultDescription
presetmesh-gradient | aurora | plasma | galaxy | waves | synthwave | liquid | topography | rays | grid-glow | silkmesh-gradientWhich shader.
colorscolors—Space-separated colours.
speednumber0.6Animation speed.
intensitynumber1Effect strength.

HeroOverlay

A gradient over the background for legible text.

HeroContent

The centred content column.

HeroEyebrow

A small pill above the title.

HeroTitle

The page's h1.

HeroDescription

Supporting paragraph.

HeroActions

A row of buttons.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

App structure

AppShell

An app layout: a sidebar column that's a sticky rail on large screens and a slide-over panel on small ones, beside the content column.

6 parts

Dashboard

Your content goes here.

div(class: "h-[26rem] overflow-hidden rounded-2xl ring-1 ring-gray-900/10") {
    AppShell(class: "h-full min-h-0 bg-gray-50") {
        AppSidebar(class: "lg:h-full") {
            Sidebar(label: "Workspace", value: "dashboard") {
                SidebarHeader { NavbarLogo "◆" "Acme" }
                SidebarContent {
                    SidebarMenu {
                        SidebarItem(value: "dashboard") { SidebarIcon "◉" "Dashboard" }
                        SidebarItem(value: "inbox") { SidebarIcon "✉" "Inbox" SidebarBadge "12" }
                    }
                }
            }
        }
        AppContent {
            AppHeader {
                AppSidebarToggle
                p(class: "text-lg font-bold tracking-tight") "Dashboard"
            }
            AppMain(as: "div") { p(class: "text-sm opacity-70") "Your content goes here." }
        }
    }
}
Parts and props

AppShell

The grid: sidebar column and content column.

AppSidebar

The sidebar column (Escape or the backdrop closes it on small screens).

PropTypeDefaultDescription
labeltextSidebarThe landmark's name.

AppContent

The content column.

AppHeader

The sticky top bar.

AppSidebarToggle

Opens the sidebar on small screens (☰ unless you give it content).

PropTypeDefaultDescription
labeltextOpen navigationAccessible name.

AppMain

The main landmark.

PropTypeDefaultDescription
idtextmainTarget for the skip link.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Toolbar

A row (or column) of related controls with the toolbar role.

Toolbar(label: "Text formatting") {
    Button(variant: "ghost", size: "icon-sm", label: "Bold") "B"
    Button(variant: "ghost", size: "icon-sm", label: "Italic") "I"
    Button(variant: "ghost", size: "icon-sm", label: "Underline") "U"
}
Props and events

Toolbar

PropTypeDefaultDescription
labeltextToolbarAccessible name.
orientationhorizontal | verticalhorizontalDirection.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

BottomNav

A tab bar pinned to the bottom of small screens.

2 parts
div(class: "relative h-32 overflow-hidden rounded-2xl bg-slate-100 ring-1 ring-slate-200") {
    BottomNav(class: "absolute") {
        BottomNavItem(href: "#demo", current: true) { span(aria-hidden: "true", class: "text-lg") "⌂" "Home" }
        BottomNavItem(href: "#demo") { span(aria-hidden: "true", class: "text-lg") "⌕" "Search" }
        BottomNavItem(href: "#demo") { span(aria-hidden: "true", class: "text-lg") "♡" "Saved" }
    }
}
Parts and props

BottomNav

The bar (fixed to the bottom).

PropTypeDefaultDescription
labeltextPrimaryThe landmark's name.

BottomNavItem

A destination: an icon and a short label.

PropTypeDefaultDescription
hreftext#Destination.
currentboolfalseMarks the current page.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Actions

Button

A button, or a link styled as one when it has an href. Icon buttons use an icon size and a label.

A link
div(class: "flex flex-wrap items-center gap-3") {
    Button "Primary"
    Button(variant: "outline") "Outline"
    Button(variant: "ghost") "Ghost"
    Button(variant: "gradient") "Gradient"
    Button(variant: "outline", size: "icon", label: "Add") "+"
    Button(variant: "link", href: "#demo") "A link"
}
Props and events

Button

PropTypeDefaultDescription
variantprimary | secondary | outline | ghost | gradient | danger | light | glass | linkprimaryLook.
sizesm | md | lg | icon | icon-sm | icon-lgmdSize. Takes a value per breakpoint.
hreftext—Renders a link.
labeltext—Accessible name (for icon buttons).
typebutton | submit | resetbuttonsubmit for a form's submit button: the default, button, doesn't submit the form.
disabledboolfalseDisables it.
fullboolfalseFull width.
  • @press — Pressed (@click works too).

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

ThemeToggle

Switches the page between light and dark; the choice is remembered and applied before the first paint. Sections marked theme-locked keep their colours.

ThemeToggle
Props and events

ThemeToggle

Its content replaces the ☾ / ☀ icons.

PropTypeDefaultDescription
labeltextSwitch themeAccessible name.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

CopyButton

Copies text — or another element's text, by selector — and confirms with “Copied”.

cargo add weft
div(class: "flex items-center gap-3") {
    code(class: "rounded-lg bg-slate-100 px-3 py-1.5 font-mono text-sm text-slate-800") "cargo add weft"
    CopyButton(text: "cargo add weft")
}
Props and events

CopyButton

Its content replaces the label.

PropTypeDefaultDescription
texttext—The text to copy.
targettext—A CSS selector whose text is copied instead.
labeltextCopyButton text and accessible name.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

FileDownload

A file to download, such as a PDF form: one link showing the file's kind, its title, a description and size, and a download icon. Name the saved file with filename; files must be on the same site for that.

div(class: "grid max-w-xl gap-3") {
    FileDownload(href: "files/sample.pdf", filename: "Intake form.pdf", description: "Please fill it in before your first session.", size: "1 KB") "Client intake form"
    FileDownload(href: "files/sample.csv", filename: "Session log.csv", size: "1 KB") "Session log"
}
Props and events

FileDownload

Its content is the file's title.

PropTypeDefaultDescription
hreftext—Where the file is: /forms/intake.pdf.
filenametext—The name it's saved as, such as Intake form.pdf. Without one, the name in href is used.
descriptiontext—A line about what it's for.
sizetext—Its size, shown after its kind: 120 KB.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Data display

Badge

A small label.

DefaultBrandLiveBeta
div(class: "flex flex-wrap gap-2") {
    Badge "Default"
    Badge(tone: "brand") "Brand"
    Badge(tone: "success") "Live"
    Badge(tone: "warning") "Beta"
}
Props and events

Badge

PropTypeDefaultDescription
tonegray | brand | accent | success | warning | danger | infograyColour.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Card

A surface for related content: a header with a title and description, content, and a footer.

6 parts

Shaders without fear

Animated backgrounds in one line of template.

Pick a preset and your colours; Weft handles the GPU.

Card(class: "max-w-sm") {
    CardHeader {
        CardTitle "Shaders without fear"
        CardDescription "Animated backgrounds in one line of template."
    }
    CardContent { p(class: "text-sm/6") "Pick a preset and your colours; Weft handles the GPU." }
    CardFooter {
        Button(size: "sm") "Read the guide"
        Button(size: "sm", variant: "ghost") "Later"
    }
}
Parts and props

Card

The surface.

CardHeader

Title and description.

CardTitle

An h3 (use as for another level).

CardDescription

Muted supporting text.

CardContent

The body.

CardFooter

Actions along the bottom.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Avatar

A round picture with initials underneath as the fallback; group several to overlap them.

4 parts
Ada LovelaceALGH
ATKJMH
div(class: "flex items-center gap-6") {
    Avatar { AvatarImage(src: photo_ocean, alt: "Ada Lovelace") AvatarFallback "AL" }
    Avatar(size: "lg") { AvatarFallback(name: "Grace Hopper") }
    AvatarGroup {
        Avatar(size: "sm") { AvatarFallback(name: "Alan Turing") }
        Avatar(size: "sm") { AvatarFallback(name: "Katherine Johnson") }
        Avatar(size: "sm") { AvatarFallback(name: "Margaret Hamilton") }
    }
}
Parts and props

Avatar

The round frame.

PropTypeDefaultDescription
sizesm | md | lg | xlmdSize. Takes a value per breakpoint.

AvatarImage

The picture, over the fallback.

PropTypeDefaultDescription
srctext—Image URL.
alttext—Who it shows.

AvatarFallback

Initials of name (or its content).

PropTypeDefaultDescription
nametext—Whose initials; also names it for screen readers.

AvatarGroup

Overlapping avatars.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Stat

A key figure with a label and a change. Style the frame with classes.

4 parts

Revenue

$48,210

12.5% (increase)

vs last month

Churn

2.1%

0.4% (decrease)

div(class: "grid gap-4 sm:grid-cols-2") {
    Stat(class: "rounded-3xl bg-white p-6 shadow-xl shadow-gray-900/5 ring-1 ring-gray-900/5") {
        StatLabel "Revenue"
        StatValue "$48,210"
        StatDelta(value: 12.5) span(class: "font-normal opacity-70") "vs last month"
    }
    Stat(class: "rounded-3xl bg-white p-6 shadow-xl shadow-gray-900/5 ring-1 ring-gray-900/5") {
        StatLabel "Churn"
        StatValue "2.1%"
        StatDelta(value: -0.4, polarity: "down")
    }
}
Parts and props

Stat

A column.

StatLabel

What it measures.

StatValue

The figure.

StatDelta

The change, with an arrow; green when good. Its content follows the number.

PropTypeDefaultDescription
valuenumber0The change.
polarityup | downupWhether up or down is good.
suffixtext%Unit after the number.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Timeline

Events in order down a line.

5 parts
  1. Reactive core

    Signals, memos and effects.

  2. Native Tailwind

    A JIT engine written in Rust.

Timeline {
    TimelineItem {
        TimelineTime(datetime: "2026-03") "March 2026"
        TimelineTitle "Reactive core"
        TimelineDescription "Signals, memos and effects."
    }
    TimelineItem {
        TimelineTime(datetime: "2026-06") "June 2026"
        TimelineTitle "Native Tailwind"
        TimelineDescription "A JIT engine written in Rust."
    }
}
Parts and props

Timeline

The list.

TimelineItem

An event, with a dot on the line.

TimelineTime

A time element.

PropTypeDefaultDescription
datetimetext—Machine-readable date.

TimelineTitle

An h3.

TimelineDescription

Details.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Steps

Progress through a process.

2 parts
Steps(label: "Checkout progress") {
    Step(status: "complete", number: "1") "Cart"
    Step(status: "current", number: "2") "Shipping"
    Step(status: "upcoming", number: "3") "Payment"
}
Parts and props

Steps

The list (in a named nav).

PropTypeDefaultDescription
labeltextProgressThe landmark's name.

Step

One step.

PropTypeDefaultDescription
statuscomplete | current | upcomingupcomingWhere it is.
numbertext—Shown in the dot.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Table

A table in a scrolling frame. The parts mirror HTML; for sorting and paging use DataTable.

8 parts
Recent orders
OrderCustomerTotal
#1042Ada Lovelace$248.00
#1043Grace Hopper$89.00
Total$337.00
Table {
    TableCaption "Recent orders"
    TableHeader {
        TableRow { TableHead "Order" TableHead "Customer" TableHead(class: "text-right") "Total" }
    }
    TableBody {
        TableRow { TableCell "#1042" TableCell "Ada Lovelace" TableCell(class: "text-right tabular-nums") "$248.00" }
        TableRow { TableCell "#1043" TableCell "Grace Hopper" TableCell(class: "text-right tabular-nums") "$89.00" }
    }
    TableFooter {
        TableRow { TableCell "Total" TableCell TableCell(class: "text-right tabular-nums") "$337.00" }
    }
}
Parts and props

Table

The table (class) in its frame (frame_class).

PropTypeDefaultDescription
frame_classtext—Classes for the scrolling frame.

TableCaption

TableHeader

thead.

TableBody

tbody.

TableFooter

tfoot.

TableRow

tr.

TableHead

th.

PropTypeDefaultDescription
scopecol | rowcolWhat it heads.

TableCell

td.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Progress

A progress bar. The class styles the track; bar_class the fill.

Progress(value: 64, label: "Upload progress", class: "max-w-sm")
Props and events

Progress

PropTypeDefaultDescription
valuenumber0Progress.
maxnumber100Complete at.
labeltextProgressAccessible name.
tonebrand | success | warning | dangerbrandFill colour.
bar_classtext—Classes for the fill.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Spinner

A loading indicator that announces its label.

Loading results
Spinner(label: "Loading results")
Props and events

Spinner

PropTypeDefaultDescription
labeltextLoadingAnnounced status.
sizesm | md | lgmdSize.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Skeleton

A shimmering placeholder block; size and shape it with classes. Put a status message nearby for screen readers.

Loading profile
div(role: "status", class: "flex max-w-sm items-center gap-4") {
    span(class: "sr-only") "Loading profile"
    Skeleton(class: "size-12 rounded-full")
    div(class: "flex-1 space-y-2") {
        Skeleton(class: "w-3/4")
        Skeleton(class: "w-1/2")
    }
}
Props and events

Skeleton

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Kbd

A key or shortcut.

Open search with ⌘ K

p(class: "text-sm") { "Open search with " Kbd "⌘ K" }
Props and events

Kbd

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Divider

A separator line, horizontal or vertical; with labelled its content sits in the middle.

div(class: "max-w-sm space-y-6") {
    Divider
    Divider(labelled: true, aria-label: "or") "or"
}
Props and events

Divider

PropTypeDefaultDescription
orientationhorizontal | verticalhorizontalDirection.
labelledboolfalseShow the content in the middle.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Marquee

Content scrolling sideways forever (paused on hover; still with reduced motion).

OrbitalHalcyonVertexMonolith
Marquee(label: "Customers") {
    span(class: "text-xl font-black opacity-60") "Orbital"
    span(class: "text-xl font-black opacity-60") "Halcyon"
    span(class: "text-xl font-black opacity-60") "Vertex"
    span(class: "text-xl font-black opacity-60") "Monolith"
}
Props and events

Marquee

PropTypeDefaultDescription
labeltext—Names it as a group.
row_classtext—Classes for each copy of the row.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

DescriptionList

Terms and their details.

4 parts
Plan
Pro (annual)
Seats
12 of 20
Renews
1 March 2027
DescriptionList(class: "max-w-md") {
    DescriptionItem { DescriptionTerm "Plan" DescriptionDetails "Pro (annual)" }
    DescriptionItem { DescriptionTerm "Seats" DescriptionDetails "12 of 20" }
    DescriptionItem { DescriptionTerm "Renews" DescriptionDetails "1 March 2027" }
}
Parts and props

DescriptionList

dl.

DescriptionItem

A term and its details.

DescriptionTerm

dt.

DescriptionDetails

dd.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

EmptyState

What to show when there's nothing yet.

5 parts

No projects yet

Create your first project to see it here.

EmptyState {
    EmptyStateIcon "✦"
    EmptyStateTitle "No projects yet"
    EmptyStateDescription "Create your first project to see it here."
    EmptyStateActions { Button(size: "sm") "New project" }
}
Parts and props

EmptyState

The dashed frame.

EmptyStateIcon

A decorative icon.

EmptyStateTitle

An h2.

EmptyStateDescription

EmptyStateActions

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Tag

A label you can remove.

RustWebAssembly
div(class: "flex flex-wrap gap-2") {
    Tag(tone: "brand", removable: true, label: "Rust", @remove: noop) "Rust"
    Tag(label: "WebAssembly") "WebAssembly"
}
Props and events

Tag

PropTypeDefaultDescription
tonegray | brand | success | warning | dangergrayColour.
removableboolfalseShow a ✕.
labeltexttagNames the ✕ (“Remove …”).
valuetext—Sent with remove.
  • @remove — The ✕ was pressed.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Image

A responsive image with a fixed aspect ratio, cropping, lazy loading, a shimmer while it loads, an optional caption and hover zoom. Decorative images are hidden from screen readers.

Wind-carved dunes under a low sun
Image(src: photo_dunes, alt: "Wind-carved dunes under a low sun", ratio: "16/9", caption: "Placeholder art, generated as SVG.", zoom: true, ring: true, class: "max-w-lg")
Props and events

Image

PropTypeDefaultDescription
srctext—Image URL.
alttext—What the image shows.
decorativeboolfalsePurely decorative: empty alt, hidden from assistive technology.
ratio16/9 | 4/3 | 3/2 | 1/1 | 21/9 | 3/4 | auto16/9Aspect ratio of the frame (auto keeps the image's own). Takes a value per breakpoint.
fitcover | contain | fill | nonecoverHow the image fills the frame. Takes a value per breakpoint.
positioncenter | top | bottom | left | rightcenterWhich part stays in view when cropped. Takes a value per breakpoint.
roundednone | sm | md | lg | xl | 2xl | 3xl | full2xlCorner radius. Takes a value per breakpoint.
captiontext—A caption below (figcaption).
lazybooltrueLoad when near the viewport.
decodingsync | async | autosyncsync paints the page and image together, so a large image doesn't flash blank when you return to the tab.
placeholderbooltrueShimmer behind the image while it loads.
zoomboolfalseZoom in slightly on hover.
ringboolfalseA hairline border.
shadowboolfalseA soft drop shadow.
srcsettext—Responsive sources.
sizestext—Responsive sizes.
img_classtext—Extra classes for the img.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

CodeBlock

A dark code panel with a language label and a copy button.

weft
Button(variant: "primary") "Get started"
CodeBlock(code: "Button(variant: \"primary\") \"Get started\"", language: "weft", class: "max-w-lg")
Props and events

CodeBlock

PropTypeDefaultDescription
codetext—The code.
languagetextweftLabel shown in the header.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Rating

A star rating, read out as "4.5 out of 5".

★★★★★
Rating(value: 4.5, label: "Rated 4.5 out of 5")
Props and events

Rating

PropTypeDefaultDescription
valuenumber0Rating.
maxnumber5Number of stars.
labeltextRatingAccessible name.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

GradientText

Text filled with an animated gradient.

Make it glow

h3(class: "text-4xl font-black tracking-tight") { "Make it " GradientText(text: "glow") }
Props and events

GradientText

PropTypeDefaultDescription
texttext—Text when there are no children.
fromtextfrom-brand-500Gradient start class.
viatextvia-fuchsia-500Gradient middle class.
totextto-accent-400Gradient end class.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Calendar

A month grid for picking a date, with every day named in full for screen readers.

October 2026

MoTuWeThFrSaSu
Calendar(value: "2026-10-23", today: "2026-10-20", label: "Delivery date", @select: noop)
Props and events

Calendar

PropTypeDefaultDescription
valuetext—Selected date, YYYY-MM-DD.
monthtext—Month to show first, YYYY-MM (defaults to the value's month or today).
todaytext—Today's date, YYYY-MM-DD (defaults to the system clock).
labeltextCalendarAccessible name of the grid.
  • @select — A day is picked (event.value is YYYY-MM-DD).

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

DataTable

A table with sortable columns, pagination and row selection — for admin screens and reports.

Orders
#1042Ada Lovelace248
#1043Grace Hopper89
#1044Alan Turing1,120

1–3 of 5

DataTable(caption: "Orders", columns: data_columns, rows: data_rows, page-size: 3, selectable: true, @select: noop)
Props and events

DataTable

PropTypeDefaultDescription
searchablebooleanfalseOffer a search box over the shown columns.
exportablebooleanfalseOffer the table as CSV.
stickybooleanfalseKeep the header in view in a scrolling box.
barstext—Number columns to underline with a bar sized by value, comma-separated.
columnslist—Records: key, label, sortable, align (right).
rowslist—Records keyed by column key.
captiontext—Table caption (its accessible name).
page-sizenumber0Rows per page (0 shows all).
selectableboolfalseCheckboxes to select rows.
  • @select — Selection changes (event.value is how many rows are selected).

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

ProgressRing

Circular progress with the percentage in the middle.

72%
45%
90%
div(class: "flex items-center gap-6") {
    ProgressRing(value: 72, label: "Upload", size: "sm")
    ProgressRing(value: 45, label: "Storage")
    ProgressRing(value: 90, label: "Goal", tone: "success", size: "lg")
}
Props and events

ProgressRing

PropTypeDefaultDescription
valuenumber0Current value.
maxnumber100Maximum.
labeltextProgressAccessible name.
sizesm | md | lgmdDiameter.
tonebrand | success | warning | dangerbrandColour.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Feedback

Alert

A callout with an icon, title and description, optionally dismissible.

6 parts

Deployed

Your site is live.
div(class: "max-w-lg space-y-3") {
    Alert(tone: "success") {
        AlertIcon
        AlertContent { AlertTitle "Deployed" AlertDescription "Your site is live." }
    }
    Alert(tone: "danger") {
        AlertIcon
        AlertContent { AlertTitle "Payment failed" AlertDescription "Check your card details." }
        AlertClose(@dismiss: noop)
    }
}
Parts and props

Alert

PropTypeDefaultDescription
toneinfo | success | warning | dangerinfoColour and urgency (warning and danger are announced at once).

AlertIcon

The tone's symbol (or its content).

PropTypeDefaultDescription
toneinfo | success | warning | danger—Overrides the Alert's.

AlertContent

Holds the title and description.

AlertTitle

AlertDescription

AlertClose

A ✕.

PropTypeDefaultDescription
labeltextDismissAccessible name.
  • @dismiss — The ✕ was pressed.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Tooltip

A short hint on hover or focus.

3 parts

Shader qualityLower it on slow devices.

p(class: "flex items-center gap-2 text-sm") {
    "Shader quality"
    Tooltip {
        TooltipTrigger(label: "About shader quality") "?"
        TooltipContent "Lower it on slow devices."
    }
}
Parts and props

Tooltip

TooltipTrigger

The control it describes.

PropTypeDefaultDescription
labeltext—Accessible name for icon-only content.

TooltipContent

The hint.

PropTypeDefaultDescription
sidetop | bottomtopWhere it appears.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Toaster

Stacked toast notifications in a polite live region. toasts is a list you keep in state; each toast is a record, { message: "Saved", tone: "success" }, or plain text. Add one with toasts <- toasts + [{ … }] (in brackets: + only adds a list to a list), and remove it on close with remove_at(toasts, event.index).

state sent = []
on send = sent <- sent + [{ message: "Thanks, we'll be in touch.", tone: "success" }]
on dismiss = sent <- remove_at(sent, event.index)
form(class: "flex items-end gap-3", @submit: send) {
    Field {
        Label "Email"
        Input(type: "email", required)
    }
    Button(type: "submit") "Subscribe"
}
Toaster(toasts: sent, @close: dismiss)
Props and events

Toaster

PropTypeDefaultDescription
toastslist—The toasts: each a record, { message: "Saved", tone: "success" } (tones: success, danger, warning, info), or plain text. Shapes it can't show are reported in the console.
positionbottom-right | top-right | bottom-left | top-centerbottom-rightWhere toasts appear.
  • @close — A toast's close button is pressed (event.index).

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Overlays

Dialog

A modal window. Opens from its trigger (or open); Escape, the backdrop and the ✕ close it. Focus stays inside and returns afterwards.

8 parts
Dialog {
    DialogTrigger "Edit profile"
    DialogContent {
        DialogHeader {
            DialogTitle "Edit profile"
            DialogDescription "Changes are saved when you click Save."
        }
        Field(class: "mt-6") { Label "Name" Input(value: "Ada Lovelace") }
        DialogFooter {
            DialogClose "Cancel"
            DialogClose(variant: "primary") "Save"
        }
    }
}
Parts and props

Dialog

Holds the state (no element).

PropTypeDefaultDescription
openbool—Controls it.
  • @close — It closed.

DialogTrigger

A button that opens it (styled like Button).

PropTypeDefaultDescription
varianttextprimaryButton variant.
sizetextmdButton size.

DialogContent

The panel over a backdrop.

PropTypeDefaultDescription
sizesm | md | lg | xlmdWidth.
close_buttonbooltrueShow the ✕.

DialogHeader

DialogTitle

Names the dialog.

DialogDescription

Describes it.

DialogFooter

Actions.

DialogClose

A button that closes it.

PropTypeDefaultDescription
varianttextoutlineButton variant.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Sheet

A panel that slides in from an edge — for carts, filters and navigation.

8 parts
Sheet {
    SheetTrigger "Open cart"
    SheetContent(side: "right") {
        SheetHeader { SheetTitle "Your cart" SheetDescription "2 items" }
        p(class: "text-sm") "Nebula Lamp — $89"
        SheetFooter { SheetClose(variant: "primary") "Check out" }
    }
}
Parts and props

Sheet

Holds the state.

PropTypeDefaultDescription
openbool—Controls it.
  • @close — It closed.

SheetTrigger

PropTypeDefaultDescription
varianttextoutlineButton variant.
sizetextmdButton size.

SheetContent

The panel.

PropTypeDefaultDescription
sideleft | right | top | bottomrightEdge.
sizesm | md | lg | fullmdWidth (left/right).
close_buttonbooltrueShow the ✕.

SheetHeader

SheetTitle

SheetDescription

SheetFooter

SheetClose

PropTypeDefaultDescription
varianttextoutlineButton variant.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

AlertDialog

A confirmation that must be answered. Cancel is focused first; Escape cancels.

9 parts
AlertDialog {
    AlertDialogTrigger "Delete project"
    AlertDialogContent {
        AlertDialogHeader {
            AlertDialogTitle "Delete this project?"
            AlertDialogDescription "This can't be undone."
        }
        AlertDialogFooter {
            AlertDialogCancel "Cancel"
            AlertDialogAction(variant: "danger", @confirm: noop) "Delete"
        }
    }
}
Parts and props

AlertDialog

Holds the state.

PropTypeDefaultDescription
openbool—Controls it.
  • @close — It closed.

AlertDialogTrigger

PropTypeDefaultDescription
varianttextdangerButton variant.
sizetextmdButton size.

AlertDialogContent

The panel.

AlertDialogHeader

AlertDialogTitle

AlertDialogDescription

AlertDialogFooter

AlertDialogAction

Confirms, then closes.

PropTypeDefaultDescription
variantprimary | dangerprimaryButton variant.
  • @confirm — Confirmed.

AlertDialogCancel

Closes.

PropTypeDefaultDescription
varianttextoutlineButton variant.
  • @cancel — Cancelled.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Popover

Floating content anchored to a button; Escape or a click outside closes it.

3 parts
Popover {
    PopoverTrigger "Filters ⌄"
    PopoverContent(label: "Filters") {
        p(class: "font-semibold") "Filters"
        p(class: "mt-1 opacity-70") "Narrow the results."
    }
}
Parts and props

Popover

PropTypeDefaultDescription
unstyledflagfalseNo styles of its own (yours, in its classes).

PopoverTrigger

PropTypeDefaultDescription
varianttextoutlineButton variant.
sizetextmdButton size.
unstyledflagfalseNo styles of its own (yours, in its classes).

PopoverContent

PropTypeDefaultDescription
alignstart | endstartWhich edge it lines up with.
labeltext—Accessible name.
unstyledflagfalseNo styles of its own (yours, in its classes).

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Command

A searchable list of actions with keyboard navigation (put it in a Dialog for a command palette).

8 parts
Dashboard
Settings⌘ ,
New project
Command(class: "max-w-md") {
    CommandInput(placeholder: "Search commands")
    CommandList {
        CommandEmpty "No results."
        CommandGroup(heading: "Pages") {
            CommandItem(value: "Dashboard", @select: noop) "Dashboard"
            CommandItem(value: "Settings", @select: noop) { "Settings" CommandShortcut "⌘ ," }
        }
        CommandSeparator
        CommandGroup(heading: "Actions") {
            CommandItem(value: "New project", @select: noop) "New project"
        }
    }
}
Parts and props

Command

CommandInput

The search box; ↑ ↓ move, Enter chooses.

PropTypeDefaultDescription
placeholdertextSearch…Placeholder and accessible name.
autofocusboolfalseFocus it when shown.

CommandList

PropTypeDefaultDescription
labeltextCommandsAccessible name.

CommandEmpty

Shown when nothing matches.

CommandGroup

PropTypeDefaultDescription
headingtext—Group heading.

CommandItem

An action, hidden when it doesn't match.

PropTypeDefaultDescription
valuetext—What the search matches (default: its label).
  • @select — Chosen; value is its value.

CommandShortcut

A shortcut at the end of an item.

CommandSeparator

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Forms

Field

A label, a control and its description or error, wired together: the label targets the control, and the description and error are announced with it.

6 parts

We'll never share it.

Tell us a little more.

div(class: "grid max-w-md gap-6") {
    Field {
        Label "Email"
        Input(type: "email", placeholder: "you@studio.dev")
        FieldDescription "We'll never share it."
    }
    Field {
        Label "Message"
        Textarea(rows: 3, value: "Hi!")
        FieldError "Tell us a little more."
    }
}
Parts and props

Field

Groups the parts.

Label

PropTypeDefaultDescription
fortext—The control's id (inside a Field it's automatic).

Input

Any input attribute works; @input, @change and @keydown reach it.

PropTypeDefaultDescription
typetext | email | password | number | search | tel | url | datetextInput type.
valuetext—Value.
placeholdertext—Placeholder.
nametext—Form field name.
requiredboolfalseRequired.
disabledboolfalseDisabled.
invalidboolfalseMarks it invalid (a FieldError does too).
autocompletetext—Autofill hint.

Textarea

PropTypeDefaultDescription
rowsnumber4Height.
valuetext—Value.
placeholdertext—Placeholder.

FieldDescription

Helper text.

FieldError

An error; marks the control invalid.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Select

A native select, from options or option children.

Field(class: "max-w-xs") {
    Label "Size"
    Select(options: sizes, value: "M")
}
Props and events

Select

PropTypeDefaultDescription
optionslist—Strings or {value, label} records.
valuetext—Selected value.
nametext—Form field name.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Checkbox

A checkbox; pair it with a Label in a Field.

Field(class: "flex-row items-center gap-3") {
    Checkbox(checked: checked, @toggle: toggle_checked)
    Label "Email me about releases"
}
Props and events

Checkbox

PropTypeDefaultDescription
checkedboolfalseChecked.
nametext—Form field name.
disabledboolfalseDisabled.
  • @toggle — Toggled; value is "true" or "false".

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Switch

An on/off switch.

Field(class: "flex-row items-center gap-3") {
    Switch(checked: switch_on, @toggle: toggle_switch)
    Label "Dark previews"
}
Props and events

Switch

PropTypeDefaultDescription
checkedboolfalseOn.
labeltext—Accessible name without a Label.
disabledboolfalseDisabled.
  • @toggle — Flipped; value is the new state.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Slider

A range input.

Field(class: "max-w-sm") {
    Label "Volume"
    Slider(value: volume, @input: set_volume)
}
Props and events

Slider

@input reaches it.

PropTypeDefaultDescription
valuenumber50Value.
minnumber0Minimum.
maxnumber100Maximum.
stepnumber1Step.
valuetexttext—Spoken value (e.g. “40 percent”).

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

RadioGroup

One choice from several, as clickable rows.

2 parts
RadioGroup(label: "Plan", value: plan, @change: set_plan, class: "max-w-md sm:grid-cols-3") {
    RadioGroupItem(value: "Free") "Free"
    RadioGroupItem(value: "Pro") "Pro"
    RadioGroupItem(value: "Team") "Team"
}
Parts and props

RadioGroup

PropTypeDefaultDescription
labeltext—Accessible name.
valuetext—The choice.
nametext—Form field name.
  • @change — Chosen; value is its value.

RadioGroupItem

A radio and its label.

PropTypeDefaultDescription
valuetext—Its value.
disabledboolfalseDisabled.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

SearchField

A search box in a role="search" form.

SearchField(label: "Search the docs", placeholder: "Components, hooks…", class: "max-w-md")
Props and events

SearchField

PropTypeDefaultDescription
labeltextSearchAccessible name.
valuetext—Current query.
placeholdertextSearch…Placeholder.
actiontext—Go here on Enter, with the query (/search/?q=…).
nametextqThe query's name in that address.
unstyledflagfalseNo styles of its own (the form takes its classes, the box input_class).
input_classtext—Classes for the box.
autofocusflagfalseFocus the box when it appears (in a popover).
  • @input — The query changes (event.value).
  • @submit — Enter is pressed.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

NumberInput

A number field with decrease and increase buttons, clamped to its range.

NumberInput(label: "Guests", value: guests, min: 1, max: 12, @change: set_guests)
Props and events

NumberInput

PropTypeDefaultDescription
labeltextFieldVisible label.
valuenumber0Current value.
minnumber—Minimum.
maxnumber—Maximum.
stepnumber1Step.
hinttext—Help text.
  • @change — The value changes (event.value).

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

PinInput

One-time codes: a box per digit, auto-advancing, with Backspace going back.

PinInput(label: "Verification code", length: 6, @complete: noop)
Props and events

PinInput

PropTypeDefaultDescription
labeltextCodeGroup name.
lengthnumber6Number of digits.
  • @complete — Every digit is filled (event.value is the code).
  • @change — A digit changes.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Combobox

Type to filter a list of options (the ARIA combobox pattern with a listbox).

Combobox(label: "Country", options: countries, placeholder: "Start typing…", class: "max-w-xs")
Props and events

Combobox

PropTypeDefaultDescription
labeltextFieldVisible label.
optionslist—Option labels.
valuetext—Selected value.
placeholdertext—Placeholder.
hinttext—Help text.
  • @change — An option is chosen (event.value).

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

FileDrop

A drop zone for files that is also a real file input — click, drop or use the keyboard.

FileDrop(label: "Upload a photo", hint: "PNG or JPG, up to 5 MB", accept: "image/*", class: "max-w-md")
Props and events

FileDrop

PropTypeDefaultDescription
labeltextUpload a fileWhat to upload.
hinttext—Accepted types and sizes.
accepttext—The accept filter, e.g. image/*.
multipleboolfalseAllow several files.
  • @change — A file is chosen (event.value is its name).

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

ColorPicker

Pick from colour swatches; a radio group with arrow-key support.

Accent colour

ColorPicker(label: "Accent colour", colors: swatches, value: "#7c3aed")
Props and events

ColorPicker

PropTypeDefaultDescription
labeltextColourGroup label.
colorslist—Hex strings, or records with name and value.
valuecolor—Selected colour.
  • @change — A swatch is chosen (event.value is its colour).

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

What every chart shares

Point a chart or a DataTable at its data with a src, or pass rows with data. Columns are typed for you, and a missing or suppressed value is never drawn as zero. Each chart's own entry lists only what's particular to it; these work on all of them. Charts other than BarChart, LineChart, DonutChart and Sparkline need a cargo feature on weft, named in their entries, and say so on the page if it's missing.

DataTable(src: "/data/sales.csv")
LineChart(src: "/data/sales.csv", x: "month", y: "revenue, costs")
BarChart(src: "https://api.example.com/cities", path: "results", x: "name", y: "population")
LineChart(src: "https://data.api.abs.gov.au/rest/data/ABS,CPI/1.10001.10.50.Q", x: "TIME_PERIOD", y: "OBS_VALUE")
CandlestickChart(src: "/api/quotes/AAPL", refresh: 5)
LineChart(live: "wss://example.com/ticks", update: "append", keep: 500, x: "time", y: "price")
Data: everything that shows data
PropTypeDefaultDescription
datalist—Rows, as records, from Rust instead of src.
srctext—Where the data comes from: a CSV, TSV, JSON, NDJSON or GeoJSON file, a REST or GraphQL URL, or an official statistics API (SDMX and JSON-stat need stats).
viewtext—The name of a DataView above, to use its data instead.
formattext—csv, json, ndjson or sdmx, if it can't be told from the file or response.
pathtext—Where the rows are in a JSON response (data.items, results[*].stats). Found automatically when there's only one list.
querytext—A GraphQL query ({ … }); makes src a GraphQL endpoint. For the URL's query string, use params.
variablesrecord—GraphQL variables.
methodtextGETThe HTTP method.
bodytext—The request body.
paramsrecord—Added to the URL's query string: { startPeriod: "2024-01" }.
loadtext—build (into the page), browser, or both. Site files default to build; anything else to both.
refreshnumber—Load again every this many seconds, resting while the page is out of sight.
livetext—Where updates arrive: wss://… is a WebSocket, anything else server-sent events. Can replace src: the data then starts with the first message. Needs live.
subscriptiontext—A GraphQL subscription, over a WebSocket to live or to src. Needs live.
live_pathtext—Where the rows are in a live message.
eventtextmessageThe type of server-sent event to listen for.
updatetextappendWhat a live message does: append, upsert (the default given key) or replace.
keytext—The column identifying a row, for upsert.
keepnumber—The most recent rows to hold on to.
wheretext—Keep matching rows: TSEST=Original, REGION=Australia, or a record.
sorttext—A column to sort by; -column for descending.
limitnumber—The most rows to keep.
group_bytext—Combine rows with the same value in this column.
aggregatetextsumWith group_by: sum, mean, count, min or max. Cells with no value are left out, and a note says so.
missingtext—More markers for "no value", comma-separated, beyond the standard np, .., n.a. and so on.
paginatebooleanfalseFollow an API's pages to the end. Needs stats.
presettext—An export's layout: qualtrics, surveymonkey or tablebuilder. Needs stats.
skiptext—Rows to drop from the top, or auto to find the table. Needs stats.
header_rowsnumber1How many rows the header takes. Needs stats.
footernumber—Rows to drop from the end. Needs stats.
sheettext—Which sheet of an Excel workbook. Needs excel.
melttext—Columns to turn into variable and value rows, or true for every number column. Needs stats.
labelstext—A codebook of code and label, with column if codes differ by column. Needs stats.
  • @load The first data has arrived.
  • @update New data has arrived.
  • @error Loading failed; the event's value says why.
Display: every chart
PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
headingtext—A title shown above the chart; also its accessible name when there's no title.
x-labeltext—A title under the x axis.
y-labeltext—A title beside the y axis.
x-starttext—The first x value shown: a date, number or label. Earlier rows are left out.
x-endtext—The last x value shown, included. A date names its whole period: 2025 keeps all of 2025.
labeltext—Another name for title.
sourcetext—Who to credit, shown below it. SDMX data fills this in.
show_tablebooleanfalseOffer a table of the data below it.
controlstext—true for a selector per varying dimension, or columns, comma-separated. Needs charts.
facettext—A column to split into small multiples, on one scale. Needs charts.
linktext—A name shared with other charts: they hover together, and clicking narrows the others. Needs charts.
exporttext—true offers PNG, SVG and CSV, or name them: png, csv. Needs charts.
densenumber5000How many marks before drawing on a canvas instead of SVG. Needs charts.
widthnumber—Drawing width, used until it can measure the space it's in.
heightnumber—Drawing height.
  • @select A mark was clicked or chosen from the keyboard.

Charts: comparison

BarChart

A bar chart. Every bar is a labelled, focusable element; selecting one fires select.

BarChart(title: "Weekly downloads", data: downloads, unit: " downloads", selected: bar, @select: set_bar)
Props and events

BarChart

PropTypeDefaultDescription
breakstext—x values where the series changed method, comma-separated, marked with a line.
annotationslist—Records of y, x, or from and to, each with label.
stackedbooleanfalseStack the series. Totals rows are left out.
percentbooleanfalseStack to 100%.
horizontalbooleanfalseLay the bars on their sides.
totalsbooleanfalseDraw totals rows in a stack anyway.
moetext—A column of margins of error, drawn as error bars.
ci_lowtext—A column of lower bounds.
ci_hightext—A column of upper bounds.
rsetext—A column of relative standard errors: 25% and over are flagged.
xtext—The column along the x axis. Defaults to the first date or category.
ytext—The column to plot, or several comma-separated. Defaults to every numeric column.
seriestext—A column to split into one series per value.
titletextBar chartThe figure's accessible name.
datalist—Records with label, value and optional color.
unittext—Suffix for values.
selectednumber-1Highlighted bar.
colorscolors—Space-separated bar colours.
colorcolor—One colour for every bar.
widthnumber560Drawing width (it scales responsively).
heightnumber300Drawing height.
  • @select — A bar is clicked or activated (event.index).

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

LollipopChart

Bars thinned to a stem and a dot, for many categories at once. Needs charts.

LollipopChart(title: "Uptime by service", data: downloads, unit: " hrs")
Props and events

LollipopChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The column along the x axis.
ytext—The column to plot, or several comma-separated.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

DumbbellChart

Two values per row and the gap between them: before and after. Needs charts.

  • Before
  • After
DumbbellChart(title: "Before and after", data: before_after, x: "label", y: "before, after")
Props and events

DumbbellChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The column along the x axis.
ytext—The column to plot, or several comma-separated.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

BulletChart

A value against its target, on bands of how good that is. Needs charts.

BulletChart(title: "Sales against target", data: targets_data, x: "label", y: "value, target")
Props and events

BulletChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The column along the x axis.
ytext—The value column, then the target column.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

RadarChart

Series around a circle: profiles across several measures. Needs charts.

  • Ana
  • Ben
RadarChart(title: "Skills", data: profile, x: "label", y: "ana, ben")
Props and events

RadarChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The column along the x axis.
ytext—The column to plot, or several comma-separated.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

SlopeChart

Each series from its first value to its last. Needs charts.

SlopeChart(title: "Change", data: slopes, x: "year", y: "sales, costs")
Props and events

SlopeChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The column along the x axis.
ytext—The column to plot, or several comma-separated.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Charts: over time

LineChart

A smooth line with a gradient area and labelled points.

LineChart(title: "Stars this year", series: series, labels: series_labels, color: "#06b6d4", unit: " stars")
Props and events

LineChart

PropTypeDefaultDescription
zerobooleanfalseStart the y axis at zero.
annotationslist—Records of y, x, or from and to, each with label.
breakstext—x values where the series changed method, comma-separated.
stepbooleanfalseHold each value until the next.
smoothbooleanfalseCurve between points.
moetext—A column of margins of error, drawn as a band.
ci_lowtext—A column of lower bounds.
ci_hightext—A column of upper bounds.
rsetext—A column of relative standard errors: 25% and over are flagged.
labelstext—A codebook of code and label, with column if codes differ by column. With plain series numbers, a list of x labels.
xtext—The column along the x axis. Defaults to the first date or category.
ytext—The column to plot, or several comma-separated. Defaults to every numeric column.
seriestext—A column to split into one series per value, or a plain list of numbers (with labels).
titletextLine chartThe figure's accessible name.
colorcolor#8b5cf6Line colour.
fillbooltrueGradient area under the line.
unittext—Suffix for values.
widthnumber560Drawing width.
heightnumber260Drawing height.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

AreaChart

Values filled to the baseline. Several series stack, and stream centres them. Totals rows are left out. Needs charts.

  • Web
  • Mobile
AreaChart(title: "Traffic", data: traffic, x: "day", y: "web, mobile")
Props and events

AreaChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The column along the x axis.
ytext—The column to plot, or several comma-separated.
seriestext—A column to split into one series per value.
streambooleanfalseCentre the stack around the middle.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

RangeAreaChart

A band between a low and a high, with an optional line through it. Needs charts.

RangeAreaChart(title: "Temperatures", data: temps, x: "day", low: "low", high: "high", y: "mean")
Props and events

RangeAreaChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The column along the x axis.
lowtextlowThe lower column.
hightexthighThe upper column.
ytext—A line through the band.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

CandlestickChart

Open, high, low and close. Rising candles are hollow and falling ones solid, so direction never rests on colour alone. Needs charts.

CandlestickChart(title: "Share price", data: candles, x: "date")
Props and events

CandlestickChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The column along the x axis.
opentextopenThe opening column.
hightexthighThe high column.
lowtextlowThe low column.
closetextcloseThe closing column.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

CalendarHeatmap

One square per day, in weeks, darker for more. Needs charts.

  • 0
  • 9
CalendarHeatmap(title: "Commits", data: days, x: "date", y: "n")
Props and events

CalendarHeatmap

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The date column.
ytext—The column to plot, or several comma-separated.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

GanttChart

A bar per task, from its start to its end. Needs charts.

  • Studio
  • Engineering
GanttChart(title: "Schedule", data: tasks, x: "task", start: "start", end: "end", series: "team")
Props and events

GanttChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The tasks' names.
starttextstartThe start column.
endtextendThe end column.
seriestext—A column to colour by.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Sparkline

A tiny trend line for tables and stat cards.

div(class: "flex items-center gap-6") {
    Sparkline(label: "Requests trend", values: series)
    Sparkline(label: "Latency trend", values: latency, color: "#f43f5e")
}
Props and events

Sparkline

PropTypeDefaultDescription
xtext—The column along the x axis. Defaults to the first date or category.
ytext—The column to plot, or several comma-separated. Defaults to every numeric column.
seriestext—A column to split into one series per value.
labeltextTrendAccessible name.
valueslist—Numbers.
colorcolor#10b981Line colour.
widthnumber120Drawing width.
heightnumber36Drawing height.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Charts: part to whole

DonutChart

A donut with a legend and an optional figure in the middle.

  • Web54%
  • Server31%
  • Desktop15%
DonutChart(title: "Deploy targets", data: donut, center: "54%", center-label: "web")
Props and events

DonutChart

PropTypeDefaultDescription
piebooleanfalseNo hole in the middle.
xtext—The column along the x axis. Defaults to the first date or category.
ytext—The column to plot, or several comma-separated. Defaults to every numeric column.
seriestext—A column to split into one series per value.
titletextDonut chartThe figure's accessible name.
datalist—Records with label, value and optional color.
centertext—Big text in the middle.
center-labeltext—Small text under it.
center-colorcolor#0f172aColour of the middle text.
stackedboolfalseAlways put the legend under the chart.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

TreemapChart

Rectangles sized by value, coloured by group or by size. Totals rows are left out. Needs charts.

  • Home
  • Life
TreemapChart(title: "Budget", data: budget_items, x: "label", y: "value", series: "group")
Props and events

TreemapChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The names.
ytext—The column to plot, or several comma-separated.
seriestext—A column to colour by.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

SunburstChart

Rings of a hierarchy, with each slice inside its parent. Needs charts.

  • Home
  • Life
SunburstChart(title: "Population", data: budget_items, levels: "group, label", y: "value")
Props and events

SunburstChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
levelstext—The hierarchy's columns, outermost last.
ytext—The column to plot, or several comma-separated.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

WaffleChart

A hundred squares, shared out. Easier to read as parts of a whole than a pie. Needs charts.

  • Mon12.8%
  • Tue18.7%
  • Wed16.8%
  • Thu23.7%
  • Fri28%
WaffleChart(title: "Spending", data: downloads)
Props and events

WaffleChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The column along the x axis.
ytext—The column to plot, or several comma-separated.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

FunnelChart

Stages narrowing, each shown as a share of the first. Needs charts.

FunnelChart(title: "Signups", data: stages, unit: " people")
Props and events

FunnelChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The column along the x axis.
ytext—The column to plot, or several comma-separated.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

MekkoChart

Stacks whose widths show each column's share too. Needs charts.

  • Web
  • Mobile
MekkoChart(title: "Market", data: traffic, x: "day", y: "web, mobile")
Props and events

MekkoChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The column along the x axis.
ytext—The column to plot, or several comma-separated.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

WaterfallChart

How a start becomes an end: each step's rise or fall in order, with totals drawn from zero. Needs charts.

WaterfallChart(title: "Cash flow", data: flows)
Props and events

WaterfallChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The column along the x axis.
ytext—The column to plot, or several comma-separated.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Charts: distribution

Histogram

Counts in equal-width bins with round edges. The bin count suits the data unless bins says otherwise. Needs charts.

Histogram(title: "Ages", data: people, y: "age", bins: 5)
Props and events

Histogram

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
ytextvalueThe number column.
binsnumber—About how many bins.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

BoxPlot

Medians, quartiles and outliers, a row per group. Needs charts.

BoxPlot(title: "Weight by group", data: people, x: "group", y: "weight")
Props and events

BoxPlot

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—A column of groups, a row each.
ytextvalueThe number column.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

ViolinPlot

Smoothed spreads, mirrored, with the median marked: a box plot that shows the shape. Needs charts.

Smoothed: curves can run past the actual values.

ViolinPlot(title: "Weight by group", data: people, x: "group", y: "weight")
Props and events

ViolinPlot

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—A column of groups, a row each.
ytextvalueThe number column.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

DensityPlot

A smooth estimate of each group's spread. Needs charts.

  • A
  • B

Smoothed: curves can run past the actual values.

DensityPlot(title: "Weight", data: people, series: "group", y: "weight")
Props and events

DensityPlot

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
seriestext—A column of groups, a curve each.
ytextvalueThe number column.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

StripPlot

Every value as a dot, a row per group. beeswarm moves overlapping dots apart. Needs charts.

StripPlot(title: "Weight", data: people, x: "group", y: "weight", beeswarm: true)
Props and events

StripPlot

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—A column of groups, a row each.
ytextvalueThe number column.
beeswarmbooleanfalseMove overlapping dots apart.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

RidgelinePlot

Densities in overlapping rows, for seeing many groups' shapes together. Needs charts.

Smoothed: curves can run past the actual values.

RidgelinePlot(title: "Weight", data: people, x: "group", y: "weight")
Props and events

RidgelinePlot

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—A column of groups, a row each.
ytextvalueThe number column.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Charts: relationship

ScatterChart

One point per row, between two number columns. Rows missing either aren't drawn, and a note says how many. Needs charts.

  • A
  • B
ScatterChart(title: "Height and weight", data: people, x: "height", y: "weight", series: "group", label: "name")
Props and events

ScatterChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The horizontal column.
ytext—The vertical column.
seriestext—A column to colour by.
labeltext—The column naming each point.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

BubbleChart

A scatter plot whose points are sized by a third column, by area. Needs charts.

BubbleChart(title: "Countries", data: people, x: "height", y: "weight", size: "age", label: "name")
Props and events

BubbleChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The horizontal column.
ytext—The vertical column.
sizetext—The column sizing each point.
seriestext—A column to colour by.
labeltext—The column naming each point.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

HeatmapChart

Cells coloured by value, or with correlate, how each pair of number columns moves together. Needs charts.

  • 0
  • 7
HeatmapChart(title: "Activity", data: grid, x: "day", y: "time", value: "n")
Props and events

HeatmapChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The columns' column.
ytext—The rows' column.
valuetextvalueThe column colouring the cells.
correlatebooleanfalseShow correlations between the number columns instead.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

ParallelCoordinates

A vertical axis per number column and a line per row, for comparing rows across many measures. Needs charts.

  • A
  • B
ParallelCoordinates(title: "Cars", data: people, y: "height, weight, age", label: "name", series: "group")
Props and events

ParallelCoordinates

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
ytext—The number columns, comma-separated. Defaults to all of them.
seriestext—A column to colour by.
labeltext—The column naming each row.
datalist—Rows, as records.
colorscolors—Space-separated colours, replacing the palette.
unittext—Suffix for values.
heightnumber—Its height in pixels.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Charts: flows and networks

SankeyChart

Flows between stages, each as wide as its amount. Needs flow. Connections that go in a circle are refused: use a ChordChart.

SankeyChart(title: "Energy", data: flows_between, from: "from", to: "to", value: "value")
Props and events

SankeyChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
fromtextfromThe column naming where each link starts.
totexttoThe column naming where it ends.
valuetextvalueThe column of amounts.
unittext—Suffix for values.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

ChordChart

Flows between groups, in both directions, around a circle. Needs flow.

ChordChart(title: "Trade", data: trade, from: "from", to: "to", value: "value")
Props and events

ChordChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
fromtextfromThe column naming where each link starts.
totexttoThe column naming where it ends.
valuetextvalueThe column of amounts.
unittext—Suffix for values.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

NetworkGraph

Nodes and the links between them, in a layout that comes out the same every time. Needs flow.

NetworkGraph(title: "Network", data: trade, from: "from", to: "to", value: "value")
Props and events

NetworkGraph

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
fromtextfromThe column naming where each link starts.
totexttoThe column naming where it ends.
valuetextvalueThe column of amounts.
unittext—Suffix for values.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

TreeDiagram

A hierarchy, from a column of names and a column of each one's parent. Needs flow.

TreeDiagram(title: "Team", data: team, x: "name", parent: "parent")
Props and events

TreeDiagram

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The names.
parenttextparentThe column naming each one's parent.
valuetext—A number to show with each.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

ArcDiagram

Nodes on a line, with arcs between those that connect. Needs flow.

ArcDiagram(title: "Links", data: trade, from: "from", to: "to", value: "value")
Props and events

ArcDiagram

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
fromtextfromThe column naming where each link starts.
totexttoThe column naming where it ends.
valuetextvalueThe column of amounts.
unittext—Suffix for values.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

WordCloud

Words sized by a number. Good for a first impression, poor for comparing: use a bar chart if the amounts matter. Needs flow.

WordCloud(title: "Words", data: words, x: "word", y: "n")
Props and events

WordCloud

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The words.
ytext—The numbers.
unittext—Suffix for values.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Charts: surveys and census

LikertChart

Answers on a scale, as shares centred on the middle answer, with the number of responses beside each. Responses with no answer aren't counted. Needs stats.

  • Strongly disagree
  • Disagree
  • Neutral
  • Agree
  • Strongly agree

Weighted shares. n counts responses, not weights.

LikertChart(title: "Staff survey", data: survey, items: "pay, hours, team", weight: "wt")
Props and events

LikertChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
itemstext—The question columns: Q4_*, or comma-separated.
scaletext—The answers in order. Common scales and codebooks don't need it.
weighttext—A column of survey weights.
min_basenumber0Hide results with fewer responses than this.
datalist—Rows, as records.
labelstext—A codebook of code and label, with column if codes differ by column. Answers keep its order.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Crosstab

A cross-tabulation: percentages of each row, column or the total, weighted if asked, with base sizes. Needs stats.

State by PayDisagreeNeutralAgreeStrongly agreen
NSW40%0%60%0%2
VIC0%60%0%40%2
QLD0%0%100%0%1
n1121

Weighted percentages of each row. n counts responses.

Crosstab(data: survey, row: "state", column: "pay", weight: "wt", percent: "row")
Props and events

Crosstab

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
rowtext—The column down the side.
columntext—The column across the top.
percenttextrowrow, column, total, or count for no percentages.
weighttext—A column of survey weights.
min_basenumber0Hide results with fewer responses than this.
captiontext—A caption for the table.
datalist—Rows, as records.
labelstext—A codebook of code and label, with column if codes differ by column. Answers keep its order.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

PopulationPyramid

Two series either side of a line, first row at the bottom: usually ages by sex. Totals rows are left out. Needs stats.

PopulationPyramid(title: "Population", data: ages, x: "age", y: "male, female", percent: true)
Props and events

PopulationPyramid

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The rows, youngest first.
ytext—The two columns.
seriestext—A column splitting long data into the two sides.
percentbooleanfalseShow each as a share of everyone.
datalist—Rows, as records.
labelstext—A codebook of code and label, with column if codes differ by column. Answers keep its order.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

DotPlot

Estimates as dots with their intervals, for comparing groups honestly. Needs stats.

DotPlot(title: "Estimates", data: estimates, x: "state", y: "pct", moe: "moe", unit: "%")
Props and events

DotPlot

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The rows.
ytext—The estimates.
moetext—A column of margins of error.
ci_lowtext—A column of lower bounds.
ci_hightext—A column of upper bounds.
unittext—Suffix for values.
datalist—Rows, as records.
labelstext—A codebook of code and label, with column if codes differ by column. Answers keep its order.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

PivotTable

Numbers summarised by rows and a column, with totals worked out from the data itself. Needs stats.

StateAgreeDisagreeStrongly agreeNeutralTotal
NSW1.20.8––2
VIC––11.52.5
QLD0.5–––0.5
Total1.70.811.55
PivotTable(data: survey, rows: "state", column: "pay", value: "wt", aggregate: "sum")
Props and events

PivotTable

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
rowstext—The columns down the side, comma-separated.
columntext—The column across the top.
valuetextvalueThe numbers to combine.
aggregatetextsumsum, mean, count, min or max. Cells with no value aren't counted.
totalsbooleantrueShow totals.
captiontext—A caption for the table.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Charts: maps

ChoroplethMap

Regions coloured by value: data joined to GeoJSON shapes by code, in classes of about equal size. Rows that match no region are reported, which catches boundary editions that don't match. Needs stats.

  • 38 to 42
  • 42 and over
ChoroplethMap(title: "Median age", data: regions_data, geo: demo_regions, join: "code", y: "age")
Props and events

ChoroplethMap

PropTypeDefaultDescription
projectiontext—mercator or equal-earth. Otherwise a plain fit, which suits one country.
zoombooleanfalseOffer zoom buttons, and centre on a click.
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
geotext—A GeoJSON file of the regions.
jointext—The column of region codes.
geo_keytext—The regions' property holding the codes. Found automatically.
ytext—The column colouring them.
pertext—A column to divide by, making a rate.
per_unitnumber100000What the rate is per.
classesnumber5How many colours.
unittext—Suffix for values.
datalist—Rows, as records.
labelstext—A codebook of code and label, with column if codes differ by column. Answers keep its order.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

TileMap

A square per region, coloured by value, so a small region with a lot of people isn't lost. Named grids for Australian and US states, or your own row and column. Needs maps.

  • 11%
  • 32%
TileMap(title: "States", data: states, tiles: "au-states", x: "code", y: "value", unit: "%")
Props and events

TileMap

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
tilestext—au-states or us-states.
xtext—The regions' codes.
ytextvalueThe column colouring them.
rowtextrowYour own grid's row column.
columntextcolumnYour own grid's column column.
unittext—Suffix for values.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

PointMap

Points at places, sized by area. cluster merges those that would overlap. Needs maps.

PointMap(title: "Cities", data: cities, lon: "lon", lat: "lat", size: "pop", label: "name", zoom: true)
Props and events

PointMap

PropTypeDefaultDescription
cluster_sizenumber28With cluster, the size in pixels of the cells it merges within.
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
lontextlonThe longitude column.
lattextlatThe latitude column.
sizetext—A column sizing each point, by area.
labeltext—The column naming each point.
clusterbooleanfalseMerge points that would overlap.
geotext—A GeoJSON file of regions to draw behind.
projectiontext—mercator or equal-earth. Otherwise a plain fit, which suits one country.
zoombooleanfalseOffer zoom buttons. Clicking a place centres on it.
unittext—Suffix for values.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

FlowMap

Lines between places, as thick as their amounts. Needs maps.

FlowMap(title: "Flights", data: routes, from_lon: "a", from_lat: "b", to_lon: "c", to_lat: "d", value: "n", label: "name")
Props and events

FlowMap

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
from_lontextfrom_lonWhere each starts: longitude.
from_lattextfrom_latWhere each starts: latitude.
to_lontextto_lonWhere each ends: longitude.
to_lattextto_latWhere each ends: latitude.
valuetextvalueThe column of amounts.
labeltext—The column naming each.
geotext—A GeoJSON file of regions to draw behind.
projectiontext—mercator or equal-earth. Otherwise a plain fit, which suits one country.
zoombooleanfalseOffer zoom buttons. Clicking a place centres on it.
unittext—Suffix for values.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Charts: single values

Gauge

A half-circle dial for one number against its range. It only turns red if low or high say what's out of range. Needs charts.

Gauge(title: "Capacity", value: 62, max: 100, unit: "%")
Props and events

Gauge

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
valuenumber—The number, if not from src.
ytextvalueThe column to take the last value of.
minnumber0The bottom of the range.
maxnumber100The top of the range.
lownumber—Below this is out of range.
highnumber—Above this is out of range.
unittext—Suffix for values.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Meter

A bar for one number against its range, with a mark for target. Needs charts.

Meter(title: "Budget used", value: 62, target: 80, unit: "%")
Props and events

Meter

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
valuenumber—The number, if not from src.
ytextvalueThe column to take the last value of.
minnumber0The bottom of the range.
maxnumber100The top of the range.
lownumber—Below this is out of range.
highnumber—Above this is out of range.
targetnumber—Where to mark a target.
unittext—Suffix for values.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

DataStat

A headline number from a source: its latest value and the change since the one before. Needs charts.

Downloads

2,710

▲ 420 (18.3%)

DataStat(label: "Downloads", data: downloads, y: "value")
Props and events

DataStat

PropTypeDefaultDescription
labeltext—What it is.
datalist—Rows, as records.
ytextvalueThe column to take the last value of.
unittext—Suffix for values.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Charts: 3D

Bar3D

Columns on a floor, from x, an optional z, and y for height. Depth makes values harder to compare, so the numbers come with it: prefer BarChart for reading values. Needs charts3d.

Show data
DayWeb
2024-03-01120
2024-03-02150
2024-03-03130
2024-03-04170
Bar3D(title: "Sales", data: traffic, x: "day", y: "web")
Props and events

Bar3D

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—One way along the floor.
ztext—The other way along the floor.
ytext—The heights.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Scatter3D

Balls at three numbers. Needs charts3d.

Show data
NameHeightWeightAge
Ana1656134
Ben1808241
Cai1727029
Dee1585552
Scatter3D(title: "People", data: people, x: "height", y: "weight", z: "age", label: "name")
Props and events

Scatter3D

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—One number column.
ytext—Another.
ztext—A third.
labeltext—The column naming each.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Surface3D

A grid of values as adjoining columns, coloured by height: a stepped surface rather than a smooth one. Needs charts3d.

Show data
DayTimeN
MonAM3
TueAM7
MonPM5
TuePM1
Surface3D(title: "Activity", data: grid, x: "day", z: "time", y: "n")
Props and events

Surface3D

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—One way along the floor.
ztext—The other way along the floor.
ytext—The heights.
datalist—Rows, as records.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Charts: build your own

Chart

A chart assembled from parts, for combinations no other chart covers. They all share one x axis and one y axis: two scales on one chart suggest a relationship that's only in the choice of scales. Needs charts.

8 parts
  • Mobile
  • Web
  • Web trend
  • Mobile days
Chart(title: "Traffic", data: traffic, x: "day") {
    ChartBand(from: "2024-03-02", to: "2024-03-03", label: "Campaign")
    ChartArea(y: "mobile", label: "Mobile")
    ChartBars(y: "web", label: "Web")
    ChartLine(y: "web", label: "Web trend")
    ChartDots(y: "mobile", label: "Mobile days")
    ChartRule(y: 125, label: "Target")
    ChartNote(x: "2024-03-04", y: 170, label: "Peak")
}
Parts and props

Chart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The column along the x axis.
unittext—Suffix for values.
datalist—Rows, as records.
x-starttext—The first x value shown: a date, number or label. Earlier rows are left out.
x-endtext—The last x value shown, included. A date names its whole period: 2025 keeps all of 2025.

ChartLine

PropTypeDefaultDescription
ytext—The column.
labeltext—Its name in the legend.
srctext—Its own data, apart from the chart's: joined to the rest on x, so other sources (and frequencies) share the time axis.
xtext—With src: the column of its dates.
indextext—Rebase to 100 at this date, to compare measures in different units by how they've changed.
changetext—Show percentage changes: "year" (from a year earlier) or "previous" (from the observation before).
unittext—What its values are in. Series in different units can't share a chart.

ChartBars

PropTypeDefaultDescription
ytext—The column.
labeltext—Its name in the legend.
srctext—Its own data, apart from the chart's: joined to the rest on x, so other sources (and frequencies) share the time axis.
xtext—With src: the column of its dates.
indextext—Rebase to 100 at this date, to compare measures in different units by how they've changed.
changetext—Show percentage changes: "year" (from a year earlier) or "previous" (from the observation before).
unittext—What its values are in. Series in different units can't share a chart.

ChartArea

PropTypeDefaultDescription
ytext—The column.
labeltext—Its name in the legend.
srctext—Its own data, apart from the chart's: joined to the rest on x, so other sources (and frequencies) share the time axis.
xtext—With src: the column of its dates.
indextext—Rebase to 100 at this date, to compare measures in different units by how they've changed.
changetext—Show percentage changes: "year" (from a year earlier) or "previous" (from the observation before).
unittext—What its values are in. Series in different units can't share a chart.

ChartDots

PropTypeDefaultDescription
ytext—The column.
labeltext—Its name in the legend.
srctext—Its own data, apart from the chart's: joined to the rest on x, so other sources (and frequencies) share the time axis.
xtext—With src: the column of its dates.
indextext—Rebase to 100 at this date, to compare measures in different units by how they've changed.
changetext—Show percentage changes: "year" (from a year earlier) or "previous" (from the observation before).
unittext—What its values are in. Series in different units can't share a chart.

ChartRule

PropTypeDefaultDescription
ynumber—A value to draw a line across at.
xtext—An x to draw a line up at.
labeltext—Words on it.

ChartBand

PropTypeDefaultDescription
fromtext—Where it starts.
totext—Where it ends.
axistextxx or y.
labeltext—Words on it.

ChartNote

PropTypeDefaultDescription
xtext—The x it points at.
ynumber—The value it points at.
labeltext—The words.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

CorrelationChart

Two series against each other, one point per period they share, with Pearson's r: does one rise or fall when the other changes? Each series can bring its own src; sources at different frequencies meet at the coarser one, and lag pairs the second with the first that long before. Needs charts.

CorrelationChart(title: "Cash rate and inflation", lag: "12 months") {
    ChartDots(src: "/data/cash-rate.csv", x: "period", y: "rate", label: "Cash rate")
    ChartDots(src: "/data/inflation.csv", x: "period", y: "inflation", label: "Inflation")
}
Props and events

CorrelationChart

PropTypeDefaultDescription
titletext—The figure's accessible name, read by screen readers; not shown. To show a title, use heading.
xtext—The dates' column, for series without their own src.
datalist—Rows, as records.
lagtext—Pair the second series with the first this long before: "12 months", "2 quarters", "1 year".
x-starttext—The first date compared.
x-endtext—The last date compared.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

DataView

Names a source for the components inside it. Any of them can then use it with view, adding its own where or sort, and they share one request.

DataView(name: "sales", data: downloads) {
    BarChart(title: "Sales", data: downloads)
}
Props and events

DataView

PropTypeDefaultDescription
nametext—What view calls it.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

3D & shaders

ShaderBackground

An animated fragment-shader background for the nearest positioned ancestor. Presets: mesh-gradient, aurora, plasma, galaxy, waves, synthwave, liquid, topography, rays, grid-glow, silk.

plasma

div(class: "relative isolate grid h-48 place-items-center overflow-hidden rounded-2xl text-white") {
    ShaderBackground(preset: "plasma", colors: "#0b1020 #7c3aed #06b6d4 #f472b6", speed: 0.6)
    p(class: "text-2xl font-black") "plasma"
}
Props and events

ShaderBackground

PropTypeDefaultDescription
presetmesh-gradient | aurora | plasma | galaxy | waves | synthwave | liquid | topography | rays | grid-glow | silkmesh-gradientWhich shader.
colorscolors—Up to four space-separated colours.
speednumber0.5Animation speed.
intensitynumber1Effect strength.
textureurl—An image for the shader to sample (u_map).

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

ParticleBackground

Drifting particles joined by lines, reacting to the pointer, as a background for the nearest positioned ancestor. Hover to grab, bubble or repulse; click to push, remove, bubble or repulse.

particles

div(class: "relative isolate grid h-56 place-items-center overflow-hidden rounded-2xl bg-slate-950 text-white") {
    ParticleBackground(count: 240, color: "#38bdf8 #a78bfa", link-color: "#38bdf8", hover: "grab", click: "push")
    p(class: "text-2xl font-black") "particles"
}
Props and events

ParticleBackground

PropTypeDefaultDescription
countnumber80How many particles, per density area.
densitynumber | false800Thousand square pixels per count particles, so the number follows the size; false keeps count fixed.
colorcolours | random#94a3b8Particle colours (each picks one), or random.
shapecircle | square | triangle | polygon | star | imagecircleShapes, space-separated (each picks one).
sidesnumber5Sides of a polygon, points of a star.
strokecolor#000000Outline colour.
stroke-widthnumber0Outline width.
imageurl—The image for shape: "image"; an SVG takes each particle's colour.
image-widthnumber1The image's width, for its aspect ratio.
image-heightnumber1The image's height, for its aspect ratio.
opacitynumber0.5Opacity, 0 to 1.
opacity-randombooleanfalseRandom opacity up to opacity.
opacity-speednumber0Pulse between opacity-min and opacity (0: no pulse).
opacity-minnumber0.1Lowest opacity when pulsing.
opacity-syncbooleanfalsePulse together.
sizenumber3Radius in pixels.
size-randombooleantrueRandom radius up to size.
size-speednumber0Pulse between size-min and size (0: no pulse).
size-minnumber0.1Smallest radius when pulsing.
size-syncbooleanfalsePulse together.
linksbooleantrueLines between nearby particles.
link-distancenumber150How near, in pixels.
link-colorcolor#94a3b8Line colour.
link-opacitynumber0.4Opacity of the shortest lines.
link-widthnumber1Line width.
movebooleantrueParticles drift.
speednumber2Drift speed.
directionnone | top | top-right | right | bottom-right | bottom | bottom-left | left | top-leftnoneWhich way they drift.
random-speedbooleanfalseVary the speed between particles.
straightbooleanfalseMove exactly in direction, not scattered around it.
edgeout | bounceoutLeave and come back on the opposite side, or bounce off the edges.
collidebooleanfalseParticles bounce off each other.
attractbooleanfalseLinked particles pull together.
attract-xnumber3000Horizontal pull (smaller is stronger).
attract-ynumber3000Vertical pull (smaller is stronger).
detectwindow | canvaswindowFollow the pointer anywhere, or only over the background.
hovergrab bubble repulse | nonegrabHover effects, space-separated.
clickpush remove bubble repulse | nonepushClick effects, space-separated.
grab-distancenumber140Reach of grab lines.
grab-opacitynumber1Opacity of the shortest grab lines.
bubble-distancenumber200Reach of bubble.
bubble-sizenumber40Radius particles bubble to.
bubble-opacitynumber0.8Opacity particles bubble to.
bubble-durationnumber0.4Seconds a click's bubble grows (and shrinks).
repulse-distancenumber200Reach of repulse.
repulse-durationnumber0.4Seconds a click's repulse lasts.
pushnumber4Particles a click adds.
removenumber2Particles a click removes.
seednumber1Random seed.
labeltext—Accessible name (decorative and hidden without one).

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

FloatingShapes

Glossy 3D shapes drifting in a WebGL scene — a decorative hero accent.

FloatingShapes(palette: "#8b5cf6 #22d3ee #f472b6", class: "h-64 w-full")
Props and events

FloatingShapes

PropTypeDefaultDescription
palettecolors#8b5cf6 #06b6d4 #f472b6Three colours.
labeltext—Accessible name (decorative and hidden without one).

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Globe

A glowing, rotating particle globe.

Globe(label: "A rotating globe", class: "mx-auto aspect-square w-64")
Props and events

Globe

PropTypeDefaultDescription
colorcolor#0ea5e9Globe colour.
glowcolor#22d3eeRim and particle colour.
labeltext—Accessible name.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

ProductViewer

A rotating 3D object over a shader backdrop — product shots without photos. material: "pbr" shades it physically (metallic-roughness); shadows puts it on a floor it casts a shadow on.

div(class: "grid grid-cols-2 gap-4") {
    ProductViewer(label: "A torus knot in 3D", shape: "torus-knot", color: "#f472b6", color2: "#8b5cf6", class: "aspect-square w-full overflow-hidden rounded-3xl")
    ProductViewer(label: "A gold knot casting a shadow", shape: "torus-knot", material: "pbr", metallic: 1, roughness: 0.3, color: "#e9b44c", color2: "#e2e8f0", shadows: true, class: "aspect-square w-full overflow-hidden rounded-3xl")
}
Props and events

ProductViewer

PropTypeDefaultDescription
shapecube | sphere | torus | torus-knot | icosphere | cylinder | conetorus-knotMesh.
colorcolor#a855f7Base colour.
color2color#22d3eeGradient colour.
wobblenumber0Noise displacement.
materialstandard | pbrstandardpbr: physically based shading (color is the albedo).
metallic0–10With pbr: how metallic.
roughness0–10.5With pbr: 0 mirror-like, 1 matte.
shadowsboolfalseCast a shadow on a floor below.
backdropmesh-gradient | aurora | plasma | galaxy | waves | synthwave | liquid | topography | rays | grid-glow | silksilkBackdrop shader preset.
backdrop-colorscolors#0f0a1f #312e81 #7c3aed #0e7490Backdrop colours.
labeltext—Accessible name.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Motion

Parallax

Moves its content at a different speed from the page as it scrolls past (scrubbed to the scroll position). Layer several with different distances for depth; clip makes a parallax window for images.

Scroll the page — the layers drift at different speeds.

Fast
Still
Slow
div(class: "space-y-4") {
    div(class: "grid grid-cols-3 gap-4") {
        Parallax(distance: -60) { div(class: "rounded-2xl bg-gradient-to-br from-brand-500 to-accent-400 p-6 text-center font-bold text-white") "Fast" }
        Parallax(distance: 0) { div(class: "rounded-2xl bg-slate-900 p-6 text-center font-bold text-white") "Still" }
        Parallax(distance: 60) { div(class: "rounded-2xl bg-gradient-to-br from-fuchsia-500 to-orange-400 p-6 text-center font-bold text-white") "Slow" }
    }
    Parallax(distance: 70, clip: true, class: "h-48 rounded-2xl") { img(src: photo_ocean, alt: "", class: "size-full object-cover") }
}
Props and events

Parallax

PropTypeDefaultDescription
distancenumber80Pixels travelled each way while it crosses the viewport; negative moves against the scroll.
axisy | xyDirection of travel.
scalenumber1Scale at the start (eases to 1).
rotatenumber0Degrees of rotation across the scroll.
smoothnumber0.4Seconds of smoothing (0 follows the scroll exactly).
clipboolfalseClip to the box and overhang the content, for image windows (give it a height).
inner_classtext—Classes for the moving layer.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

HorizontalScroll

A pinned section whose content slides sideways as the page scrolls down. With reduced motion (or before the runtime loads) it's an ordinary horizontally scrollable row.

Scroll down — the row pins and slides sideways.

Aurora
Plasma
Galaxy
Silk
Synthwave
Liquid
HorizontalScroll(label: "Shader presets", height: "20rem") {
    for panel in hscroll_panels { div(class: panel.class) "{panel.title}" }
}
Props and events

HorizontalScroll

PropTypeDefaultDescription
labeltextGalleryAccessible name of the section.
heighttext100vhHeight of the pinned viewport (CSS length).
track_classtext—Classes for the sliding row.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

Reveal

Animates its children in — once, as they scroll into view, or on hover — with a preset and an optional stagger. Honours reduced motion.

Hover the dashed box to play it, or press Replay. Change `trigger` under Customize.

Reveal(preset: "pop", stagger: 0.08, trigger: "hover", class: "flex gap-3") {
    div(class: "size-16 rounded-2xl bg-gradient-to-br from-brand-500 to-accent-400")
    div(class: "size-16 rounded-2xl bg-gradient-to-br from-fuchsia-500 to-brand-500")
    div(class: "size-16 rounded-2xl bg-gradient-to-br from-accent-400 to-emerald-400")
}
Props and events

Reveal

PropTypeDefaultDescription
presetfade | fade-up | fade-down | fade-left | fade-right | zoom-in | zoom-out | flip-up | blur-in | pop | rise | spin-in | tilt-in | float | pulse | wobblefade-upThe animation.
staggernumber—Seconds between children (animates each child in turn).
triggerscroll | load | hoverscrollWhen it plays.
delaynumber—Seconds before it starts.
durationnumber—Seconds (defaults to the preset's).

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.

SplitText

Text animated letter by letter or word by word; screen readers get the whole text once.

Hover the dashed box to play it, or press Replay. Change `trigger` under Customize.

Rendered beautifully

h3(class: "text-4xl font-black tracking-tight") { SplitText(text: "Rendered beautifully", by: "chars", preset: "flip-up", trigger: "hover") }
Props and events

SplitText

PropTypeDefaultDescription
texttext—The text.
bychars | wordscharsHow to split it.
presetfade-up | fade | pop | flip-up | blur-in | rise | zoom-in | tilt-infade-upThe animation for each piece.
staggernumber0.03Seconds between pieces (0.08 for words).
triggerload | scroll | hoverloadWhen it plays.
delaynumber—Seconds before it starts.

Every part also takes class (merged with its own — yours win), as, and attributes such as id, aria-* and data-* and DOM events such as @click, which go to its element.