Manual UI

UI

elements man ui

@elements/ui is the UI package: some eighty templates, from Button and Input to Dialog, Select, DataTable and Toast, the behaviors they are built from, twelve themes, and the stylesheet they share: the tokens, the type scale, the layout primitives and the classes for buttons, forms, cards and pills. It covers all of the primary UI templates an app will need; anything else can be composed or created from these primitives. A template is an Elements HTML template imported from its own path and written like any tag, with typed attributes, slots and two-way state. It renders on the server, so the page arrives finished, and it imports its own CSS, so importing a template styles it.

Install

Every new app has it: elements create pins @elements/ui in config.jsoc and imports it in app/shared/styles/page.css, so there is nothing to install. It is its own package, versioned apart from the Elements tooling, and an app that wants none of it removes it with elements uninstall @elements/ui and deletes the import.

app/shared/styles/page.css
@import "@elements/ui"; @import "./vars.css";

The import loads the base classes (the design system: tokens, the reset, bare element styling, typography, layout and utilities), the theme contract the templates read, and the default look. vars.css holds the app's own token overrides, so it comes after. See elements man style for the classes and tokens.

Import a template

One import per template, from @elements/ui/<name>, where <name> is the page name in the table below. A template's parts come from the same path:

app/pages/settings/template.ehtml
import { Button } from "@elements/ui/button"; import { Dialog, DialogFooter, DialogClose } from "@elements/ui/dialog"; <Dialog title="Edit profile" description="Make changes, then save."> <Button slot="trigger">Edit profile</Button> <input value={form.name}> <DialogFooter> <DialogClose><Button>Cancel</Button></DialogClose> <Button variant="primary" onclick={() => save(form)}>Save</Button> </DialogFooter> </Dialog>

Attributes are typed: a variant that does not exist is a build error, and the editor completes the ones that do. An attribute its page marks two-way can be bound to state. <Dialog open={state.editing}> opens and closes from the page, and the dialog writes false back when the user closes it; written as a literal, <Dialog open>, the template owns the state. Every template takes class for extra classes on its root, and a template with a native element at its root takes attrs for any other attribute on it.

Read a template's page before you build with it: elements man ui/templates/dialog. The order of reach is a template before a class, and a class before a rule of your own. A <Button> renders the design system's .button, so it matches a bare <button> on the same page.

Themes

The default look is the design system's monochrome. A different look is one more import after the package, before vars.css:

app/shared/styles/page.css
@import "@elements/ui"; @import "@elements/ui/themes/editorial"; @import "./vars.css";

A theme is a full look: type, corners, density, borders, shadows, motion and color, in light and dark, and every template reads the same tokens, so one import restyles all of them. Twelve ship, from editorial to coder to brutalist; themes (opens in a new tab) describes each and how to choose. Dark mode follows the OS preference, and <html data-theme="dark"> forces it. Branding stays in vars.css: the accent tokens there apply inside any theme.

Emails take the mail-safe baseline instead: @import "@elements/ui/email"; in app/shared/styles/email.css, which a new app has too.

Behaviors

Behaviors are reusable functions for focus, the keyboard, positioning and dismissal, exported from @elements/ui/behaviors for templates of your own: focusScope (trap focus and return it), rovingFocus (one tab stop, arrows between items), typeahead (jump to an item by typing), pushLayer (close on Escape or an outside press, stacked), float (position a panel beside an anchor), presence (enter and exit animation), lockScroll, announce (a live region), drag, activeDescendant and gridFocus. Each takes DOM elements and returns a release function. Start one in oninsert and release it in onremove. The shipped templates call the same functions. Behaviors (opens in a new tab) has a page per behavior: the signature, every option with its default, what it writes to the DOM, and an example in a template of your own.

Editors

Two templates, CodeEditor and RichText, install separately. Their pages are here with the rest.

Templates

Each template imports from @elements/ui/<name>, where <name> is the page name in its link. CodeEditor and RichText install separately.

Forms

