Menu


Log


What a program prints as it runs: wrapped lines in a well that keeps the newest in view until the reader scrolls up.

Customize the preview


Choices
Show
View
Preview outputRunning
› npm run build
  vite v8.0.2 building for production…
  ✓ 412 modules transformed.
  dist/index.html                  0.62 kB
  dist/assets/index-4f1c2a.css    38.40 kB
  dist/assets/index-9b7e11.js    184.12 kB
Preview output: Running

Options


Log options
ChoiceValuesDefaultWhat it does
statesmbk-log--state-<value>runningfinishedrunning
Running while the program prints, finished once it stops. The badge says which, and a screen reader hears when it starts and when it ends.

Partssmbk-log__headersmbk-log__titlesmbk-log__statussmbk-log__wellsmbk-log__scrollsmbk-log__notesmbk-log__dividersmbk-log__linessmbk-log__jumpsmbk-log__announcement

Examples


Usage

A running log: its title, a Running badge, a note of what was left out and the newest line in view.

Build outputRunning

40 earlier lines left out


› npm run build
  vite v8.0.2 building for production…
  ✓ 412 modules transformed.
  dist/index.html                  0.62 kB
  dist/assets/index-4f1c2a.css    38.40 kB
  dist/assets/index-9b7e11.js    184.12 kB
Build output: Running

Live output

Press Run the build: lines arrive while the newest stays in view, until you scroll up. A screen reader hears the start and the end, not the lines.

Live build outputWaiting

Waiting for output…

Live build output: Waiting

Waiting

Nothing printed yet: the badge says Waiting and the well says so too.

Deploy outputWaiting

Waiting for output…

Deploy output: Waiting

Finished

The badge turns to Finished, and a screen reader hears that the output ended.

Test outputFinished

40 earlier lines left out


› npm run build
  vite v8.0.2 building for production…
  ✓ 412 modules transformed.
  dist/index.html                  0.62 kB
  dist/assets/index-4f1c2a.css    38.40 kB
  dist/assets/index-9b7e11.js    184.12 kB
  ✓ built in 4.81s
Test output: Finished

Scrolled up

The reader scrolled up, so the log stopped following; "Jump to latest" brings the newest line back and follows again.

Upload outputRunning
› npm run upload
  uploaded pages/guide-01.html  (1.2 kB)
  uploaded pages/guide-02.html  (1.6 kB)
  uploaded pages/guide-03.html  (2.0 kB)
  uploaded pages/guide-04.html  (2.4 kB)
  uploaded pages/guide-05.html  (2.8 kB)
  uploaded pages/guide-06.html  (3.2 kB)
  uploaded pages/guide-07.html  (3.6 kB)
  uploaded pages/guide-08.html  (1.2 kB)
  uploaded pages/guide-09.html  (1.6 kB)
  uploaded pages/guide-10.html  (2.0 kB)
  uploaded pages/guide-11.html  (2.4 kB)
  uploaded pages/guide-12.html  (2.8 kB)
  uploaded pages/guide-13.html  (3.2 kB)
  uploaded pages/guide-14.html  (3.6 kB)
  uploaded pages/guide-15.html  (1.2 kB)
  uploaded pages/guide-16.html  (1.6 kB)
  uploaded pages/guide-17.html  (2.0 kB)
  uploaded pages/guide-18.html  (2.4 kB)
  uploaded pages/guide-19.html  (2.8 kB)
  uploaded pages/guide-20.html  (3.2 kB)
  uploaded pages/guide-21.html  (3.6 kB)
  uploaded pages/guide-22.html  (1.2 kB)
  uploaded pages/guide-23.html  (1.6 kB)
  uploaded pages/guide-24.html  (2.0 kB)
  uploaded pages/guide-25.html  (2.4 kB)
  uploaded pages/guide-26.html  (2.8 kB)
  uploaded pages/guide-27.html  (3.2 kB)
  uploaded pages/guide-28.html  (3.6 kB)
  uploaded pages/guide-29.html  (1.2 kB)
  uploaded pages/guide-30.html  (1.6 kB)
  uploaded pages/guide-31.html  (2.0 kB)
  uploaded pages/guide-32.html  (2.4 kB)
  uploaded pages/guide-33.html  (2.8 kB)
  uploaded pages/guide-34.html  (3.2 kB)
  uploaded pages/guide-35.html  (3.6 kB)
  uploaded pages/guide-36.html  (1.2 kB)
