Skip to content

COMPONENT

Terminal

Commands a reader is meant to run, with a way to take them. Press COPY, then paste it somewhere: what lands is the source, not what you can see.

Two lines and a square in the corner

terminal-copy pins the control inside the box, top right, at --ds-radius-control like every other control. Both classes are required: btn brings the fill, the border, the hover and the focus ring, and this adds where it sits and what shape it is. The button is hidden in the markup and the directive unhides it, so it exists exactly when it can do something. With no script the text is still selectable, which is what everybody did before clipboards were scriptable.

chmod +x thing_0.9.0_linux_amd64.AppImage
./thing_0.9.0_linux_amd64.AppImage
HTML
<!-- The word is on the button's accessible name, not in it: `x-ds-copy` writes
     `aria-label` the moment the button has a child, so the icon survives. The
     library ships no glyphs β€” this clipboard is the book's own. -->
<div class="terminal" x-ds-copy data-label-copy="COPY" data-label-done="COPIED" style="width:100%">
  <pre class="terminal-body"><code>chmod +x thing_0.9.0_linux_amd64.AppImage
./thing_0.9.0_linux_amd64.AppImage</code></pre>
  <button class="btn terminal-copy" type="button" hidden>
    <svg class="icon icon-sm" viewBox="0 0 24 24" aria-hidden="true">
      <path fill-rule="evenodd" d="M9 2h9a3 3 0 0 1 3 3v11h-2V5a1 1 0 0 0-1-1H9V2Z"></path>
      <path fill-rule="evenodd" d="M3 8a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8Zm2 0v12h10V8H5Z"></path>
    </svg>
  </button>
</div>

Why the word is not in the button

A square cannot hold COPY, so the word moves to the accessible name. x-ds-copy decides by looking: an empty button gets the word written into it, exactly as every caller before this did, and a button with an icon in it keeps the picture and gets the word as its aria-label. Forget the icon and you get a square with COPY spilling out of it β€” a loud failure rather than an empty square nobody can press with confidence.

The copied moment needs the same treatment, because a picture cannot change its own word. data-ds-copied goes on the button for the window the label used to change in, and .terminal-copy[data-ds-copied] fills it with the accent. Press it and watch. The glyph is the book's own β€” the library ships no glyphs, deliberately, so that a consumer's icons are a consumer's decision.

Leave terminal-copy off and the button lands under the box, in the flow, which is what this component did until Greg looked at one in a download card and asked for the corner instead. Both still work; the pinned one is the one to reach for when the box is the whole of what the reader is looking at.

Reference

Read from components/terminal.css when this page was built, so it cannot fall behind the stylesheet.

CLASSES.terminal.terminal-body.btn.terminal-copy
SETTINGSSet the first on one element; a theme sets the second for all of them.--terminal-shadow β€” falls back to --ds-shadow-well--terminal-copy β€” falls back to --ds-terminal-copy
READS--ds-accent--ds-accent-deep--ds-focus-ring--ds-font-display--ds-font-features--ds-gap-tight--ds-ground--ds-hairline--ds-ink-on-accent--ds-pad-card--ds-radius-control--ds-radius-field--ds-rule--ds-text-ui

Notes

IT IS NOT A CODE BLOCK

The difference is what the reader is meant to do. A code block shows source: something to read, and to copy only if you happen to want it. This shows a command somebody is about to type into their own machine. That earns the accent ink, because the line is the instruction rather than an illustration of one, and it earns a copy button, because retyping a path by hand is where the mistake happens.

IT WRAPS WHERE THE CODE BLOCK SCROLLS

The opposite default, on purpose. A code block scrolls because at the reading measure a scrolling line is easier to follow than a folded one. A terminal line is a path, and a path in a card is longer than the card, so there is no reading measure here β€” only a column, and a reader dragging a box sideways to see the end of a filename they are about to type is the failure this exists to avoid.

Safe because a soft wrap is not a broken command: pre-wrap keeps the newlines that are in the text and adds none of its own. Measured on the code block's page, an 84-character command drawn over eight lines copies back byte for byte with zero newlines in it.

ONE VOICE, NO HIGHLIGHTING

The ink is --ds-accent and there is no syntax palette here, deliberately. A shell transcript is one voice, and colouring parts of it implies a grammar the reader then goes looking for.