Clipboard Button
The <x-wirekit::clipboard-button> component copies a value to the clipboard on click and temporarily shows a "Copied!" confirmation. It uses the Clipboard API and announces the copy action to screen readers via a live region.
Usage
Inline with a code snippet:
<div class="flex items-center justify-between rounded-lg px-3 py-2" style="background: var(--color-wk-bg-muted);">
<code class="text-sm">composer require pushery/wirekit</code>
<x-wirekit::clipboard-button value="composer require pushery/wirekit">
Copy
</x-wirekit::clipboard-button>
</div>
Custom Confirmation Text
Change the text shown after copying:
Custom Duration
Control how long the "Copied!" state persists (in milliseconds):
Copying Dynamic Values
Use Blade expressions to copy dynamic content:
<x-wirekit::clipboard-button :value="$user->api_key">
Copy API Key
</x-wirekit::clipboard-button>
Code Block with Copy
Combine with other components to create a copyable code snippet:
composer require pushery/wirekit
Visual Behavior
- Default state — shows a clipboard icon + your slot content (e.g., "Copy Link")
- After click — icon swaps to a green checkmark, label changes to
copiedText - After duration — reverts to the default state automatically
The icon swap is handled by Alpine's x-show directives. The checkmark icon uses --color-wk-success-text for the green color.
Requirements
The clipboard button uses the Clipboard API (navigator.clipboard.writeText()), which requires:
- HTTPS or localhost — the Clipboard API is only available in secure contexts
- User gesture — the copy happens inside a click handler, which satisfies the browser's user activation requirement
If neither condition is met, the copy will silently fail. All modern browsers (Chrome, Firefox, Safari, Edge) support the Clipboard API.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value |
string |
'' |
The text to copy to the clipboard |
copiedText |
string |
'Copied!' |
Label shown temporarily after copying |
duration |
int |
2000 |
How long (ms) the "Copied!" state persists before reverting |
iconOnly |
bool |
false |
Render a bare icon-only button (no border/label) — gray glyph that pops green on copy. Requires aria-label. |
scope |
string|null |
null |
Scoped personalization key |
Accessibility
- The button is a native
<button type="button">— fully keyboard-accessible - Icons:
aria-hidden="true"on both SVGs (decorative — the text label is the accessible name) - Live region:
role="status"+aria-live="polite"announces "Copied to clipboard" to screen readers when the copy succeeds - Focus ring visible via
focus-visible:ring
The slot content (e.g., "Copy Link") serves as the button's accessible name. If you need a different accessible name, pass an aria-label attribute.
Keyboard Interaction
| Key | Action |
|---|---|
Tab |
Move focus to the button |
Enter / Space |
Activate the button |
Pitfalls
- Don't bind
wire:clickon the button — use the component's built-in:valueprop. The Alpine handler writes via the Clipboard API; awire:clickserver roundtrip would race the clipboard write.
Design Tokens
| Token | Used for |
|---|---|
--font-wk-sans |
Button font family |
--font-wk-body-weight |
Font weight |
--text-wk-md |
Font size |
--color-wk-text |
Default label text |
--color-wk-success-text |
Copied checkmark color |
--color-wk-bg-elevated |
Button background |
--color-wk-bg-subtle |
Hover background |
--color-wk-border |
Button border |
--color-wk-ring |
Focus ring |
--ring-wk-width |
Focus ring width |
--border-wk-width |
Border width |
--radius-wk-md |
Border radius |
--shadow-wk-sm |
Subtle shadow |
--gap-wk-sm |
Icon-to-label gap |
--padding-wk-x-md / --padding-wk-y-sm |
Button padding |
--transition-wk-duration / --transition-wk-easing |
Hover / icon-swap transition |
Personalization
Override classes globally via WireKit::personalize():
use Pushery\WireKit\WireKit;
WireKit::personalize('clipboard-button', [
'base' => 'inline-flex items-center gap-2 px-4 py-2 text-sm bg-blue-600 text-white rounded-md',
]);
Further Reading
- MDN: Clipboard API — the browser API used for copying
- MDN:
navigator.clipboard.writeText()— the specific method called - MDN:
role="status"— live region role for the copy announcement - Can I Use: Clipboard API — browser support table