Template What it is
Button (opens in a new tab) A button or a link that looks like one, in six variants and four sizes.
ButtonGroup (opens in a new tab) Related buttons, or an input and its buttons, joined into one control.
Input (opens in a new tab) A native text input in the theme's control chrome, with a two-way value.
InputGroup (opens in a new tab) An Input or Textarea with icons, text and buttons inside one box.
Textarea (opens in a new tab) A native multi-line input that grows with its content, between rows and maxRows.
Field (opens in a new tab) A label, a control, a description and an error wired together, with native validation that never moves the layout.
Label (opens in a new tab) A native label for a control, which dims when the control is disabled.
NativeSelect (opens in a new tab) The browser's own select, styled as a control. Native pickers on phones, no script needed.
Checkbox (opens in a new tab) A native checkbox drawn by the theme, with an indeterminate (mixed) state.
RadioGroup (opens in a new tab) One choice from a set: native radios sharing a name, with arrow-key movement.
Switch (opens in a new tab) An on/off control that takes effect at once: a native checkbox with the switch role.
Toggle (opens in a new tab) A button that is on or off, with aria-pressed.
ToggleGroup (opens in a new tab) A set of toggle buttons, one or many on, with one tab stop and arrow keys.
Slider (opens in a new tab) Pick a value or a range by dragging thumbs along a track, with full keyboard support.
NumberInput (opens in a new tab) A number field with stepper buttons, keyboard steps, formatting, wheel and scrub.
PasswordInput (opens in a new tab) A password field with a button that shows and hides what was typed.
InputOTP (opens in a new tab) A one-time code in separate slots, with paste, SMS autofill and a pattern.
TagsInput (opens in a new tab) Type a list of tags into one field: add, edit, delete and paste them from the keyboard.
ColorPicker (opens in a new tab) Pick a color with an area, channel sliders, inputs, swatches and the eye dropper.
FileUpload (opens in a new tab) Drop, paste or browse for files; see them listed with previews, sizes, errors and progress.
Select (opens in a new tab) Pick one value, or several, from a styled listbox that lines the selected option up over the trigger.
Combobox (opens in a new tab) A text input that filters a list of options as you type, for one value or several shown as chips, with async results.

Overlays

Template What it is
Dialog (opens in a new tab) A modal window over the page that traps focus until it closes.
AlertDialog (opens in a new tab) A modal that interrupts with something important and waits for an answer.
Sheet (opens in a new tab) A dialog that slides in from an edge of the screen, for content that complements the page.
Drawer (opens in a new tab) A panel that slides from an edge and can be dragged away, with snap points and a scaled background.
Popover (opens in a new tab) Rich content in a floating panel, opened by a trigger, that keeps the page usable.
HoverCard (opens in a new tab) A preview of what a link points to, shown while the pointer rests on it.
Tooltip (opens in a new tab) A short label for a control, shown on hover and keyboard focus.
DropdownMenu (opens in a new tab) A menu of actions from a button, with submenus, checkbox and radio items.
ContextMenu (opens in a new tab) A menu at the pointer on right-click or long-press.
Menubar (opens in a new tab) A desktop-style bar of menus that stays open as you move across it.
NavigationMenu (opens in a new tab) Site navigation with large animated dropdown panels.
Command (opens in a new tab) A searchable, ranked list of actions run from the keyboard: inline, in a popover, or as a command palette.
Toast (opens in a new tab) Short notices that stack at an edge of the screen, pause on hover and close on their own or with a swipe.

Display

