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
5 changes: 5 additions & 0 deletions .changeset/inline-copy-text.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cloudflare/kumo": minor
---

Add `InlineCopyText`, a compact borderless copy control for short values in dense interfaces and table cells. It accepts string or rich children, Text typography props excluding heading variants, an explicit copied value for rich content, localized accessible labels, inline success feedback, and hover or focus icon reveal.
2 changes: 2 additions & 0 deletions packages/kumo-docs-astro/src/components/SearchDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ const COMPONENT_DESCRIPTIONS: Record<string, string> = {
checkbox:
"A control that allows the user to toggle between checked and not checked.",
"clipboard-text": "A text component with a copy-to-clipboard button.",
"inline-copy-text":
"A compact, borderless copy control for short inline values.",
collapsible:
"A vertically stacked set of interactive headings that each reveal content.",
combobox:
Expand Down
1 change: 1 addition & 0 deletions packages/kumo-docs-astro/src/components/SidebarNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const componentItems: NavItem[] = [
{ label: "Empty", href: "/components/empty" },
{ label: "Flow", href: "/components/flow" },
{ label: "Grid", href: "/components/grid" },
{ label: "Inline Copy Text", href: "/components/inline-copy-text" },
{ label: "Input", href: "/components/input" },
{ label: "InputArea", href: "/components/input-area" },
{ label: "InputGroup", href: "/components/input-group" },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { InlineCopyText } from "@cloudflare/kumo";

/** Compact copy control for a short identifier. */
export function InlineCopyTextBasicDemo() {
return (
<InlineCopyText
labels={{ copyAction: "Copy database ID", copied: "Database ID copied" }}
>
f86b3f10-32e9-4db7-ae95-84a1b2c3d4e5
</InlineCopyText>
);
}

/** Inline copy text inside a dense, hoverable resource row. */
export function InlineCopyTextResourceRowDemo() {
return (
<div className="group flex w-full max-w-xl items-center justify-between gap-4 rounded-lg bg-kumo-base px-4 py-3 ring ring-kumo-line">
<span className="min-w-0 truncate text-sm text-kumo-default">
Production database
</span>
<InlineCopyText
labels={{
copyAction: "Copy database ID",
copied: "Database ID copied",
}}
>
f86b3f10-32e9-4db7-ae95-84a1b2c3d4e5
</InlineCopyText>
</div>
);
}

/** Display rich content while copying its underlying value. */
export function InlineCopyTextRichContentDemo() {
return (
<InlineCopyText
value="f86b3f10-32e9-4db7-ae95-84a1b2c3d4e5"
variant="body"
labels={{ copyAction: "Copy database ID", copied: "Database ID copied" }}
>
<span>
Database ID: <strong>f86b3f10…</strong>
</span>
</InlineCopyText>
);
}
90 changes: 90 additions & 0 deletions packages/kumo-docs-astro/src/pages/components/inline-copy-text.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
layout: ~/layouts/MdxDocLayout.astro
title: "Inline Copy Text"
description: "A compact, borderless copy control for short inline values."
sourceFile: "components/inline-copy-text"
---

import ComponentExample from "~/components/docs/ComponentExample.astro";
import ComponentSection from "~/components/docs/ComponentSection.astro";
import PropsTable from "~/components/docs/PropsTable.astro";
import {
InlineCopyTextBasicDemo,
InlineCopyTextResourceRowDemo,
InlineCopyTextRichContentDemo,
} from "~/components/demos/InlineCopyTextDemo";

<ComponentSection>
<ComponentExample demo="InlineCopyTextBasicDemo">
<InlineCopyTextBasicDemo client:visible />
</ComponentExample>
</ComponentSection>

<ComponentSection>

## Installation

### Barrel

```tsx
import { InlineCopyText } from "@cloudflare/kumo";
```

### Granular

```tsx
import { InlineCopyText } from "@cloudflare/kumo/components/inline-copy-text";
```

</ComponentSection>

<ComponentSection>

## Usage

Use `InlineCopyText` for short identifiers and values in dense interfaces such as table cells. Use [`ClipboardText`](/components/clipboard-text) when the value should appear in a read-only, input-like field with an always-visible copy button.

```tsx
import { InlineCopyText } from "@cloudflare/kumo";

export default function Example() {
return (
<InlineCopyText
labels={{ copyAction: "Copy database ID", copied: "Database ID copied" }}
>
f86b3f10-32e9-4db7-ae95-84a1b2c3d4e5
</InlineCopyText>
);
}
```

</ComponentSection>

<ComponentSection>

## Examples

### Resource row

An enclosing Tailwind `group` can reveal the copy icon when the entire row is hovered or receives focus within.

<ComponentExample demo="InlineCopyTextResourceRowDemo">
<InlineCopyTextResourceRowDemo client:visible />
</ComponentExample>

### Rich content

String children are copied by default. When the children are not a string, provide the required `value` prop with the value to copy. `InlineCopyText` also accepts Text props such as `variant`, `size`, `bold`, `truncate`, and `as`; heading variants are not supported.

<ComponentExample demo="InlineCopyTextRichContentDemo">
<InlineCopyTextRichContentDemo client:visible />
</ComponentExample>

</ComponentSection>

<ComponentSection>

## API Reference

<PropsTable component="InlineCopyText" />
</ComponentSection>
4 changes: 4 additions & 0 deletions packages/kumo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@
"types": "./dist/components/grid.d.ts",
"import": "./dist/components/grid.js"
},
"./components/inline-copy-text": {
"types": "./dist/components/inline-copy-text.d.ts",
"import": "./dist/components/inline-copy-text.js"
},
"./components/input": {
"types": "./dist/components/input.d.ts",
"import": "./dist/components/input.js"
Expand Down
1 change: 1 addition & 0 deletions packages/kumo/scripts/component-registry/discovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const CATEGORY_MAP: Record<string, string> = {
button: "Action",
"button-group": "Action",
"clipboard-text": "Action",
"inline-copy-text": "Action",
// Display
badge: "Display",
breadcrumbs: "Display",
Expand Down
37 changes: 37 additions & 0 deletions packages/kumo/scripts/component-registry/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,43 @@ export const ADDITIONAL_COMPONENT_PROPS: Record<
string,
Record<string, PropSchema>
> = {
InlineCopyText: {
children: {
type: "ReactNode",
required: true,
description:
"Content to display. String children are copied unless `value` is provided.",
},
value: {
type: "string",
description:
"The value to copy. Required when `children` is not a string.",
},
variant: {
type: '"body" | "secondary" | "success" | "error" | "mono" | "mono-secondary"',
optional: true,
description:
"Text style variant. Supports every Text variant except heading variants.",
values: [
"body",
"secondary",
"success",
"error",
"mono",
"mono-secondary",
],
default: '"mono-secondary"',
},
size: {
type: '"xs" | "sm" | "base" | "lg"',
description: "Text size. Supported values depend on the text variant.",
},
bold: {
type: "boolean",
description:
"Whether to use medium font weight. Only applies to body text variants.",
},
},
Meter: {
value: {
type: "number",
Expand Down
8 changes: 8 additions & 0 deletions packages/kumo/src/components/inline-copy-text/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export {
InlineCopyText,
KUMO_INLINE_COPY_TEXT_DEFAULT_VARIANTS,
KUMO_INLINE_COPY_TEXT_STYLING,
KUMO_INLINE_COPY_TEXT_VARIANTS,
type InlineCopyTextLabels,
type InlineCopyTextProps,
} from "./inline-copy-text";
Loading
Loading