Skip to content
RU
Scale
Density
Theme
Accent

Layout

Page header

The name of a screen, its explanation and the principal actions. One per screen — exactly as one <h1>.

The component

Runs

Every region scrolls by itself: the side navigation does not travel away while the table is being read.

Markup
<div class="inst-page-header">
  <div class="inst-page-header-main">
    <h1 class="inst-page-title">Runs</h1>
    <p class="inst-page-desc">Every region scrolls by itself: the side navigation does
      not travel away while the table is being read.</p>
  </div>
  <div class="inst-page-actions">
    <button class="inst-btn inst-btn--sm" type="button">Filters</button>
    <button class="inst-btn inst-btn--sm inst-btn--primary" type="button">Run</button>
  </div>
</div>

Contract

The inst-page-header-main wrapper is required: it holds the name and the explanation as one column with a gap of --space-2 and carries a flex: 1 1 20rem — the threshold below which the actions wrap under the heading rather than squeezing it into a column of one word.

The min-inline-size: 0 on it is not decoration: without it a long name with no spaces stretches the whole header and drives the actions past the edge.

What Why
An <h1> under inst-page-title The class gives the size rather than the level. The level is the work of the tag, and a screen reader reads exactly that
An inst-page-header-main as the wrapper Without it the name and the explanation become separate children of the row and line up side by side
A type="button" on the actions Otherwise inside a form they will submit it

Accessibility

The level of the heading One <h1> per document. It is not assigned automatically: it is set by the author of the markup
The measure of the explanation 68ch. A longer line is lost on the return to the start
Wrapping The header wraps by itself; at a 200% increase of type size the actions go under the heading rather than past the edge of the screen
Contrast The explanation is --text-secondary (4.5:1). --text-faint is not applied to text that gets read
Print The name and the explanation are printed, inst-page-actions is not: actions on paper are not actions
Order The actions stand after the heading in the markup and are traversed after it. order is not used

Anatomy

inst-page-actions is pushed to the far edge (margin-inline-start: auto) and wraps within itself. Keep one primary here: a screen where everything is primary has no primary at all — see the button.

The fourth action and the ones after it move into a menu. A strip of six buttons above a screen is read neither by eye nor from the keyboard.

Composition

Example

Run #4127 running

worldgen · started at 14:02

Markup
<div class="inst-page-header">
  <div class="inst-page-header-main">
    <h1 class="inst-page-title">Run #4127
      <span class="inst-badge" data-tone="running"><span class="inst-dot"></span>running</span></h1>
    <p class="inst-page-desc">worldgen · started at 14:02</p>
  </div>
  <div class="inst-page-actions">
    <button class="inst-btn inst-btn--sm inst-btn--danger" type="button">Stop</button>
  </div>
</div>

API

Classes
NameWhat it does
class
inst-page-headerThe container. A row that wraps, aligned to the top
inst-page-header-mainThe "name + explanation" column. The wrapping threshold is 20rem
inst-page-titleThe name of the screen. The size is --text-xl
inst-page-descThe explanation. --text-sm, --text-secondary, a measure of 68ch
inst-page-actionsThe actions. Pushed to the far edge, and they wrap
Tokens
NameValueWhere from
token
--gap-inlinevar(--space-4)base +14: density · scale
--pad-panelvar(--space-5)base +14: density · scale
--space-24pxone across every cell
--space-36pxone across every cell
--text-xl1.375rembase +4: scale
--text-sm0.875rembase +4: scale
--text-secondarylight-dark(var(--n-9), var(--n-5))one across every cell

Why the kit works this way — the constitution · Open source under MIT, github.com/keshon/instrument