Skip to content

Element atlas

64 elements. Poke any of them.

Every card below is the real engine running that element's example. Press, drag and type, then flip a card to see the lines that draw it.

Layout

Containers that place other elements, plus each, which repeats elements once per item of a list.

All on one page →
column
row

Places children side by side, splitting the width equally. On narrow screens they wrap; sibling cards share a height per line by default.

Open →
overlap

Puts its later children on top of its first one, at a corner, an edge or the middle: a Sale badge on a picture, a count on an icon, a label over a card. The first child sets the size.

Open →
grid

Places children in responsive equal columns. Cards in the same grid row automatically share a height, keeping dashboard panels aligned.

Open →
card

A surface that groups related content, stacked vertically. Give it on= to make the whole card pressable.

Open →
list

A bordered list of rows, separated by lines. Use list-item children; any other element (a row, a check) becomes a row of its own.

Open →
list-item

One row of a list: a title, an optional detail line and value on the right, and anything inside it (a badge, a check, a row) under the title. Give it on= to make it pressable.

Open →
accordion

A heading that shows or hides the content under it when pressed. Stack several for an FAQ.

Open →
each

Repeats what's inside it once per item of a list, in place, with no look of its own; inside, the current item is called item (or the name given by as=). if= on each keeps only the items it's true for: each items=tasks as=t if={owner == 'All' || t.owner == owner}.

Open →
timeline

Steps in order with a line joining them: itineraries, how-to guides, order tracking, project history. Give steps a status only to show progress, like where an order is or which step the person has reached.

Open →
step

One step of a timeline: a title, an optional detail line and time, and whether it's done, current or upcoming.

Open →
carousel

Cards side by side, a page at a time, with arrows and dots: a few options to browse, like products, hotels or recipes. Put a card per option inside it (or each over a list).

Open →
scroll

A region that shows its children up to a fixed height and scrolls the rest, for a long list inside a card: messages, activity, results. Everything inside is still read and copied.

Open →

Content

Text, images, code, badges and avatars.

All on one page →
text

A paragraph or heading that wraps to the available width. Use {expressions} to show state.

Open →
image
image "Ridgeline trail runners, side view" src="/images/ridgeline.jpg" ratio=4:3

A picture, such as a product photo. The quoted text says what it shows, and is displayed if the image can't load.

Open →
code

A short piece of code or a command, in a monospaced font on a tinted block.

Open →
badge

A small rounded label for a status or a short tag, like Shipped or New.

Open →
avatar

A person's initials in a circle, with their name and an optional detail line beside it.

Open →
callout

The one thing to notice in an answer: a key finding, a warning or a next step.

Open →
icon

A small symbol on its own, like a status mark or a weather sign. To start a line of text or a list row with one, use icon= on text or list-item instead.

Open →
tile

A small fixed-size face with a value, an optional icon and a detail line, for playing cards, seats, dice, keys or lottery numbers. Several in a row keep their size and wrap.

Open →

Data

Figures, ratings, charts, tables and the world map. map and pin ship in the separate sayshape/map entry point because the country outlines add about 76 KB.

All on one page →
stat

A labelled number, for key figures like totals or counts. Add change= to show how it moved, and spark= for a small line of its recent values.

Open →
rating

A star rating. Shows value= as stars, or with bind= lets the user pick a rating.

Open →
chart

A chart of a list of records: bar or line for one or more numbers per item, such as revenue and last year's revenue by month, stacked for each item's total split into parts, such as revenue by product per month, area for an amount over time, hbar for a ranking with long names, such as top customers, pie or donut for how one number splits across items, such as sales by region, funnel for how many get through each stage, such as leads to won deals, waterfall for how changes add up to a total, such as revenue minus costs, bullet for each KPI against its target, such as quarterly goals, heatmap for one number across two dimensions, such as retention by cohort, scatter for how two numbers relate, such as price against rating, treemap for how a total splits across many parts, such as costs by line item, or sankey for how amounts flow from sources to where they end up, such as budget to departments to projects. It redraws when the list changes, and shows at most 200 items, 6 series and 6 slices (smaller slices are summed into Other).

Open →
chart-line

Under a bar or line chart: another field of the same items drawn as a line on top, on the same scale, such as a forecast or last year over this year's bars. Name the chart's own bars in the legend with its labels=, like labels="This year".

Open →
chart-rule

Under a bar or line chart: a level drawn across the plot, such as a target, a budget or an average.

Open →
chart-note

Under a bar or line chart: a marker at one item with a few words, such as a launch or an outage.

Open →
meter

One number against its range, as a ring or a gauge: progress toward a goal, a score, utilization or a budget used. Add bands= to color it bad, warn or good by where the value falls.

