MUI Docs Infra

Warning

This is an internal project, and is not intended for public use. No support or stability guarantees are provided.

Use Copier

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, the useCode and useDemo hooks already provide built-in copy functionality, so useCopier is not needed.

Basic Usage

Text Input Copy

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>
  );
}

Advanced Usage

Dynamic Content

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>
  );
}

With Error Handling

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>
  );
}

With Custom Analytics

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>
  );
}

Types

ParameterTypeDescription
contents
(() => string | undefined) | string
opts
UseCopierOpts | undefined
Return Type
KeyTypeRequired
copy
(
  event: React.MouseEvent<HTMLButtonElement, MouseEvent>,
) => Promise<void>
Yes
recentlySuccessful
boolean
Yes
UseCopierOpts
type UseCopierOpts = {
  onCopied?: OnCopied;
  onError?: OnCopyError;
  onClick?: OnCopyClick;
  timeout?: number;
}

How It Works

  1. Content Resolution: When copy is called, resolves content from string or function
  2. Clipboard API: Uses the clipboard-copy library for cross-browser compatibility
  3. Success State: Sets recentlySuccessful to true after successful copy
  4. Timeout Management: Automatically resets success state after configured timeout
  5. Cleanup: Clears timeouts to prevent memory leaks

State Management

The hook manages internal state for copy feedback:

  • Initial state: recentlySuccessful is false
  • On copy attempt: State resets to false and clears any existing timeout
  • On success: State becomes true and starts timeout countdown
  • After timeout: State resets to false
  • On error: State remains false but error callback is fired

Error Handling

Copy operations can fail for various reasons:

  • Security restrictions: Some browsers require user interaction
  • Permission denied: Clipboard access may be blocked
  • Empty content: No content to copy (function returns undefined)

The hook provides the onError callback to handle these cases gracefully.


When to Use

  • Code blocks - Copy source code, commands, or configurations
  • Documentation - Copy API endpoints, package names, or examples
  • Interactive demos - Copy generated output or current state
  • Forms - Copy generated URLs, tokens, or formatted data
  • Any UI element - That benefits from copy-to-clipboard functionality

Browser Support

Uses the clipboard-copy library which provides:

  • Modern navigator.clipboard.writeText() API when available
  • Fallback to document.execCommand('copy') for older browsers
  • Works in both secure (HTTPS) and insecure contexts