Component

Surfaces and feedback

Nine surfaces carry everything Inline says to a writer. In-flow surfaces stay flat behind hairlines; shadow, scrim, and status color appear only for the moment they are needed.

Cards and containers

The card is the default white working surface: one bounded region for a draft summary, a question, or a settings group. Interactivity shows in the border, never as lift.

Monuments and public memory

Draft 2 · Saved 4 minutes ago

Removing a monument can reveal more about public memory than leaving it untouched.

Draft goals

Argue one claim and support it with local evidence.

Card surface · border line · radius 8 · inset 24 · compact 16 · hover border ink-400
job
Hold one group of related content on the paper canvas without adding depth.
anatomy
Optional header (title plus mono meta), body, optional footer actions, inside one hairline at radius.md.
variants
Default at inset.md 24px; compact at inset.sm 16px for dense rails; interactive, where the whole card is one link or button.
states
Flat at rest and on hover. An interactive card answers with a border of ink.400; focus uses the global ring. Never shadow, scale, or motion.
tokens
surface · border.default · radius.md · inset.md / inset.sm · hover border ink.400
accessibility
An interactive card is a single control with one accessible name; never nest a second target inside it.

One card is the exception: the margin question card is an annotation on the manuscript plane, so it stays square and is owned by Writing surfaces.

Feedback settings

Evidence and Clarity run on the next pass.

Nest with paper. Inside one bordered card, an inner region uses paper fill or a soft divider.

Feedback settings

Evidence and Clarity run on the next pass.

Borders on borders. A hairline card inside a hairline card reads as a mistake, not structure.

Overlays

Menus, popovers, and tooltips are transient tools on the overlay tier. They float above the writing plane, never dim it, and leave on outside click or Escape.

Menu

Lists actions for one control, then gets out of the way. It opens with the overlay motion recipe and closes on outside click and Escape.

Menu outer 6 · items 8 × 12 · radius 8 and 4 · shadow.overlay · fade + 4px rise · sm hover a row for the ink a04 wash; the active row holds ink-100
job
Offer the actions of one trigger in one place, briefly.
anatomy
White overlay surface with 6px outer padding; rows at 8px by 12px, radius.sm. A destructive row sits last, after an inset rule, in danger.600 text.
variants
Plain action list; list with one destructive item. Anything that holds content is a popover.
states
Row hover washes ink.a04, the active row ink.100. Opens on the overlay recipe (fade + 4px rise · sm · ease.out); closes on outside click and Escape; never dims the page.
tokens
surface · border.default · radius.md / radius.sm · shadow.overlay · z.overlay · ink.a04 · ink.100 · danger.600
accessibility
role="menu" with menuitem rows: arrow keys move, Enter activates, and focus returns to the trigger on close.

Popover

The same surface as the menu, holding content instead of commands. The dimensions legend is the canonical example: colored dots with written labels, so color never stands alone.

Dimensions
  • ArgumentThe claim you make
  • EvidenceWhat supports it
  • ReasoningHow parts connect
  • ClarityHow it reads
  • StrengthWhat already works
Popover max width 288 · inset 16 · radius 8 · shadow.overlay
job
Hold light content beside its trigger: a legend, a definition, a short explainer.
anatomy
White overlay surface, hairline, radius.md, inset.sm 16px, max width around 288px.
variants
Legend, definition, explainer. Commands belong in a menu; blocking decisions in a dialog.
states
Opens from its trigger on the overlay recipe; closes on outside click and Escape; never dims the page.
tokens
surface · border.default · radius.md · inset.sm · shadow.overlay · z.overlay
accessibility
The trigger carries aria-expanded and the popover follows it in DOM order; every colored dot pairs with a written label.

Tooltip

Names or clarifies a control, on hover and focus only. It never holds controls and is never required to operate anything.

Copy or export draft
Tooltip ink-900 · paper caption text · radius 4 · inset 6 × 8 · no arrow
job
Give a control its name or one clarifying line, then vanish.
anatomy
ink.900 surface, paper caption text, radius.sm, 6px by 8px inset, no arrow. The dark surface separates itself; no shadow.
variants
None. One size, one style.
states
Hidden at rest. Appears only on hover and focus after a short pause near 480ms; the fade itself runs duration.xs. Leaves on pointer-out, blur, or Escape.
tokens
ink.900 (bg.inverse) · text.inverse · size.caption · radius.sm · duration.xs
accessibility
role="tooltip" linked with aria-describedby; it repeats or extends a visible label, so nothing requires the tooltip to exist.

Dialogs

A dialog is the only blocking surface: one ink scrim, one decision, then back to the draft. Only one dialog exists at a time.

Leave this draft?

Your draft is saved. Feedback still running will be ready when you return.

Standard confirm primary last · Escape closes

Delete this draft?

This removes draft 2 and its feedback. There is no undo.

