Files
coder/site/src/components/CopyButton/CopyButton.tsx
Ammar Bandukwala 2ee6acb2ad Upgrade frontend to React 18 (#3353)
Co-authored-by: Kira Pilot <kira.pilot23@gmail.com>
2022-08-22 15:42:06 -05:00

108 lines
2.8 KiB
TypeScript

import IconButton from "@material-ui/core/Button"
import { makeStyles } from "@material-ui/core/styles"
import Tooltip from "@material-ui/core/Tooltip"
import Check from "@material-ui/icons/Check"
import React, { useState } from "react"
import { combineClasses } from "../../util/combineClasses"
import { FileCopyIcon } from "../Icons/FileCopyIcon"
interface CopyButtonProps {
text: string
ctaCopy?: string
wrapperClassName?: string
buttonClassName?: string
tooltipTitle?: string
}
export const Language = {
tooltipTitle: "Copy to clipboard",
ariaLabel: "Copy to clipboard",
}
/**
* Copy button used inside the CodeBlock component internally
*/
export const CopyButton: React.FC<React.PropsWithChildren<CopyButtonProps>> = ({
text,
ctaCopy,
wrapperClassName = "",
buttonClassName = "",
tooltipTitle = Language.tooltipTitle,
}) => {
const styles = useStyles()
const [isCopied, setIsCopied] = useState<boolean>(false)
const copyToClipboard = async (): Promise<void> => {
try {
await window.navigator.clipboard.writeText(text)
setIsCopied(true)
window.setTimeout(() => {
setIsCopied(false)
}, 1000)
} catch (err) {
const input = document.createElement("input")
input.value = text
document.body.appendChild(input)
input.focus()
input.select()
const result = document.execCommand("copy")
document.body.removeChild(input)
if (result) {
setIsCopied(true)
window.setTimeout(() => {
setIsCopied(false)
}, 1000)
} else {
const wrappedErr = new Error("copyToClipboard: failed to copy text to clipboard")
if (err instanceof Error) {
wrappedErr.stack = err.stack
}
console.error(wrappedErr)
}
}
}
return (
<Tooltip title={tooltipTitle} placement="top">
<div className={combineClasses([styles.copyButtonWrapper, wrapperClassName])}>
<IconButton
className={combineClasses([styles.copyButton, buttonClassName])}
onClick={copyToClipboard}
size="small"
aria-label={Language.ariaLabel}
>
{isCopied ? (
<Check className={styles.fileCopyIcon} />
) : (
<FileCopyIcon className={styles.fileCopyIcon} />
)}
{ctaCopy && <div className={styles.buttonCopy}>{ctaCopy}</div>}
</IconButton>
</div>
</Tooltip>
)
}
const useStyles = makeStyles((theme) => ({
copyButtonWrapper: {
display: "flex",
marginLeft: theme.spacing(1),
},
copyButton: {
borderRadius: theme.shape.borderRadius,
padding: theme.spacing(0.85),
minWidth: 32,
"&:hover": {
background: theme.palette.background.paper,
},
},
fileCopyIcon: {
width: 20,
height: 20,
},
buttonCopy: {
marginLeft: theme.spacing(1),
},
}))