Warning
This is an internal project, and is not intended for public use. No support or stability guarantees are provided.
The useCopier hook provides robust clipboard copy functionality with success state management, error handling, and customizable callbacks. It's designed for code blocks, buttons, and interactive elements that need copy-to-clipboard functionality.
Note
When using
CodeHighlighter, theuseCodeanduseDemohooks already provide built-in copy functionality, souseCopieris not needed.
A simple example showing how to copy text from an input field.
'use client';
import * as React from 'react';
import { useCopier } from '@mui/internal-docs-infra/useCopier';
import styles from './TextInputCopy.module.css';
export function TextInputCopy() {
const [text, setText] = React.useState('Hello, copy me!');
const { copy, recentlySuccessful } = useCopier(() => text);
return (
<div className={styles.container}>
<input
type="text"
value={text}
onChange={(event) => setText(event.target.value)}
className={styles.input}
placeholder="Enter text to copy..."
/>
<button type="button" onClick={copy} className={styles.button}>
{recentlySuccessful ? '✓ Copied!' : 'Copy'}
</button>
</div>
);
}
import { useCopier } from '@mui/internal-docs-infra/useCopier';
function CodeBlockCopy({ getCode }: { getCode: () => string }) {
const { copy, recentlySuccessful } = useCopier(getCode);
return (
<button onClick={copy} disabled={recentlySuccessful}>
{recentlySuccessful ? '✓ Copied' : 'Copy Code'}
</button>
);
}
import { useCopier } from '@mui/internal-docs-infra/useCopier';
function CopyWithFeedback({ content }: { content: string }) {
const [error, setError] = React.useState<string | null>(null);
const { copy, recentlySuccessful } = useCopier(content, {
onCopied: () => setError(null),
onError: (err) => setError('Failed to copy to clipboard'),
timeout: 3000,
});
return (
<div>
<button onClick={copy}>{recentlySuccessful ? 'Copied!' : 'Copy'}</button>
{error && <span style={{ color: 'red' }}>{error}</span>}
</div>
);
}
import { useCopier } from '@mui/internal-docs-infra/useCopier';
function AnalyticsCopyButton({ text, label }: { text: string; label: string }) {
const { copy, recentlySuccessful } = useCopier(text, {
onCopied: () => {
// Track successful copy events
analytics.track('Code Copied', { label });
},
onError: (error) => {
// Track copy failures
analytics.track('Copy Failed', { label, error: String(error) });
},
onClick: (event) => {
// Track all copy attempts
analytics.track('Copy Attempted', { label });
},
});
return (
<button onClick={copy} className={recentlySuccessful ? 'success' : ''}>
{recentlySuccessful ? 'Copied!' : `Copy ${label}`}
</button>
);
}
const { copy, recentlySuccessful } = useCopier(contents, options);
| Parameter | Type | Description |
|---|---|---|
contents | string | (() => string | undefined) | Static text or function returning text to copy |
options | UseCopierOpts | Optional configuration object |
| Option | Type | Default | Description |
|---|---|---|---|
onCopied | () => void | - | Callback fired after successful copy |
onError | (error: unknown) => void | - | Callback fired when copy fails |
onClick | (event: React.MouseEvent<HTMLButtonElement>) => void | - | Additional click handler |
timeout | number | 2000 | Duration (ms) to show success state |
| Property | Type | Description |
|---|---|---|
copy | (event: React.MouseEvent<HTMLButtonElement>) => void | Function to trigger copy operation |
recentlySuccessful | boolean | Whether copy was recently successful |
export type UseCopierOpts = {
onCopied?: () => void;
onError?: (error: unknown) => void;
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
timeout?: number;
};
export function useCopier(
contents: (() => string | undefined) | string,
opts?: UseCopierOpts,
): {
copy: (event: React.MouseEvent<HTMLButtonElement>) => void;
recentlySuccessful: boolean;
};
copy is called, resolves content from string or functionclipboard-copy library for cross-browser compatibilityrecentlySuccessful to true after successful copyThe hook manages internal state for copy feedback:
recentlySuccessful is falsefalse and clears any existing timeouttrue and starts timeout countdownfalsefalse but error callback is firedCopy operations can fail for various reasons:
The hook provides the onError callback to handle these cases gracefully.
Uses the clipboard-copy library which provides:
navigator.clipboard.writeText() API when availabledocument.execCommand('copy') for older browsersCodeHighlighter - Often used together for code copy functionality