Upload output: Running

Long lines

Lines wrap at the well's width, so nothing scrolls sideways, on a phone too.

Install outputRunning
› npm ci
  npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value.
  added 812 packages in 9s
Install output: Running

Guidelines


Purpose

Shows what a program prints as it runs, such as a build, an upload or a job, and keeps it after the program finishes. The newest line stays in view while it prints, unless the reader scrolls up to read.

When to use

  • For the output of a build, an upload, a test run or a script, while it runs and after.
  • For any text that arrives line by line and is read as it comes.

When not to use

  • For code a reader copies or studies. Use a code block.
  • For messages a reader must act on. Use an alert or a toast.
  • For a list of past events with times and people. Use a timeline.

Usage rules

Do

  • Name the log for what printed it.
  • Say in the note what was left out when you drop old lines.
  • Set state to finished when the program stops.

Don't

  • Announce each line.
  • Color lines to mean errors with no words.
  • Use a log for code to copy.
Cut outputRunning

120 earlier lines left out


  dist/index.html                  0.62 kB
  dist/assets/index-4f1c2a.css    38.40 kB
  dist/assets/index-9b7e11.js    184.12 kB
Cut output: Running
Do

Say what was left out when a long output is cut, so the reader knows the start is missing.

Bare outputRunning
  dist/index.html                  0.62 kB
  dist/assets/index-4f1c2a.css    38.40 kB
  dist/assets/index-9b7e11.js    184.12 kB
Bare output: Running
Don't

Cutting lines without a note makes the output look as if it starts in the middle.

Anatomy

  • The block: the header, then the well.
  • The header part: the title part in a medium label style, then the status part, a small soft badge that says Waiting, Running or Finished.
  • The well part, the sunken surface inside a subtle hairline with the small container corners, no taller than a long list.
  • The scroll part, the area inside the well that scrolls.
  • The note part, an optional line in a small body style and the subtle text color, such as "40 earlier lines left out", with the divider part under it.
  • The lines part, the output in the code style, left to right, wrapping at the well's width. Before anything is printed it says "Waiting for output…" in the subtle text color.
  • The jump part, a small ghost "Jump to latest" button at the well's foot, there only while the reader is scrolled up.
  • The announcement part, a status line a screen reader hears, in the page but not drawn.

Behavior

Set state to running while the program prints and to finished once it stops; the badge follows, in the info color while running and the success color when finished. With no lines yet it says Waiting.

While running, the well keeps the newest line in view as lines arrive and as the lines rewrap. When the reader scrolls up, the log stops following, so the lines they are reading stay still, and "Jump to latest" appears at the well's foot. Pressing it goes to the newest line at once, follows again and puts the keyboard back in the well; scrolling back to the end does the same. A page can also hold the following itself with following and onFollowingChange.

Lines wrap at any point, so nothing scrolls sideways, on a phone too. Keep the lines you pass to a few hundred; for more, drop the oldest and say so in the note.

Accessibility


What it does for you

  • The well is one stop for the Tab key and a region named by the title (or by aria-label when the log has no title), so the arrow keys scroll it. It shows the focus ring inside its edge, drawn in the system's highlight color in a forced-color mode.
  • The lines are never read out one by one: hundreds of lines would drown everything else. A screen reader hears when the log starts printing ("Build output: Running") and when it finishes ("Build output: Finished").
  • status adds the page's own short status, such as "120 lines printed", heard when it changes.
  • Every word it says by itself, such as the state on its badge and the jump button, keeps its English unless the page gives its own.

What you must do

  • Name the log for what printed it, with a title or an aria-label. Without a name the wrapper warns in development.
  • Change status seldom: every few seconds at most.
  • Don't say an error by the color of a line alone; say it in words in the output, or in an alert beside the log.
  • Give the state's words and the jump button's label in the page's own language when the page is not in English.

How to test

  • With the keyboard, Tab reaches the log's well once, with the focus ring inside its edge. The arrow keys scroll it, and Home and End jump to the first and last lines.
  • Scroll up while it runs: the log stops following, and "Jump to latest" appears at the well's foot. Press it with Enter or Space: the newest line shows and the keyboard is back in the well.
  • With a screen reader, the log is read as a region by its title, and it announces "Running" and "Finished" but not each line.
  • With text at 200% and the page 320 pixels wide, the lines wrap and nothing scrolls sideways.
  • In a forced-color mode, the focus ring around the well is visible.

