Skip to content

Terminal

A recorded terminal session: what running something looked like, not code to take away.

Preview

Code

The three render the same class names, the same ARIA and the same data attributes. That is checked when this site builds: a class in any of these samples that neither the markup contract nor the shipped stylesheet defines fails the build.

<pre class="wsu-terminal" tabindex="0" role="region" aria-label="Subscribing to the calendar feed"><code class="wsu-terminal__line"><span class="wsu-terminal__prompt" aria-hidden="true">$</span>curl -O webcal://calendar.wayne.edu/registration/ee6515.ics</code><code class="wsu-terminal__line"><span class="wsu-terminal__prompt" aria-hidden="true">&gt;</span>Downloading ee6515.ics...</code><code class="wsu-terminal__line"><span class="wsu-terminal__prompt" aria-hidden="true">&gt;</span>Done.</code></pre>

Why it works this way

  • CodeBlock and this component are for opposite things. CodeBlock presents real code somebody is meant to take, which is why it has a language label and a copy button. This presents a pretend terminal, used to show what running something looks like, so it has neither: nobody copies a screenshot of a terminal, and offering a copy button on one would be a lie about what it is.
  • Each line's prompt, the $ or > at the start, is part of the illustration rather than something a reader would want read out or selected, the same treatment a Timeline gives its marker. It is aria-hidden and unselectable in the stylesheet; the line's own text is never touched by that and stays exactly as reachable as any other text on the page.
  • A line can carry highlight to point at the one line an example is actually about, the same job a highlighted line does in a diff. It reads with a heavier weight as well as a fill, so the emphasis never rests on color alone (1.4.1). A whole session can carry nowrap when its own line length is part of what it is showing, a long path or URL: the panel already scrolls horizontally, so nowrap keeps that one line exactly as recorded instead of folding it into lines that were never really there. Ordinary sessions leave both off and wrap, which is free for a screen reader and for reflow (1.4.10).
  • The panel is a fixed dark surface in both themes, the same in light or dark, because a real terminal does not repaint itself when the page around it changes theme. `variant` is a fixed set drawn from the semantic layer instead (brand, accent, success, danger), the same one wsu-badge and wsu-alert already use: every line in this panel is plain text the component itself sets `color` on, never a caller's own markup, so the matching on-X/X pairing is proven at 7:1 against the whole panel, in both themes, by the token suite rather than asserted here.

Accessibility

  • The prompt is aria-hidden and CSS user-select: none, so it is announced by nothing and copied by nothing, the way the marker before a Timeline entry is (2.1.1, 1.1.1).
  • pre carries tabindex="0" and role="region" with a required label, the same pairing CodeBlock and DataTable use for a horizontally scrolling area with nothing else focusable inside it (1.4.10, 2.1.1).
  • Every line is a real code element in the document, not painted with CSS content, so a screen reader reads the command exactly as printed.
  • highlight is a visual pointer, not a state, so it changes nothing in the accessibility tree; the heavier weight it carries alongside its fill is what keeps the emphasis from resting on color alone.

Success criteria in brackets refer to WCAG 2.2. Every one of them is checked by axe-core in both themes at three viewport widths before this page can be published. See Accessibility for what the gates are.

Props

Blade

AttributeDefaultWhat it does
linesrequired[{ prompt, text, highlight }]. prompt is optional, for a continuation line with no leading $ or >. highlight marks the one line an example is about.
label'terminal output'Names the scrollable region for a line too long to fit.
nowrapfalseScrolls a long line instead of wrapping it, for a line whose own length is part of what it shows.
variant'''' | 'brand' | 'accent' | 'success' | 'danger'. Recolors the whole panel, proven at 7:1 against its own text.

Vue

PropType and defaultWhat it does
linesArray, required[{ prompt, text, highlight }]. prompt is optional, for a continuation line with no leading $ or >. highlight marks the one line an example is about.
labelString, 'terminal output'Names the scrollable region for a line too long to fit.
nowrapBoolean, falseScrolls a long line instead of wrapping it, for a line whose own length is part of what it shows.
variantString, '''' | 'brand' | 'accent' | 'success' | 'danger'. Recolors the whole panel, proven at 7:1 against its own text.

In the markup contract

contract/markup-contract.json is extracted from the two static templates and every package tests against it. This is what it records for .wsu-terminal.

TemplateElementsAccessibility attributesUses
internal apps/examples/static-html/index.htmlprearia-labelroletabindex1
public apps/examples/static-html/public-app.htmlprearia-labelroletabindex1