Clipboard
stimeo--clipboard
Copies text to the clipboard and announces completion in a live region.
The stimeo--clipboard controller copies the source target's value (or an explicit text value) using the standard navigator.clipboard API — no extra dependency. Success and failure are reflected on data-state and announced through a role="status" live region, never by icon alone. The completion notice clears itself after feedbackDuration, and an stimeo--clipboard:copy event carries { success, text }. Behavior only — styling is owned by this Playground.
Keyboard
| Key | Action |
|---|---|
| Enter / Space | Activate the copy button (native button). |
<%# Markup for the clipboard (copy & completion feedback) demo.
Copies via navigator.clipboard and announces completion in a role="status" live
region. For localization the completion messages are passed via the copied-label /
error-label Values. The look per data-state (idle / copied / error) lives in demo.css. %>
<div
class="clipboard"
data-controller="stimeo--clipboard"
data-stimeo--clipboard-feedback-duration-value="2000"
data-stimeo--clipboard-copied-label-value="<%= t('components.clipboard.demo.copied') %>"
data-stimeo--clipboard-error-label-value="<%= t('components.clipboard.demo.error') %>">
<input
class="clipboard__source"
type="text"
readonly
aria-label="<%= t('components.clipboard.demo.source_label') %>"
value="https://stimeo.example/share/abc123"
data-stimeo--clipboard-target="source">
<button
class="clipboard__button"
type="button"
data-stimeo--clipboard-target="button"
data-action="click->stimeo--clipboard#copy">
<%= t("components.clipboard.demo.button") %>
</button>
<span
class="clipboard__feedback"
role="status"
aria-live="polite"
data-stimeo--clipboard-target="feedback"></span>
</div>
/*
* Presentation-only styles for the clipboard demo.
* Success / failure styling switches on the data-state the library sets on the
* controller element.
*/
.clipboard {
display: flex;
align-items: center;
gap: 0.5rem;
flex-wrap: wrap;
max-width: 32rem;
}
.clipboard__source {
flex: 1 1 16rem;
padding: 0.5rem 0.75rem;
border: 1px solid var(--border-strong);
border-radius: 0.375rem;
font: inherit;
color: var(--fg);
background: var(--surface-subtle);
}
.clipboard__button {
padding: 0.5rem 0.9rem;
border: 1px solid var(--accent);
border-radius: 0.375rem;
background: var(--accent);
color: var(--white);
font: inherit;
font-weight: 600;
cursor: pointer;
}
.clipboard[data-state="copied"] .clipboard__button {
background: var(--leaf-500);
border-color: var(--leaf-500);
}
.clipboard[data-state="error"] .clipboard__button {
background: var(--danger-500);
border-color: var(--danger-500);
}
.clipboard__feedback {
flex-basis: 100%;
min-height: 1.25rem;
font-size: 0.875rem;
color: var(--leaf-500);
}
.clipboard[data-state="error"] .clipboard__feedback {
color: var(--danger-500);
}
// Consumer-side JS for the clipboard demo (optional).
// The library fires stimeo--clipboard:copy on every copy attempt with
// detail { success, text }. The consumer subscribes to add its own behavior
// (analytics, a toast, etc.) — here just a simple log.
document.addEventListener("stimeo--clipboard:copy", (event) => {
const { success, text } = event.detail;
console.log(`[clipboard] success=${success} text=${text}`);
});
These demo styles use shared design tokens (light + dark). Copy the shared styles too, then toggle data-theme on your root element for dark mode.
The data-* attributes you add to your own HTML to wire this component. Put the data-controller below on a root element, then place its targets / values / actions inside that element.
On the root element
data-controller="stimeo--clipboard"
Targets
| Name | Description | Attribute |
|---|---|---|
source
|
The element whose value or text content is copied when no explicit text value is set. |
data-stimeo--clipboard-target="source" |
button
required
|
The button that triggers the copy action. | data-stimeo--clipboard-target="button" |
feedback
required
|
The live region (role="status") that announces the copied or error label. |
data-stimeo--clipboard-target="feedback" |
Values
| Name | Description | Attribute |
|---|---|---|
text
|
Explicit text to copy; when empty (default), the source target's value or text is used instead. | data-stimeo--clipboard-text-value |
feedbackDuration
|
Milliseconds before the completion notice auto-clears and state returns to idle (default 2000); 0 disables auto-reset. | data-stimeo--clipboard-feedback-duration-value |
copiedLabel
|
Label announced in the feedback region on a successful copy (default "Copied"). | data-stimeo--clipboard-copied-label-value |
errorLabel
|
Label announced in the feedback region when the copy fails (default "Copy failed"). | data-stimeo--clipboard-error-label-value |
Actions
| Name | Description | Action |
|---|---|---|
copy
|
Copies the resolved text to the clipboard, reflects the outcome on data-state, and shows the feedback message. |
stimeo--clipboard#copy |
Events
| Name | Description | Event |
|---|---|---|
copy
|
Dispatched after every copy attempt with { success, text } in detail, including on failure. |
stimeo--clipboard:copy |
State hooks
The library only manages these ARIA/data attributes and custom properties. Your CSS reads them to render the look — selectors like [aria-selected], [aria-expanded], or var(--stimeo--…) hook into this state.
| Hook | Target | Meaning |
|---|---|---|
data-state |
Root element | "idle" / "copied" / "error". |
text content |
Feedback | The completion or failure message (live region). |