Copy Button <mv-copy-button>
Bouton de copie avec retour façon compteur kilométrique : l’icône et le libellé défilent vers le haut jusqu’à une coche (ou vers le bas jusqu’à une alerte en cas d’échec) dans des fenêtres fixes, pendant qu’un voile teinté remplit le bouton puis se vide pendant le délai, comme un compte à rebours ; les boutons à icône reçoivent une étiquette d’état.
Catégorie Micro-interactions Type Web Component (<mv-copy-button>) Statut stable Keywords copy, clipboard, roll, odometer, success, feedback, code
When to use
A code block, API key or share link needs a copy button with clear success or failure feedback An icon-only copy control in a toolbar or command bar should show a status tag and a timed reset A copied state should visibly count down before the button returns to idle
Avoid when
The button toggles an on/off state rather than performing a one-shot copy → use Toggle instead
Obtenir Copy Button. Inclus dans toutes les offres : le Pro pack contient les 317 composants, avec la CLI et le serveur MCP utilisés ci-dessous.
Voir les offres
Installation
node scripts/add.mjs copy-button --out ./src/marvelous
Agent IA avec le serveur MCP de Marvelous UI : install_components({ slugs: ["copy-button"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).
Fichiers copiés (dépendances comprises) : tokens/tokens.css, core/base.css, core/element.js, core/motion.js, components/copy-button/copy-button.js, components/copy-button/copy-button.css.
Utilisation
Balisage de référence : partez de celui-ci et personnalisez-le avec les attributs, data-* et les variables CSS :
<div style="display:grid;gap:1rem;width:100%;max-width:520px">
<div style="display:flex;align-items:center;gap:.5rem;padding:.4rem .4rem .4rem .9rem;border:1px solid var(--mv-border);border-radius:var(--mv-radius-lg);background:var(--mv-bg-subtle);font:500 .85rem/1 var(--mv-font-mono)">
<span style="color:var(--mv-fg-subtle)">$</span>
<code style="flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">node scripts/add.mjs confetti</code>
<mv-copy-button value="node scripts/add.mjs confetti" data-variant="ghost" label="Copy command"></mv-copy-button>
</div>
<div style="position:relative;border:1px solid var(--mv-border);border-radius:var(--mv-radius-lg);background:var(--mv-surface);overflow:hidden">
<div style="display:flex;justify-content:space-between;align-items:center;padding:.4rem .5rem .4rem .9rem;border-bottom:1px solid var(--mv-border);font-size:.75rem;color:var(--mv-fg-muted)">
<span>index.html</span>
<mv-copy-button target="#mv-copy-demo-code">Copy code</mv-copy-button>
</div>
<pre style="margin:0;padding:.85rem 1rem;font:.8rem/1.6 var(--mv-font-mono);overflow:auto"><code id="mv-copy-demo-code"><mv-like count="128"></mv-like>
<script type="module" src="like-button.js"></script></code></pre>
</div>
<div style="display:flex;flex-wrap:wrap;gap:.6rem;align-items:center">
<input class="mv-input" id="mv-copy-demo-link" value="https://lumen.studio/invite/7QX2" readonly style="flex:1;min-width:200px">
<mv-copy-button target="#mv-copy-demo-link" success-label="Link copied">
<button class="mv-button" data-variant="outline">Copy link</button>
</mv-copy-button>
<mv-copy-button target="#mv-copy-demo-introuvable" label="Copy (missing target: error state)"></mv-copy-button>
</div>
</div>
API
Attributes
Name Type Default Description valuestring Text to copy. targetCSS selector Otherwise: copies the value (field) or the text of the targeted element. labelstring CopyAccessible name of the icon button. success-labelstring Copied!Label / bubble / announcement on success. error-labelstring Copy failedSame, on failure. timeoutnumber 2000Duration of the copied / error state (ms). disabledboolean Disables the button. data-variantghost No border or background (command bars, code blocks). data-bubblebottom Bubble below the button instead of above. data-stateidle | copied | error Set by the component (for styling).
Properties
Name Type Description textstring Text that will be copied (read-only).
Methods
Name Description copy()Copies and plays the feedback; Promise<boolean>.
Events
Name Description mv-copySuccess; detail = { text }. mv-copy-errorFailure; detail = { error }.
Content structure
Name Description (text)Visible label; without text, an icon button with a bubble. buttonOr your own child <button> (e.g. .mv-button): the icon and cross-fade are injected into it.
CSS classes
Name Description mv-copy-button-trigger / -icons / -reel / -slot / -label / -text / -wash / -bubbleGenerated parts (the wash and reel are aria-hidden).
CSS variables
Name Default Description --mv-copy-button-successvar(--mv-success)Check color. --mv-copy-button-errorvar(--mv-danger)Error color. --mv-copy-button-icon-size1.2emIcon size.
Accessibility
A real <button>; the icon button gets an aria-label (“Copy”). The result is announced by a polite role=status region (“Copied!” / “Copy failed”); alternate labels, icons, wash and tag are aria-hidden to avoid duplicates. Clipboard API with an execCommand fallback (insecure contexts); repeated copies restart the timer. Reduced motion: no roll or drain, the state swaps instantly and the tint stays static until reset.