Keyboard

Log keys
KeyWhat it does
Tab
Moves focus to the well, which is one stop.
Down ArroworUp Arrow
Scrolls the lines.
HomeorEnd
Scrolls to the first or last line.
EnterorSpace
On "Jump to latest", goes to the newest line, follows again and puts the keyboard back in the well.

Source


The files the log is made of. Its folder on GitHub (opens in a new tab) holds them with its wrapper and its document.

Stylesheet
log.css
/* smbk-log — Log. Figma "Log" 7118:1670 (State: Empty, Running, Finished, Scrolled up; Header boolean).
 * What a program prints as it runs: a header with the log's title in Label MD and a small soft badge that
 * says Waiting, Running or Finished; then the well, the sunken surface inside a subtle hairline with the
 * small container corners, holding an optional note ("40 earlier lines left out") over a divider and the
 * lines in Code MD, which wrap so nothing scrolls sideways. The well is no taller than a long list and
 * scrolls inside itself; while the reader is scrolled up, "Jump to latest" waits at its foot. */

.smbk-log {
  box-sizing: border-box;
  /* Holds the status line, which is out of sight, inside the log rather than wherever the page would put it. */
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--smbk-space-stack-sm);
  width: 100%;
  color: var(--smbk-color-text-default);
}

.smbk-log__header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--smbk-space-inline-sm);
}

.smbk-log__title {
  color: var(--smbk-color-text-default);
  font-family: var(--smbk-typography-label-md-font-family);
  font-size: var(--smbk-typography-label-md-font-size);
  font-weight: var(--smbk-typography-label-md-font-weight);
  line-height: var(--smbk-typography-label-md-line-height);
  letter-spacing: var(--smbk-typography-label-md-letter-spacing);
  text-transform: var(--smbk-typography-label-md-text-transform);
}

.smbk-log__well {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  max-height: var(--smbk-size-list-max-height);
  overflow: hidden;
  border: var(--smbk-border-width-hairline) solid var(--smbk-color-border-subtle);
  border-radius: var(--smbk-radius-container-sm);
  background: var(--smbk-color-surface-sunken);
}

/* The well's ring when its scrolling area has the keyboard, drawn inside its edge. */
.smbk-log__well:has(.smbk-log__scroll:focus-visible) {
  outline: var(--smbk-focus-ring-width) solid var(--smbk-color-border-focus);
  outline-offset: calc(-1 * var(--smbk-focus-ring-width));
}

.smbk-log__scroll {
  box-sizing: border-box;
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: var(--smbk-space-stack-sm);
  min-height: 0;
  padding: var(--smbk-space-inset-lg);
  overflow-x: hidden;
  overflow-y: auto;
  outline: none;
  /* The system's scrollbar: thin, in the subtle border color, on a clear track. */
  scrollbar-width: thin;
  scrollbar-color: var(--smbk-color-border-subtle) transparent;
}

/* Figures of one width, so a count that grows as the program prints ("40 earlier lines left out") never moves the
   words after it. */
.smbk-log__note {
  margin: 0;
  color: var(--smbk-color-text-subtle);
  font-family: var(--smbk-typography-body-sm-font-family);
  font-size: var(--smbk-typography-body-sm-font-size);
  font-weight: var(--smbk-typography-body-sm-font-weight);
  line-height: var(--smbk-typography-body-sm-line-height);
  letter-spacing: var(--smbk-typography-body-sm-letter-spacing);
  font-variant-numeric: tabular-nums;
}

.smbk-log__divider {
  flex-shrink: 0;
}

/* The lines: the code style, always left to right, wrapping at any point so a long line never runs past
   the well. */
.smbk-log__lines {
  margin: 0;
  color: var(--smbk-color-text-default);
  font-family: var(--smbk-typography-code-md-font-family);
  font-size: var(--smbk-typography-code-md-font-size);
  font-weight: var(--smbk-typography-code-md-font-weight);
  line-height: var(--smbk-typography-code-md-line-height);
  letter-spacing: var(--smbk-typography-code-md-letter-spacing);
  text-transform: var(--smbk-typography-code-md-text-transform);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  direction: ltr;
  text-align: left;
}