Destructive confirm danger button replaces the primary
job
Hold one blocking decision the writer must resolve before continuing.
anatomy
White panel at radius.lg 12 with shadow.dialog, inset.md 24px (inset.lg 32px from 640px), over a single ink scrim. Title is an h3, body is body.md in ink.600, actions right-aligned with the primary last.
variants
Standard confirm; destructive confirm swaps the primary for the danger button.
states
Focus is trapped while open. Escape closes unless the action is destructive mid-flight. On close, focus returns to the opener.
tokens
surface · radius.lg · shadow.dialog · inset.md / inset.lg · scrim bg.overlay · z.backdrop · z.dialog
accessibility
role="dialog" with aria-modal="true", labelled by its title. The focus trap and the focus return are part of the contract.

Status messaging

Two carriers share the four status families from color. The vocabulary is fixed: 100 wash, 200 border, 600 icon, 800 text, and never a filled surface.

Banner for state that persists, toast for confirmation that passes.

If the writer could reasonably ask whether it is still true, it is a banner.

Toast

Your draft is saved.
412 words will be read.
Feedback didn't come back.
Toast bottom right · z.toast · dismisses near 4s · timer pauses on hover and focus
job
Confirm an outcome that just happened, then pass.
anatomy
Overlay tier surface: white, hairline, radius.md, shadow.overlay, 12px by 16px inset. One line with a 16px icon, plus at most one quiet action.
variants
Success, info, danger, expressed by the leading icon (family 600) and label color (family 800) only. The surface never fills.
states
Enters on the overlay recipe, exits on exit. Auto-dismisses around 4 seconds; the timer pauses on hover and focus.
tokens
surface · border.default · radius.md · shadow.overlay · z.toast · icon.size.sm · status 600 / 800
accessibility
role="status": announced politely, never steals focus. Its action must also exist somewhere persistent, because the toast passes.

Banner

412 words will be read.
Your draft is saved.
The course title is missing.
Feedback didn't come back. Your draft is saved.
Banner wash 100 · border 200 · text 800 · icon 16 · inset 12 × 16
job
Explain a state that persists, at the place it applies.
anatomy
In-flow status surface: 100 wash, 200 border, 800 text, 16px icon in the family 600, radius.md, 12px by 16px inset. Holds one optional action.
variants
Info, success, warning, danger.
states
Static. It sits inside the content column, never fixed and never floating, and stays until the state changes.
tokens
status 100 / 200 / 600 / 800 · radius.md · icon.size.sm · shadow.none
accessibility
Icon plus words carry the meaning without color. Inserted dynamically it uses role="status"; reserve role="alert" for danger.

Loading and empty

Loading keeps the layout still. An empty region says what it is for, then offers the first step.

Skeleton

Ink-100 shapes hold the place of real content during a structural load. Shapes mirror the final layout, so nothing jumps when content lands. Inline waits use a written label such as Getting feedback… instead.

loading
02

What evidence shows how residents described that change at the time?

loaded
Skeleton ink-100 shapes · opacity pulse to 55% · lg alternate · no shimmer sweep
job
Hold the layout still during a structural load.
anatomy
ink.100 text bars at radius.xs and rects at radius.sm, composed to mirror the component they replace.
variants
Text bar and rect, composed per component. No generic block, no avatar circles for their own sake.
states
A quiet opacity pulse between 100% and about 55%, alternating on duration.lg as a linear waiting loop. No shimmer sweep. Under reduced motion the shapes sit static.
tokens
ink.100 · radius.xs / radius.sm · duration.lg
accessibility
Shapes are aria-hidden; the region carries aria-busy="true" and one visually hidden Loading label.

Empty state

An empty region states what the space is for, not what is missing, and offers one first step.

Feedback lives here

Get feedback and margin questions will appear beside your draft.

Empty state 48px well · paper fill · hairline · 24px icon ink-400 · h4 title · body-sm line · one action
job
Explain the purpose of an empty region and start its first use.
anatomy
Centered in its region: a 48px icon well (paper fill, hairline, radius.full, 24px icon in ink.400), an h4 title, one body.sm line in ink.600, one action.
variants
Primary action when the step is the obvious next move; secondary when it is optional.
states
Static. Replaced by content, never shown at the same time as a skeleton.
tokens
paper · border.default · radius.full · icon.size.lg · ink.400 · ink.600
accessibility
The title joins the page heading outline; the icon is decorative and hidden from assistive technology.

Rules

Eight decisions keep nine surfaces reading as one quiet system.

  1. Borders before shadows. An in-flow surface earns a hairline, never an elevation; shadow marks transient overlap only.
  2. Overlays never dim. Menus, popovers, tooltips, and toasts float on their own shadow; only a dialog gets the ink scrim.
  3. One dialog at a time. A dialog never opens a second dialog; resolve or cancel before anything else blocks.
  4. Status color never fills a surface. Washes stop at 100, toasts stay white, and 600/800 carry only the icon and the text.
  5. Toasts confirm, banners explain. A toast passes in about 4 seconds; a banner stays at its source until the state changes.
  6. Skeletons mirror real layout. Placeholder shapes match the component they replace, so loaded content lands without a jump.
  7. Nothing lives only in an overlay. Tooltips duplicate visible labels, toast actions exist somewhere persistent, and every menu has a keyboard path.
  8. Hover never lifts. Interactive cards and rows answer with border and wash, never with shadow, scale, or motion.