Copy to Clipboard
The Copy to Clipboard component allows users to quickly copy text to the clipboard without using context menus or keyboard shortcuts.
It’s commonly used to allow users to copy unique identifiers such as tokens and URLs.
There are certain circumstances when browser's API to interact with clipboard may throw an error (or reject the returned Promise), thus we recommend to always provide onError callback via props. For example, we could show a toast notification "Couldn't copy to the clipboard. Please try again.". See "Handle errors" below for an example.
Example
function Example() { const text = 'Sample text'; const onCopy = text => { console.log(text); }; return ( <div style={{ display: 'flex', alignItems: 'center', gap: Spacing10 }}> <span>{text}</span> <CopyToClipboard text={text} notificationMessage="Copied!" onCopy={onCopy} > <IconButton iconName="Clipboard" aria-label="copy" /> </CopyToClipboard> </div> ); }
Usage Rules
Do:
- Use a
snackbarto notify users when a component wraps an element that will disappear on click. - Whenever possible, use the
Clipboardicon with a trigger element.
Variants
Toast Notification
- The implementation of
ToastProviderandToastContexthas been moved tomfe-shellandmfe-shared-context, respectively. - Please import
ToastContextfrommfe-shared-context. We have wrapped all the mfe apps withToastProviderat root level inmfe-shell. - All
mfeapps are wrapped withToastProviderfrommfe-shellso you don't need to wrap your app one more time.
You can decide by yourself how to notify users we strongly recommend using a toast only if a trigger element will disappear on click.
function NotifyWithToast() { const text = 'Another sample text'; const onCopy = text => { console.log(text); }; return ( <ToastProvider> <div style={{ display: 'flex', alignItems: 'center', gap: Spacing10 }}> <span>{text}</span> <CopyToClipboard notificationType="toast" text={text} notificationMessage="Copied!" onCopy={onCopy} > <IconButton iconName="Clipboard" aria-label="copy" /> </CopyToClipboard> </div> </ToastProvider> ); }
Alternatively, you can use the copyToClipboard callback. You can get it from the useCopyToClipboard hook.
In that case, you should pass text and notificationMessage arguments into the copyToClipboard function, respectively.
Additionally, this function can optionally receive the onCopy callback as the third argument.
function UseCallback() { const MyComponent = () => { const copyToClipboard = useCopyToClipboard(true, 'toast'); const text = 'Text to copy'; const onCopy = text => { console.log(text); }; return ( <div style={{ display: 'flex', alignItems: 'center', gap: Spacing10 }}> <span>{text}</span> <IconButton iconName="Clipboard" onClick={() => { copyToClipboard(text, 'Copied!', onCopy); }} aria-label="copy" /> </div> ); }; return ( <ToastProvider> <MyComponent /> </ToastProvider> ); }
Tooltip Position
You can use tooltipPosition prop to specify Tooltip position inside Copy to Clipboard
function Example() { const text = 'Sample text'; const onCopy = text => { console.log(text); }; return ( <div style={{ display: 'flex', alignItems: 'center', gap: Spacing10 }}> <span>{text}</span> <CopyToClipboard text={text} notificationMessage="Copied!" onCopy={onCopy} tooltipPosition="auto" > <IconButton iconName="Clipboard" aria-label="copy" /> </CopyToClipboard> <span>{text}</span> <CopyToClipboard text={text} notificationMessage="Copied!" onCopy={onCopy} tooltipPosition="bottom" > <IconButton iconName="Clipboard" aria-label="copy" /> </CopyToClipboard> </div> ); }
Handling errors
Browser API to interact with clipboard returns a promise, which can get rejected instead of resolved. Ideally we should handle potential errors, for instance navigator.clipboard.writeText() rejects when the browser window is not focused.
To reproduce this, you might enable CPU throttling via the DEV tools and click on the copy icon, following it up with immediate change to another window with a hotkey, as otherwise enough time will pass for promise to successfully resolve.
function Example() { const CopyButton = () => { const text = 'Sample text'; const { showToast } = useContext(ToastContext); const onCopy = (text) => { console.log(text); }; const onError = (err) => { showToast("Couldn't copy to the clipboard. Please try again."); }; return ( <div style={{ display: 'flex', alignItems: 'center', gap: Spacing10 }}> <span>{text}</span> <CopyToClipboard text={text} notificationMessage="Copied!" onCopy={onCopy} onError={onError} > <IconButton iconName="Clipboard" aria-label="copy" /> </CopyToClipboard> </div> ); }; return ( <ToastProvider> <CopyButton /> </ToastProvider> ); }
Props
CopyToClipboard
| Name | Type | Default |
|---|---|---|
children * The trigger element. |
| — |
notificationMessage * Text to be shown in the notification |
| — |
text * Text to be copied to clipboard |
| — |
notificationType The type of component to be used for notification |
| "tooltip" |
onCopy The callback will be executed after the text has copied |
| — |
onError The callback executed when failed to copy |
| — |
tooltipPosition |
| — |
zIndex Add z-index rule to the tooltip component |
| "auto" |
| * - the prop is required. |