/* Nothing printed yet: the waiting words in the subtle text color. */
.smbk-log__lines--empty {
  color: var(--smbk-color-text-subtle);
}

.smbk-log__jump {
  display: flex;
  flex-shrink: 0;
  justify-content: flex-end;
  padding: 0 var(--smbk-space-inset-lg) var(--smbk-space-inset-lg);
}

/* What changed, for a screen reader: in the page, not drawn. */
/* .smbk-log__announcement: hidden from view, kept for screen readers and the keyboard, by the shared rule in visually-hidden/visually-hidden.css. */
.smbk-log__announcement {
  clip-path: inset(50%);
}

/* ---- high contrast (forced colors) ---- */

@media (forced-colors: active) {
  .smbk-log__well:has(.smbk-log__scroll:focus-visible) {
    outline-color: Highlight;
  }
}
Tokens it reads
Log tokens
Token and CSSValuePreviewFoundation
space.stack.sm--smbk-space-stack-smcomfortable: 8pxcompact: 6pxchanges with densitySpacing
color.text.default--smbk-color-text-defaultlight: #232527dark: #e7ebf0changes with themeColor
space.inline.sm--smbk-space-inline-smcomfortable: 6pxcompact: 4pxchanges with densitySpacing
typography.label-md--smbk-typography-label-md-font-family--smbk-typography-label-md-font-size--smbk-typography-label-md-font-weight--smbk-typography-label-md-line-height--smbk-typography-label-md-letter-spacing--smbk-typography-label-md-text-transformfontFamily: Geist, Geist Fallback, system-ui, sans-seriffontSize: 14pxfontWeight: 500lineHeight: 1.4letterSpacing: 0px

The quick brown fox

Typography
size.list.max-height--smbk-size-list-max-height320pxSize
border-width.hairline--smbk-border-width-hairline1pxBorder width
color.border.subtle--smbk-color-border-subtlelight: #c4cdd8dark: #2d3237changes with themeColor
radius.container.sm--smbk-radius-container-sm8pxRadius
color.surface.sunken--smbk-color-surface-sunkenlight: #373d430ddark: #00000066changes with themeColor
focus.ring.width--smbk-focus-ring-width2pxFocus
color.border.focus--smbk-color-border-focuslight: #cc0d0ddark: #f34336changes with themeColor
space.inset.lg--smbk-space-inset-lgcomfortable: 12pxcompact: 8pxchanges with densitySpacing
color.text.subtle--smbk-color-text-subtlelight: #4e555edark: #9ba5b1changes with themeColor
typography.body-sm--smbk-typography-body-sm-font-family--smbk-typography-body-sm-font-size--smbk-typography-body-sm-font-weight--smbk-typography-body-sm-line-height--smbk-typography-body-sm-letter-spacing--smbk-typography-body-sm-text-transformfontFamily: Geist, Geist Fallback, system-ui, sans-seriffontSize: 14pxfontWeight: 400lineHeight: 1.5letterSpacing: 0px

The quick brown fox

Typography
typography.code-md--smbk-typography-code-md-font-family--smbk-typography-code-md-font-size--smbk-typography-code-md-font-weight--smbk-typography-code-md-line-height--smbk-typography-code-md-letter-spacing--smbk-typography-code-md-text-transformfontFamily: Geist Mono, Geist Mono Fallback, ui-monospace, monospacefontSize: 14pxfontWeight: 400lineHeight: 1.6letterSpacing: 0px

The quick brown fox

Typography
Manifest
log.manifest.json
{
  "name": "log",
  "block": "smbk-log",
  "summary": "What a program prints as it runs: wrapped lines in a well that keeps the newest in view until the reader scrolls up.",
  "adapt": "css",
  "axes": {
    "state": {
      "values": [
        "running",
        "finished"
      ],
      "default": "running",
      "description": "Running while the program prints, finished once it stops. The badge says which, and a screen reader hears when it starts and when it ends."
    }
  },
  "flags": {},
  "parts": [
    "header",
    "title",
    "status",
    "well",
    "scroll",
    "note",
    "divider",
    "lines",
    "jump",
    "announcement"
  ],
  "figmaNodeId": "7118:1670"
}