Copyable
Truncated mono text with a copy affordance for IDs and free-form surfaces, with an optional host Link.
Copyable shows a truncated, mono value and copies the full string via Copy Affordance. Use it on detail panels, headers, and free-form layouts — not as a substitute for schema-driven table cells.
When To Use
- Show a UUID, task id, or similar opaque string where the full value must be copyable but the display should stay short.
- Prefer
CopyableCellinside clickable table rows so the copy control does not fire row navigation. - Set
hrefwhen the truncated text should navigate through the hostLinkProvider/useResolvedLink. - Use schema
copyable: trueon Field Types for list/detail cells — use Copyable when you are composing outside that schema surface. - Do not introduce a second clipboard stack; Copyable always composes Copy Affordance, which shares
useClipboardCopywith message / code shells — see the Copy Affordance shell matrix.
Features
| Area | Behavior |
|---|---|
| Truncation | Default middle truncate (UUID_COPYABLE_TRUNCATE: prefix 8 / suffix 4); override or pass false |
| Clipboard | Copies the full value through Copy Affordance → useClipboardCopy (Copy / Copied labels) |
| Link | Optional href resolves via useResolvedLink / LinkProvider |
| Row safety | CopyableCell stops click propagation for table row handlers |
Installing
pnpm dlx shadcn@latest add https://ui.isaacfei.com/r/copyable.jsonnpx shadcn@latest add https://ui.isaacfei.com/r/copyable.jsonyarn dlx shadcn@latest add https://ui.isaacfei.com/r/copyable.jsonbun x shadcn@latest add https://ui.isaacfei.com/r/copyable.jsonWith a namespace: npx shadcn@latest add @f-ui/copyable.
registryDependencies: https://ui.isaacfei.com/r/copy-affordance.json, https://ui.isaacfei.com/r/link.json. Runtime npm: lucide-react (via Copy Affordance).
Usage
import { Copyable, CopyableCell } from "@/components/f-ui/copyable/copyable";
<Copyable value="12345678-aaaa-bbbb-cccc-ddddeeeeffff" />
<CopyableCell value={taskId} href={`/tasks/${taskId}`} />Examples
Plain Id
Middle-truncated mono text with an always-visible copy button. Hover the value for the full string in the native tooltip.
12345678…ffff"use client";
import { Copyable } from "@/components/f-ui/copyable/copyable";
const SAMPLE_UUID = "12345678-aaaa-bbbb-cccc-ddddeeeeffff";
export function CopyableDemo() {
return <Copyable value={SAMPLE_UUID} visibility="always" />;
}Linked Id
Same truncation and copy behavior, with the text wired as a host link (href="#" in the demo).
"use client";
import { Copyable } from "@/components/f-ui/copyable/copyable";
const SAMPLE_UUID = "12345678-aaaa-bbbb-cccc-ddddeeeeffff";
export function CopyableLinkDemo() {
return <Copyable value={SAMPLE_UUID} href="#" visibility="always" />;
}Composition
Copyable
└── CopyAffordance
├── code | ResolvedLink (truncated display, title = full value)
└── copy buttonCopyableCell wraps Copyable in a div that calls stopPropagation on click.
API Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Full string to display (truncated) and copy. |
truncate | TruncatedTextOptions | false | UUID_COPYABLE_TRUNCATE | Truncation options, or false for the full string. |
href | string | — | When set, display renders through the resolved Link instead of <code>. |
visibility | "hover" | "always" | "hover" | Copy button visibility (passed to Copy Affordance). |
showCopy | boolean | true | When false, hides the copy button. |
className | string | — | Merged onto the Copy Affordance root. |
CopyableCell
Same props as Copyable. Stops click propagation so nested use inside row-click tables does not trigger the row handler.
Constants
| Export | Description |
|---|---|
UUID_COPYABLE_TRUNCATE | { mode: "middle", prefix: 8, suffix: 4 } — default truncate for UUID-shaped ids. |