Open →
table

Rows of a list of records, one table-column per field, for things like inventory, orders or expenses. With sort= and direction=, pressing a header sorts by it; with bind= and key=, pressing a row selects it; columns too wide for the space scroll sideways, the first one staying in view.

Open →
table-column

One column of a table: its header and the field it shows.

Open →
compare

Two to four options side by side with one row per attribute, marking the best value in each row: plans, products or choices to weigh up. Use compare-row children.

Open →
compare-row

One row of a comparison: an attribute and the field each option's value comes from.

Open →
details

One record as label and value rows, for a single customer, order, policy or ticket: its fields one per line, with an optional status badge. Use detail children; for many records use a table.

Open →
detail

One row of details: a field's name and its value.

Open →
schedule

Blocks laid out on time from a list: a week of shifts, the day's room bookings, an itinerary by hour (times as HH:MM), or a project plan across dates (view=timeline, dates as YYYY-MM-DD). Overlapping blocks sit side by side; it scrolls sideways when wide.

Open →
board

Columns of cards by stage, from a list: a sales pipeline, a task board, hiring stages, support tickets. Each column shows its count and an optional total; move=true lets people drag a card to another stage.

Open →
tree

A hierarchy from a flat list where each record names its parent: an org chart, folders, a budget by department. kind=list (default) is indented rows that open and close; kind=org is a top-down chart of boxes.

Open →
flow

Boxes joined by arrows, laid out automatically from a list of steps and where each leads: an approval process, a customer journey, a decision tree. Never give positions.

Open →
map

Canvas map with pin markers, data-driven country choropleths and proportional bubble maps. For data maps, give items plus geographic and numeric field names; Canvas handles colors, sizing and legends.

Open →
pin

A labelled point on a Canvas map. The optional detail is shown in a multiline hover tooltip.

Open →

Input

Controls people press, type into or drag. Most read and write a state name through bind=.

All on one page →
button

A pressable button that runs actions. Use emit: to tell the app what the user chose.

Open →
link

Pressable text for a secondary action, lighter than a button.

Open →
check

A checkbox that toggles a true/false state value.

Open →
switch

An on/off switch with a label, for settings that take effect right away.

Open →
radio

One choice among several. Give each radio in a group the same bind= and its own value=.

Open →
select

A field that opens a list to pick one option from, for choices like a department, status or filter; compact where radio buttons would take too much room. bind= holds the chosen option's value; with multiple=true, a list of the chosen values, for filters like regions to show.

Open →
date-picker

A field that opens a month calendar to pick one date, kept in bind= as YYYY-MM-DD text ("" for none), or with range=true a start and an end. For deadlines, bookings or report filters.

Open →
stepper

A number with minus and plus buttons, for small counts like a quantity.

Open →
slider

Picks a number in a range by dragging a handle, or with the arrow keys. Good for prices, distances and amounts.

Open →
input

A text field people type into, such as a name, an email, a search, a new item, or with lines= a note or a message. Each keystroke writes its bind= state, and required= and kind=email or number say what's wrong once it's been left.

Open →
segmented

Two to six short options in one track, one chosen, like Week, Month and Year, or Chart and Table. Show different content for each with if=.

Open →
menu

A button that opens a short list of actions, for what can be done to one item (edit, duplicate, delete) without a row of buttons. Each menu-item runs its own on=.

Open →
menu-item

Navigation

Screens, tabs, breadcrumbs and pagination.

All on one page →
screen

One screen of a multi-screen interface. Only one screen shows at a time: the first, until a button runs go:name or back.

Open →
tabs

A row of tabs that switches between sections. Only the selected tab's content is shown.

Open →
tab

One tab inside tabs: its label, and the content shown while it is selected.

Open →
breadcrumb

Where the user is, as a path like Shop / Shoes / Trail runners. Earlier steps can be pressed to go back.

Open →
pagination

Previous, next and page-number buttons for moving through pages of results. Show the current page's items with slice(rows, (page - 1) * 10, page * 10).

Open →

Feedback

Progress, loading placeholders and empty states.

All on one page →
progress

A horizontal bar showing how far a value is toward a maximum.

Open →
skeleton

A grey placeholder shown while content loads: lines of text, a block or a circle.

Open →
empty

A friendly message for when there is nothing to show, with an optional button to move on.

Open →
dialog

A panel over the screen for something that needs an answer or attention first: confirm a delete, a short form, one item's details. It opens when bind= is true, so start that state false and open it from a button, unless it should greet people as the screen opens; its × button, Escape and a press outside it close it.

Open →

SayShape v0.1 is an early prototype under the MIT License. Status · GitHub