Template What it is
Badge (opens in a new tab) A small label for a status, a count or a category, built on the pill.
Card (opens in a new tab) A surface with a header, body and footer, built on the base card styles.
Alert (opens in a new tab) A callout that draws attention to a message, with an icon, a title and an action.
Icon (opens in a new tab) An inline stroke icon from the set the templates draw their own controls with, sized in pixels and colored by the text around it.
Kbd (opens in a new tab) A keyboard key or shortcut, as text.
Separator (opens in a new tab) A horizontal or vertical rule between content, semantic or decorative.
Skeleton (opens in a new tab) A placeholder shape shown while content loads, or wrapped around the content so it never moves.
Spinner (opens in a new tab) An indeterminate loading indicator, the same ring a loading Button draws.
Progress (opens in a new tab) A bar showing how far a task has run, or that it is running.
AspectRatio (opens in a new tab) Keeps media at a fixed width-to-height ratio, with its space held before it loads.
Avatar (opens in a new tab) A user image with an initials fallback, a delayed fallback, a status badge and groups.
Empty (opens in a new tab) The empty state for a list, a search or a page: media, a title, a line and what to do next.
Item (opens in a new tab) A row with media, a title, a description and actions, alone or in a list.
Table (opens in a new tab) A styled data table with caption, header, footer, alignment and row states.
Accordion (opens in a new tab) A stack of headings that each show and hide a panel, one or several at a time.
Collapsible (opens in a new tab) A trigger that shows and hides a region, with its height animated.
Tabs (opens in a new tab) Layered panels, one shown at a time, chosen from a list of tabs.
Breadcrumb (opens in a new tab) The path to the current page as a trail of links, composed from parts or built from a list.
Pagination (opens in a new tab) Page numbers with previous and next, from a page count or composed from parts.
Tree (opens in a new tab) A hierarchical list that opens with the arrow keys, selects one node or many, and loads children on demand.

Layout

Template What it is
Sidebar (opens in a new tab) An app sidebar that collapses to icons or off the canvas and becomes a sheet on phones.
Resizable (opens in a new tab) Panels separated by handles you drag or move with the arrow keys.
Carousel (opens in a new tab) Slides you swipe, drag or step through, with momentum, snapping, loop and autoplay.
ScrollArea (opens in a new tab) A scroll container with thin, themed scrollbars over native scrolling.

Dates

Template What it is
Calendar (opens in a new tab) A month grid for picking one date, several dates or a range, with keyboard navigation across months.
DatePicker (opens in a new tab) A button or text field that picks one date from a Calendar in a popover.
DateRangePicker (opens in a new tab) A button that picks a start and end date from a two-month range Calendar in a popover.
TimePicker (opens in a new tab) A time of day in the browser's own time field, styled as a control, with steps, limits and suggestions.

Data

Template What it is
DataTable (opens in a new tab) A data grid: sort, search, filter, resize, reorder, pin, group, select, edit, page or virtualize, save views and export.
VirtualList (opens in a new tab) A long list, or a grid of rows and columns, that renders only the items near the viewport, with measured row heights.
Chart (opens in a new tab) What every chart shares: the config and its colors, the tooltip, the legend, the palette and the data table.
BarChart (opens in a new tab) Vertical, horizontal, stacked and grouped bars with tooltip, legend and labels.
LineChart (opens in a new tab) Lines over categories with dots, curves, labels and a crosshair tooltip.
AreaChart (opens in a new tab) Filled areas, stacked or expanded, solid or gradient, with a crosshair tooltip.
PieChart (opens in a new tab) Pie and donut charts with labels, a center value, an active slice and stacked rings.
RadarChart (opens in a new tab) Values on radial axes, one polygon per series, over a polygon or circle grid.
RadialChart (opens in a new tab) Radial bars and gauges, with tracks, labels along the arc and a center value.
Kanban (opens in a new tab) A board of columns of cards you reorder and move by pointer, touch or keyboard, with announcements and a one-column phone layout.

Chat

Template What it is
Message (opens in a new tab) One chat message with avatar, author, time, streaming Markdown, attachments, actions and response branches.
MessageList (opens in a new tab) A conversation that stays pinned to the newest message unless the reader scrolls up.
PromptInput (opens in a new tab) A growing message composer with attachments, tools, a model picker and a send button that stops a streaming reply.
Attachment (opens in a new tab) A file or source as a thumbnail, chip or row, with preview, size, upload progress and remove.

Editors

Template What it is
RichText (opens in a new tab) A rich text editor with a formatting toolbar, markdown shortcuts, links, task lists, a slash menu, find and replace and image upload.
CodeEditor (opens in a new tab) A code editor with highlighting, line numbers, folding, completion, search, multiple cursors and diagnostics.