diff --git a/libs/ui/index.ts b/libs/ui/index.ts index 19e4235329..e70fb970a0 100644 --- a/libs/ui/index.ts +++ b/libs/ui/index.ts @@ -18,6 +18,7 @@ export * from './lib/avatar/Avatar' export * from './lib/badge/Badge' export * from './lib/button/Button' export * from './lib/checkbox/Checkbox' +export * from './lib/copy-to-clipboard/CopyToClipboard' export * from './lib/date-picker/DateRangePicker' export * from './lib/divider/Divider' export * from './lib/dropdown-menu/DropdownMenu' diff --git a/libs/ui/lib/copy-to-clipboard/CopyToClipboard.stories.tsx b/libs/ui/lib/copy-to-clipboard/CopyToClipboard.stories.tsx new file mode 100644 index 0000000000..544d6aeec6 --- /dev/null +++ b/libs/ui/lib/copy-to-clipboard/CopyToClipboard.stories.tsx @@ -0,0 +1,28 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright Oxide Computer Company + */ +import { CopyToClipboard } from './CopyToClipboard' + +export const Default = () => ( +
+
+ This is the text to be copied. + +
+

+ Note that the text rendered on the screen is independent of the text copied to the + clipboard … +

+
+ This text, for example, is different from the text that’ll be copied … + +
+
+) diff --git a/libs/ui/lib/copy-to-clipboard/CopyToClipboard.tsx b/libs/ui/lib/copy-to-clipboard/CopyToClipboard.tsx new file mode 100644 index 0000000000..c521346eaf --- /dev/null +++ b/libs/ui/lib/copy-to-clipboard/CopyToClipboard.tsx @@ -0,0 +1,44 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright Oxide Computer Company + */ + +import { useState } from 'react' + +import { Clipboard16Icon, Success12Icon, useTimeout } from '@oxide/ui' + +export const CopyToClipboard = ({ + ariaLabel = 'Click to copy this text', + text, +}: { + ariaLabel?: string + text: string +}) => { + const [hasCopied, setHasCopied] = useState(false) + + useTimeout(() => setHasCopied(false), hasCopied ? 2000 : null) + + const handleCopy = () => { + window.navigator.clipboard.writeText(text).then(() => { + setHasCopied(true) + }) + } + + return ( + + ) +} diff --git a/libs/ui/lib/truncate/Truncate.tsx b/libs/ui/lib/truncate/Truncate.tsx index 3764c1634f..6bc0c65cda 100644 --- a/libs/ui/lib/truncate/Truncate.tsx +++ b/libs/ui/lib/truncate/Truncate.tsx @@ -5,11 +5,8 @@ * * Copyright Oxide Computer Company */ -import { useState } from 'react' -import { Clipboard16Icon, Success12Icon } from '@oxide/design-system/icons/react' - -import useTimeout from '../hooks/use-timeout' +import { CopyToClipboard } from '../copy-to-clipboard/CopyToClipboard' import { Tooltip } from '../tooltip/Tooltip' type TruncatePosition = 'middle' | 'end' @@ -29,38 +26,17 @@ export const Truncate = ({ hasCopyButton, tooltipDelay = 300, }: TruncateProps) => { - const [hasCopied, setHasCopied] = useState(false) - - useTimeout(() => setHasCopied(false), hasCopied ? 2000 : null) - if (text.length <= maxLength) { return
{text}
} - const handleCopy = () => { - window.navigator.clipboard.writeText(text).then(() => { - setHasCopied(true) - }) - } - // Only use the tooltip if the text is longer than maxLength return (
{truncate(text, maxLength, position)}
- {hasCopyButton && - (hasCopied ? ( - - ) : ( - - ))} + {hasCopyButton && }
) }