Buttons
A <button> or an <a role="button"> is already a button, with no class and no attribute. data-variant picks another look, data-size="sm" makes the small uppercase one, and a <menu> lays a row of them out.
Every piece is plain HTML plus at most one data attribute. Change the palette or the theme above and each one follows.
A <button> or an <a role="button"> is already a button, with no class and no attribute. data-variant picks another look, data-size="sm" makes the small uppercase one, and a <menu> lays a row of them out.
<mark> is a chip: small uppercase text on a flat colour. data-tone picks which colour, and each tone already pairs with text that reaches 4.5:1 on it.
Draft Deployed Link missing Review 182 pages
<code> is inline code and <kbd> is a key. Both are set in IBM Plex Mono on a tinted background, in every type set.
Run atlas build --watch and the site rebuilds on save. Press ⌘ K to open the command palette.
One job written for several tools: npm, pnpm, cargo. A <figure data-tabs> holding a run of <pre> shows one at a time, under a row of tabs.
npm i s72
pnpm add s72
cargo add s72
A block of code with its language named in the caption, numbers down the side and a Copy button. data-lang picks the colouring and data-mark picks the lines to call out.
[build]
out = "_site"
watch = true
drafts = false
[links]
check = true
ignore = ["mailto:", "tel:"]
Watch mode rebuilds on save. Drafts stay out of the output until the flag flips.
A patch, read as a code view. Lines that start with + or - take a tint across the line and its gutter cell, and @@ marks where the hunk starts.
@@ -2,6 +2,7 @@
:where([role="tablist"]){display:flex;flex-wrap:wrap;gap:.25rem}
-:where([data-variant="tab"]){color:var(--s72-fg-2);padding:.6rem}
+:where([data-variant="tab"]){color:var(--s72-fg-2);padding:.6rem 1rem}
+:where([data-variant="tab"][aria-selected="true"]){color:var(--s72-fg)}
:where([role="tabpanel"]){font-size:var(--s72-s2)}
One command in a bar of its own, with a Copy button at the end. Put the command in a <code> and nothing else; the $ in front is drawn by the stylesheet, so it never reaches the clipboard.
cd ~/code/atlas && atlas build --watch
A <fieldset data-segmented> of radio labels: one choice from a short list, shown as a strip. The <legend> is hidden on screen but read aloud.
A plain <input type="range">. s72.js keeps --s72-fill in step with the value, so the filled part of the track always matches the handle.
A checkbox with role="switch" becomes a switch. It is a real checkbox, so it submits with the form and reads as a switch to a screen reader.
A plain <table> is a log-style table: a solid head, hairline rows and room for chips. Three attributes on cells cover the usual needs.
| Entry | Kind | Record | Time |
|---|---|---|---|
| 00001 | page | Rendered guide/index.md | 14 ms |
| 00002 | missing | Link not found: /guide/old | — |
| 00003 | result | 182 built, 0 failed | 1.94 s |
A session rather than a file. Lines that open with $ are what was typed; the rest is what came back. The well is dark in both themes, as a terminal is.
$ atlas build
182 pages in 1.9 s
$ atlas serve
listening on http://localhost:1313
A <footer> as a direct child of <body> sits under a top rule. With plain children it is one row; with <nav> children it becomes columns.
data-grid turns any block into a row of equal columns. Cards in it stretch to the same height, so side-by-side columns start and end together.
182 built this morning, one with a warning.
FreshThree point at a guide that no longer exists.
Needs workImages are copied as they are until the resize step lands.
Planned<section data-hero> is a colour field at the top of a page. Children stack on the left; an <aside> sits on the right, level with them.
Static site toolNo configv1.4
atlas renders a folder of Markdown into a site, watches it while you write, and deploys it in one command.
atlas build --watch
A <header> as the first child of a <section> is the section heading: an <h2> on the left and a line of standfirst on the right, above a rule.
Every page atlas rendered this morning, newest first, with the time each one took.
182 pages, one warning, 1.94 seconds.
data-layout="sidebar" puts a sticky navigation column beside the content. It stacks under 760px, where the sidebar stops being sticky.
Markdown files in content/ become pages. The folder they sit in becomes the path.
data-stack is a vertical list with the standard gap. Use it wherever two or three blocks should sit above each other with the same space as everything else on the page.
A <header> as a direct child of <body> is the page's top bar. Its first <a> is the brand and a <nav> holds the links.
data-avatar on a <span> of initials or on an <img> makes a round badge. data-avatars on a wrapper overlaps a group of them.
AR PS CN
A callout is a lasting note beside the text: a <strong> title, a paragraph, and a short colour marker down its left edge. Use a toast instead for the result of an action.
An <article> inside a grid is a card. A closing <small> is pushed to the bottom, so a row of cards has its labels on one line however long the text above is.
Every file in content/ becomes a page. The folder it sits in becomes the path.
Layouts live in layouts/. A page picks one in its front matter.
Images are copied as they are. Resizing and fingerprinting come next.
Planneddata-empty is the slot that holds nothing yet: a heading, a line that says what would appear here, and at most one action.
When a page points at something that is not there, it shows up here with the page that linked it.
An <img> as the first child of a card in a grid runs to the card's edges and takes a 16:9 crop. Everything after it is an ordinary card.
Resize and fingerprint images as part of the build.
PlannedA card without an image sits beside one with it and ends on the same line.
StableA <ul data-list> is a bordered list of rows. Each row holds a <span> of a name and its meta on the left, and one thing on the right: a chip, a button or a time.
A <dl data-pairs> is a two-column list of keys and values: an uppercase label on the left, the value on the right. It is the quietest way to put facts in a card.
~/code/atlasThe generated pattern goes on edges and backgrounds, never in corners. data-edge puts a band on one side of a block; data-fade puts the pattern behind the content and fades it out where the text sits.
How to lay out a site and write a template.
Updated todayEvery command and flag atlas understands.
v1.4A <figure data-policy> is a list of rules with a verdict against each one. data-title prints the title bar across the top, the <dl> inside holds the pairs, and a closing <figcaption> is the footnote.
A pricing card is an ordinary card with a <data> element for the price. The value attribute holds the number, the text holds what the reader sees.
atlas deployA <blockquote> is set in the display face at reading size, with a colour rule down its left edge. A <footer> or <cite> inside it is the attribution.
The page reloads before I reach the browser, so writing the site feels like editing a document.
A card of three parts: a <small> label, a <strong> value and a <span> of context. Four of them in a data-grid="4" make the row of numbers at the top of a dashboard.
A ticket is a full-width card with a stub down one side. The stub carries the pattern. Inside data-tickets, every other ticket mirrors, so the stubs alternate sides and the text follows.
182 pages rendered in 1.94 seconds, one warning.
Every one of them is /guide/old-path, left over from the rename.
An <ol data-timeline> is a vertical run of events down a rule, each with a dot. data-dot colours the dot with one of the tones.
atlas in ~/code/atlas.
A page pointed at a missing guide.
182 built, 0 failed.
data-tone turns any block into a colour panel. The six tones carry meaning: go for allowed, stop for denied, info for a notice, earth for a result, soft for a quiet accent and ink for the darkest.
182 pages went live at 14:31.
Three pages point at /guide/old.
atlas rebuilds whenever a source file is saved.
An <ol> inside a <nav> is a breadcrumb trail. The last item is the page itself, marked with aria-current="page" and not linked.
A <details data-menu> is a dropdown: the <summary> is the trigger and the <menu> inside is the list. It closes on Escape, on a click outside, and after any item is chosen.
data-navbar on the page's top bar folds the nav behind a Menu button under 560px. Above that width it is an ordinary top bar.
<nav data-pages> is a row of page links. The current page is aria-current="page"; a <span> stands in for a gap in the run.
An <ol data-steps> is a numbered run of stages across the page. data-state="done" ticks a finished step; aria-current="step" marks the one in hand.
One panel shows at a time. The tablist is a row of buttons; the panels follow it, one per button, in order.
Built 14:02 from ~/code/atlas. 182 pages, 1 warning.
Content in content/. Templates in layouts/. Output in _site/.
1,204 pages. The slowest is guide/index.md, at 94 ms.
<progress> shows how far a task has run. <meter> shows where a value sits in a range, and colours itself from low, high and optimum.
data-spinner is a small turning ring for work that is under way. data-skeleton is a grey bar standing in for content that has not arrived.
Rendering pages…
A stamp lands on a panel after the reader acts there. Nothing shows before the action. The page needs data-stamps on <html> for any of it to appear.
Stamping records that someone read the policy and signed it off.
A toast says what just happened and then leaves. It stacks at the bottom right and goes after four seconds. Use a callout instead for a note that should stay.
<menu data-group> joins a row of buttons into one block. Use aria-pressed to mark which one is on.
Plain <input type="checkbox"> and <input type="radio">, drawn to match the rest of the library. Group them in a <fieldset> with a <legend>.
A text field with its suggestions under it. The suggestions are a plain <datalist>, so the field still offers them where the script never runs.
A <mark> inside a button is a count badge. A <button data-remove> inside a <mark> turns the chip into a tag the reader can take off.
rust macos
<input type="date">, "time" and "datetime-local" take the same border, fill and height as a text field. No attribute, no script: the browser's own field and picker do the work.
A dashed well that takes files by drag or by click. The <input type="file"> inside it is the real control, so the form submits what the well holds without any help.
<label data-field> stacks a label, a control and a hint. aria-invalid="true" on the control turns the field into an error, and the hint becomes the message.
<input type="file"> and <input type="search"> are styled as they are. The file input's own button takes the button fill; the search input takes the pill corner.
<label data-chip> wraps a checkbox in a pill. Several of them make a row of filters that toggle on and off, with no JavaScript behind it.
One long form, read one <fieldset> at a time. Without the script every step shows at once and the form still submits, so the steps are a way through the form rather than the form itself.
Two native sliders over one track, for a span rather than a number. Each handle is a real <input type="range">, so each one is reachable, draggable and typeable by itself.
An <ol data-bars> is a bar chart. Each item carries its height in --s72-v from 0 to 1, its number in data-value and its axis label as the text.
data-count on an element makes the first number in its text count up from zero, once, when it scrolls into view. Separators, decimals and the words around the number are kept.
<input type="search" data-filter="#id"> hides the rows of a table or the items of a list whose text does not hold what was typed. An <output> pointed at the input reads "12 of 40".
An <ol data-heatmap> is a grid of days: seven rows, one column a week, filling column by column. data-level="0..4" sets how dark a day is and data-tip says what it means.
data-sort on a table makes every column head with text a sort button. Click once to sort up, again to sort down; the rows slide to their new places so a row can be followed.
| Repository | Message | Commits | Last push | Open |
|---|---|---|---|---|
| atlas | Cap the retry budget at four attempts | 18 | ||
| ledger | Tag 2.4 and write the release note | 6 | ||
| hummingbird | Revert the queue change that broke the tests | 11 |
<details> elements grouped in a data-accordion. A shared name makes them exclusive, so opening one closes the rest.
Pages render in parallel, and a watch run rebuilds only what changed. A thousand pages take about two seconds.
Yes. Put them in layouts/ and atlas build picks them up.
In the project's _site folder, or wherever you point --out.
A <dialog data-commands> is the ⌘K palette: a search box over a menu of commands. Typing filters the list, the arrows move the active option and Enter presses its button.
A native <dialog>, opened by a button with data-open="#id" and closed by anything with data-close, by Escape or by a click on the backdrop.
A drawer is a dialog pinned to one edge of the screen, full height. It slides in from that edge, so the reader can see where it came from and where it goes back.
A native popover: popovertarget on the button and popover plus data-popover on the panel. The browser opens and closes it; s72.js only decides where it lands.
A. Reyes
Signed in on this machine.
data-tip="Text" on any element shows a short label above it on hover and on keyboard focus. Keep it to a few words: it is drawn as one line that does not wrap.
The band at the foot of a page that asks for the click. A colour panel with the pattern along its top edge, the words on the left and the buttons on the right.
A stylesheet and a script, no build step and no runtime dependencies.
Three or four claims side by side, each one a card under a rule. It is the page's own grid, fixed at three columns, with no icons: the words carry the point.
Two files, a stylesheet and a script. Copy them in and write HTML.
A table is a table. Variants are data attributes, never classes.
Palette, type, pattern and theme all sit on the html element.
A band of the people already using the thing. One wrapping row, centred, muted until the reader points at one.
Quotations in a row of columns. Each one is the page's own <blockquote>, set on a card, with its <footer> on the bottom edge.
We dropped eleven thousand lines of CSS and the site looked better.
I wrote the whole docs site in HTML. No components, no props, no build.
The first library my designer read without asking me to translate it.