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
Removing a monument can reveal more about public memory than leaving it untouched.
Draft goals
Argue one claim and support it with local evidence.
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.md24px; compact atinset.sm16px 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 borderink.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
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.
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, indanger.600text. - variants
- Plain action list; list with one destructive item. Anything that holds content is a popover.
- states
- Row hover washes
ink.a04, the active rowink.100. Opens on theoverlayrecipe (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"withmenuitemrows: 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.
- ArgumentThe claim you make
- EvidenceWhat supports it
- ReasoningHow parts connect
- ClarityHow it reads
- StrengthWhat already works
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.sm16px, 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
overlayrecipe; 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-expandedand 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.
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.900surface, 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 witharia-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.
primary last · Escape closes
Delete this draft?
This removes draft 2 and its feedback. There is no undo.
danger button replaces the primary
- job
- Hold one blocking decision the writer must resolve before continuing.
- anatomy
- White panel at
radius.lg12 withshadow.dialog,inset.md24px (inset.lg32px from 640px), over a single ink scrim. Title is an h3, body isbody.mdinink.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· scrimbg.overlay·z.backdrop·z.dialog- accessibility
role="dialog"witharia-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.
If the writer could reasonably ask whether it is still true, it is a banner.
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
overlayrecipe, exits onexit. 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· status600/800- accessibility
role="status": announced politely, never steals focus. Its action must also exist somewhere persistent, because the toast passes.
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"; reserverole="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.
What evidence shows how residents described that change at the time?
ink-100 shapes · opacity pulse to 55% · lg alternate · no shimmer sweep
- job
- Hold the layout still during a structural load.
- anatomy
ink.100text bars atradius.xsand rects atradius.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.lgas 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 carriesaria-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.
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 inink.400), an h4 title, onebody.smline inink.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.
- Borders before shadows. An in-flow surface earns a hairline, never an elevation; shadow marks transient overlap only.
- Overlays never dim. Menus, popovers, tooltips, and toasts float on their own shadow; only a dialog gets the ink scrim.
- One dialog at a time. A dialog never opens a second dialog; resolve or cancel before anything else blocks.
- Status color never fills a surface. Washes stop at 100, toasts stay white, and 600/800 carry only the icon and the text.
- Toasts confirm, banners explain. A toast passes in about 4 seconds; a banner stays at its source until the state changes.
- Skeletons mirror real layout. Placeholder shapes match the component they replace, so loaded content lands without a jump.
- Nothing lives only in an overlay. Tooltips duplicate visible labels, toast actions exist somewhere persistent, and every menu has a keyboard path.
- Hover never lifts. Interactive cards and rows answer with border and wash, never with shadow, scale, or motion.