# Copy Button

One-tap clipboard button with a Copy↔Check icon morph and tooltip feedback, reverting after a short hold.

- Package: `@mielui/svelte`
- Component version: `1.1.0`
- Depends on Mielui components: _internal/utils, button, tooltip
- Shared utilities: components/_internal/button-attributes, hugeicons-icon, utils.cn

## Install

~~~~sh
pnpm dlx @mielui/svelte add copy-button
~~~~

## API

This reference is generated at build time from the component manifest, public `index.ts`, and documentation examples below. Changes to those source files are reflected here in the published Markdown. Standard Svelte and HTML attributes accepted by the exported prop types are supported.


### CopyButton

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| labels | CopyButtonLabels \| undefined | - | No | No | Overrides the built-in text and accessible names. Every key is optional and English is the fallback. |
| text | string | - | Yes | No | The string written to the clipboard on click. |
| duration | number \| undefined | 2000 | No | No | How long (ms) to hold the copied state before reverting. |
| variant | ButtonVariant \| undefined | 'ghost' | No | No | Button variant (defaults to `ghost`). |
| size | "sm" \| "md" \| "lg" \| "icon" \| undefined | 'icon' | No | No | Button size (defaults to `icon`). Pass a text size when rendering children. |
| class | string \| undefined | - | No | No | Classes added to the element. |
| children | Snippet<[]> \| undefined | - | No | No | Optional visible label rendered after the icon. |
| oncopy | ((text: string) => void) \| undefined | - | No | No | Fired after the text is successfully written to the clipboard. |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### Public types

~~~~ts
import type { ButtonVariant } from '@mielui/svelte/components/button';
import type { Snippet } from 'svelte';
import type { HTMLButtonAttributes } from 'svelte/elements';
import CopyButton from './copy-button.svelte';

export type CopyButtonLabels = {
    /** Tooltip and accessible name at rest. */
    copy?: string;
    /** Tooltip and accessible name shown right after copying. */
    copied?: string;
};

export type CopyButtonProps = {
    /**
     * Overrides the built-in text and accessible names. Every key is optional and English is the
     * fallback.
     */
    labels?: CopyButtonLabels;
    /** The string written to the clipboard on click. */
    text: string;
    /** How long (ms) to hold the copied state before reverting. */
    duration?: number;
    /** Button variant (defaults to `ghost`). */
    variant?: ButtonVariant;
    /** Button size (defaults to `icon`). Pass a text size when rendering children. */
    size?: 'sm' | 'md' | 'lg' | 'icon';
    /** Classes added to the element. */
    class?: string;
    /** Optional visible label rendered after the icon. */
    children?: Snippet;
    /** Fired after the text is successfully written to the clipboard. */
    oncopy?: (text: string) => void;
} & Omit<HTMLButtonAttributes, 'class' | 'type' | 'oncopy'>;

export { CopyButton };
export default CopyButton;
~~~~

## Examples

### Basic

~~~~svelte
<script lang="ts">
    import { CopyButton } from '@mielui/svelte/components/copy-button';
</script>

<div
    class="flex w-full max-w-sm items-center gap-2 rounded-[var(--radius-control)] border border-[var(--color-input)] bg-[var(--color-field)] py-1 ps-4 pe-1"
>
    <code class="min-w-0 flex-1 truncate font-mono text-sm text-foreground">
        pnpm dlx @mielui/svelte add copy-button
    </code>
    <CopyButton text="pnpm dlx @mielui/svelte add copy-button" />
</div>
~~~~

### Feedback

~~~~svelte
<script lang="ts">
    import { CopyButton } from '@mielui/svelte/components/copy-button';
</script>

<div class="flex items-center gap-3">
    <CopyButton
        text="sk_live_example"
        labels={{ copy: 'Copy API key', copied: 'Key copied' }}
        duration={4000}
        size="md"
        variant="outline"
    >
        Copy key
    </CopyButton>
    <span class="text-sm text-foreground-muted">Stays copied for four seconds</span>
</div>
~~~~

### Hero

~~~~svelte
<script lang="ts">
    import { CopyButton } from '@mielui/svelte/components/copy-button';

    let copied = $state(false);
</script>

<div class="flex flex-col gap-3">
    <div class="flex items-center gap-3">
        <code class="text-sm">pnpm add @mielui/svelte</code>
        <CopyButton
            text="pnpm add @mielui/svelte"
            labels={{ copy: 'Copy install command' }}
            oncopy={() => {
                copied = true;
            }}
        />
    </div>
    <p role="status" class="text-sm text-foreground-muted">
        {copied ? 'Install command copied.' : 'Copy the command to your clipboard.'}
    </p>
</div>
~~~~

### Variants

~~~~svelte
<script lang="ts">
    import { CopyButton } from '@mielui/svelte/components/copy-button';
</script>

<div class="flex items-center gap-3">
    <CopyButton text="ghost variant" labels={{ copy: 'Ghost' }} />
    <CopyButton text="outline variant" labels={{ copy: 'Outline' }} variant="outline" />
    <CopyButton text="secondary variant" labels={{ copy: 'Secondary' }} variant="secondary" />
</div>
~~~~

For the rendered reference, visit [/docs/components/copy-button](/docs/components/copy-button).
