Catálogo · Contenido
Terminal
Shows a command in a framed block, with tabs as its title bar and a copy button for the open one.
Encaja mejor en: documentación — commands the reader can copy, in a guide or in a documentation site
Example
An install command, in two tabs: npm and the CDN.
npm install @luz-ds/core
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@luz-ds/core@0.3.0/dist/luz.min.css">
Open the CDN tab, then press Copy: the button copies the command of the open tab. Only the npm command shows a $ prompt.
Known issues
None known.
Code
Copy the markup
import "@luz-ds/catalog/components/terminal.css";
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@luz-ds/catalog@0.3.0/dist/components/terminal.min.css" integrity="sha384-DKqk/lNOyNOUUo7fPv1IE50Kem82XAMIrVewVyJVZ1XQZI8HSjIXq/4xahlXy/Ai" crossorigin="anonymous">
<div class="luz-terminal">
<nav class="luz-tabs luz-terminal__tabs" aria-label="Install">
<a class="luz-tab" href="#install-npm-pane">npm</a>
<a class="luz-tab" href="#install-cdn-pane">CDN</a>
</nav>
<div class="luz-tabpanel luz-terminal__pane" id="install-npm-pane">
<button class="luz-copy-btn" type="button" data-copy="npm install @luz-ds/core" aria-label="Copy the npm command">Copy</button>
<pre class="luz-terminal__code" data-lang="bash" tabindex="0" role="region" aria-label="npm command"><code>npm install @luz-ds/core</code></pre>
</div>
<div class="luz-tabpanel luz-terminal__pane" id="install-cdn-pane">
<button class="luz-copy-btn" type="button" data-copy="…" aria-label="Copy the CDN link">Copy</button>
<pre class="luz-terminal__code" data-lang="html" tabindex="0" role="region" aria-label="CDN link"><code>…</code></pre>
</div>
</div>
import { initTabs } from "@luz-ds/core/tabs";
import { initCopyButtons } from "@luz-ds/core/clipboard";
initTabs();
initCopyButtons();
Variants and options
One look. Its parts are classes of the block, and the language of a pane decides whether it shows a prompt:
| Class or attribute | Effect |
|---|---|
.luz-terminal | The frame: a hairline border, rounded corners, a faint tint of the ink |
.luz-terminal | Goes on the .luz-tabs row: the title bar, with small uppercase tabs in the mono face |
.luz-terminal | Goes on a .luz-tabpanel: holds a copy button and a code block |
data-lang="bash" | On the pre.luz-terminal: the command starts with a $ prompt. Any other language shows none |
How it works
A tab row, a copy button and a code block in one frame, styled by components/terminal.css. It has no script of its own: it is tabs, a copy button and a code block.
initTabs()upgrades the row and shows one pane at a time.luz.jsruns it.initCopyButtons()copies thedata-copytext of the button.luz.jsruns it.- The copy button of the open pane sits at the end of the title bar. The code block shows no language label.
- The command is a
.luz-terminal__code, not a.luz-code-block, sohighlight.jsleaves it alone: it adds no second copy button and no syntax colours. - The prompt is drawn by CSS, so it is not part of the text the button copies.
Without JavaScript
The title bar is a row of links, and every pane is shown, stacked, in order. Each link jumps to its pane.
The copy buttons are hidden, because they would do nothing. The command stays on the page, so the reader selects and copies it.
Keyboard and ARIA
Tab moves into the title bar, to the selected tab; Tab again goes to the copy button, then to the command.
- Left and Right (or Up and Down) move to the next tab and select it; Home and End go to the first and the last. In right-to-left text, Left and Right follow the reading direction.
- Enter or Space presses the copy button. Focus stays on it.
- Name the tab row with
aria-label, and each code block witharia-labelandrole="region": the block scrolls, so it takes focus. - The visible label of the button is “Copy”; its
aria-labelstarts with it and says what is copied. The result is announced in the polite live region shared by every copy button.
Contrast and focus are in the Design tab.
Design
When to use
Use a terminal for a command the reader will paste into a shell, or a line to add to a page, that comes in more than one form: npm or the CDN, one package manager or another.
When not to use
Do not use a terminal for code that is not a command, or for a single form with nothing to switch.
- For code to read, such as markup or styles, use a code block.
- For one value to copy, use a copy button next to it.
- For a long session with its output, use a code block the reader can select.
Do and don't
Writing the content
Name each tab after the way, in one word: “npm”, “CDN”. The source is written as is; the stylesheet shows it in capitals.
- Write the command without the prompt sign: for
data-lang="bash"the stylesheet adds it. - Copy exactly what is shown, with no extra spaces and no placeholder the reader must change first.
- Start the accessible name of each copy button with “Copy” and say what it copies: “Copy the npm command”.
Contrast and focus
The command is primary text; the tabs are secondary, and the open one is primary. The prompt is secondary text, like the tabs.
| Part | Colour on background | Light | Dark | High contrast | Needs |
|---|---|---|---|---|---|
Command | --luz-text-primary on --luz-surface-page | 15.8:1 | 15.1:1 | 21.0:1 | 4.5:1 |
Tab | --luz-text-secondary on --luz-surface-page | 6.2:1 | 7.5:1 | 19.3:1 | 4.5:1 |
Open tab | --luz-text-primary on --luz-surface-page | 15.8:1 | 15.1:1 | 21.0:1 | 4.5:1 |
Prompt | --luz-text-secondary on --luz-surface-page | 6.2:1 | 7.5:1 | 19.3:1 | 4.5:1 |
Measured from the token values of each mode, rounded down. Needs is the WCAG 2.2 AA minimum: 4.5:1 for text, 3:1 for focus rings, borders and icons. The block is the page colour with 4% of the ink mixed in, and the title bar 7%, which the token pairs above cannot name: the rows are measured on the page colour, and on the tints each ratio is lower, but every pair still meets its minimum.
- Focus: a tab has the 2 px
--luz-focus-ringoutline drawn inside it, and the copy button the same ring outside it (see tabs and copy button). - Not colour alone: the open tab has a 2 px underline and a heavier weight, and a hairline under the title bar separates it from the command.
Tokens it uses
The 11 tokens that components/terminal.css reads, by family. Each family links to its page, with the values in every mode. In Figma they are variables with the same names: see Tokens in Figma.
- Spacing and sizing
--luz-space-2xs,--luz-space-3xs,--luz-space-sm,--luz-space-xs- Typography
--luz-font-mono,--luz-text-xs- Radius
--luz-radius-md
Keyboard and ARIA are in the Code tab.