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
snackbar
to notify users when a component wraps an element that will disappear on click. - Whenever possible, use the
Clipboard
icon with a trigger element.
Variants
Toast Notification
- The implementation of
ToastProvider
andToastContext
has been moved tomfe-shell
andmfe-shared-context
, respectively. - Please import
ToastContext
frommfe-shared-context
. We have wrapped all the mfe apps withToastProvider
at root level inmfe-shell
. - All
mfe
apps are wrapped withToastProvider
frommfe-shell
so 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. |