Core · Actions and input
Copy button
Copies a command or a value to the clipboard, and says it did.
Example
A value with a button that copies it to the clipboard.
var(--luz-brand-primary)
The button copies the text of its data-copy attribute.
Known issues
The Clipboard API needs a secure context (https, or localhost while you develop). Elsewhere the copy fails.
The failure is announced to screen readers only: the button shows no message, so a sighted reader sees nothing happen. The text can still be selected and copied by hand.
Code
Copy the markup
<code class="luz-code-inline">npm install @luz-ds/core</code>
<button class="luz-copy-btn" type="button" data-copy="npm install @luz-ds/core" aria-label="Copy the install command">Copy</button>
import { initCopyButtons } from "@luz-ds/core/clipboard";
initCopyButtons();
Variants and options
One class and one attribute. The look does not change.
| Class or attribute | Effect |
|---|---|
.luz-copy-btn | Small mono button, 24 px high; hidden until the script runs |
data-copy | The exact text to copy |
.is-copied | Set by the script for about a second after a copy: success colour, label "Copied" |
How it works
A native <button>, styled by components/copy-btn.css and wired by clipboard.js.
initCopyButtons()listens for clicks on any.luz-copy-btnand copies itsdata-copy.luz.jsruns it.- For about a second the label reads "Copied", then goes back.
- A polite live region says "Copied to clipboard", or that the copy failed. The texts come from
i18n.js, in the language of the page. copyToClipboard(text, el)does the same for your own controls.
Without JavaScript
The button is hidden, because it would do nothing. The text it copies stays on the page, so the reader selects and copies it.
Keyboard and ARIA
Tab reaches the button; Enter or Space copies. Focus stays on the button.
- The visible label is "Copy"; the
aria-labelstarts with it and says what is copied: "Copy the install command". - The result is announced in a polite live region shared by every copy button.
Contrast and focus are in the Design tab.
Design
When to use
Use a copy button for a short string the reader will paste somewhere else: a command, a token name, a key.
When not to use
Do not use a copy button where selecting the text is just as easy, or as the only way to get the content.
- For long text, show it in a code block the reader can select.
Do and don't
Writing the content
Keep the visible label "Copy", and name what it copies in the accessible name.
- Start the accessible name with the visible word: "Copy the install command".
- Copy exactly what is shown, without a prompt sign or extra spaces.
Contrast and focus
The label is secondary text on the page; after a copy it turns to the success colour.
| Part | Colour on background | Light | Dark | High contrast | Needs |
|---|---|---|---|---|---|
Label | --luz-text-secondary on --luz-surface-page | 6.2:1 | 7.5:1 | 19.3:1 | 4.5:1 |
Label, hover | --luz-text-primary on --luz-brand-subtle over --luz-surface-page | 14.3:1 | 12.7:1 | 20.1:1 | 4.5:1 |
Label, copied | --luz-color-success on --luz-surface-page | 5.3:1 | 12.5:1 | 9.3:1 | 4.5:1 |
Focus ring | --luz-focus-ring on --luz-surface-page | 5.6:1 | 7.7:1 | 21.0:1 | 3: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.
- Focus: a 2 px
--luz-focus-ringoutline, 2 px outside the button. - Not colour alone: after a copy the label reads “Copied” and a live region says so; the green is an extra.
- Target: at least 24 px high.
Tokens it uses
The 13 tokens that components/copy-btn.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.
- Color
--luz-brand-primary,--luz-brand-subtle,--luz-color-success,--luz-divider,--luz-focus-ring,--luz-text-primary,--luz-text-secondary- Spacing and sizing
--luz-space-2xs,--luz-space-xs- Typography
--luz-font-mono,--luz-text-xs- Radius
--luz-radius-md- Motion
--luz-duration-fast
Keyboard and ARIA are in the Code tab.