Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libs/ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
28 changes: 28 additions & 0 deletions libs/ui/lib/copy-to-clipboard/CopyToClipboard.stories.tsx
Original file line number Diff line number Diff line change
@@ -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 = () => (
<div>
<div className="flex items-center gap-2">
<span>This is the text to be copied.</span>
<CopyToClipboard text="This is the text to be copied." />
</div>
<p>
Note that the text rendered on the screen is independent of the text copied to the
clipboard …
</p>
<div className="flex items-center gap-2">
<span>This text, for example, is different from the text that’ll be copied …</span>
<CopyToClipboard
text="Clicking this button will copy the text you are currently reading"
ariaLabel="You can customize the ariaLabel for the prompt to copy"
/>
</div>
</div>
)
44 changes: 44 additions & 0 deletions libs/ui/lib/copy-to-clipboard/CopyToClipboard.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<button
className="text-tertiary hover:text-accent-secondary"
onClick={handleCopy}
type="button"
aria-label={hasCopied ? 'Copied' : ariaLabel}
>
{hasCopied ? (
<Success12Icon className="text-accent-secondary" />
) : (
<Clipboard16Icon className="h-3 w-3" />
)}
</button>
)
}
28 changes: 2 additions & 26 deletions libs/ui/lib/truncate/Truncate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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 <div>{text}</div>
}

const handleCopy = () => {
window.navigator.clipboard.writeText(text).then(() => {
setHasCopied(true)
})
}

// Only use the tooltip if the text is longer than maxLength
return (
<div className="flex items-center space-x-2">
<Tooltip content={text} delay={tooltipDelay}>
<div aria-label={text}>{truncate(text, maxLength, position)}</div>
</Tooltip>
{hasCopyButton &&
(hasCopied ? (
<Success12Icon className="text-accent-secondary" />
) : (
<button
className="text-tertiary hover:text-accent-secondary"
onClick={handleCopy}
type="button"
>
<Clipboard16Icon className="h-3 w-3" />
</button>
))}
{hasCopyButton && <CopyToClipboard text={text} />}
</div>
)
}
Expand Down