InputsReact
A button that copies a text, such as a command, a link or a code.
Rendered by React 19.3.1
Installation
npm i @hamur/reactNot on npm yet. The package goes out under the chosen name.
Anatomy
Import the component and assemble its parts:
<Clipboard.Root>
<Clipboard.Value />
<Clipboard.Trigger>
<Clipboard.Indicator />
</Clipboard.Trigger>
</Clipboard.Root>
// Not in this example: Clipboard.Input, Clipboard.LabelExamples
Link
A share link in a read-only Input named by a Label, an icon Trigger, and a line showing each status and its reason.
Generated
A value function that makes a new ticket number on each press; the line shows the number and the status.
API reference
7 props across 6 parts, in React syntax. className, style, render are listed once, under Shared props.
IndicatorClipboard.Indicator
The Trigger's icon or text for each status, hidden from assistive technology: the status region says the result. Pick its content from the state with render or className, or with CSS on the data attributes. Renders a <span>.
| Data attribute | Description |
|---|---|
data-copying | Present while the value is being written. |
data-copied | Present after the copy succeeded, until the timeout. |
data-failed | Present after the copy failed, until the timeout. |
data-disabled | Present when the component is disabled. |
InputClipboard.Input
A read-only text field holding the value, selected on focus so it can be copied by hand. A copy from it counts as copied. Stays focusable while the component is disabled. Renders an <input>.
| Data attribute | Description |
|---|---|
data-copying | Present while the value is being written. |
data-copied | Present after the copy succeeded, until the timeout. |
data-failed | Present after the copy failed, until the timeout. |
data-disabled | Present when the component is disabled. |
LabelClipboard.Label
Names the Input and, with its own text, the Trigger. Renders a <label>.
| Data attribute | Description |
|---|---|
data-copying | Present while the value is being written. |
data-copied | Present after the copy succeeded, until the timeout. |
data-failed | Present after the copy failed, until the timeout. |
data-disabled | Present when the component is disabled. |
RootClipboard.Root
Groups all parts of the clipboard: a button that copies a text, with an optional label, field and display of the text., with the status region as its last child. Renders a <div>.
| Prop | Type | Default |
|---|---|---|
valuerequiredThe text written on a press, or a function called once per press that returns it or a | ClipboardValue | — |
timeoutThe milliseconds copied and failed last before the status returns to idle; | number | 2000 |
disabledWhether the component should ignore user interaction. | boolean | false |
onStatusChangeEvent handler called on every status change, copying and idle included. | ((status: ClipboardStatus, eventDetails: ClipboardStatusChangeEventDetails) => void) | — |
labelsThe texts, in English by default: the Trigger's name and the announcements. | Partial<ClipboardLabels> | — |
| Data attribute | Description |
|---|---|
data-copying | Present while the value is being written. |
data-copied | Present after the copy succeeded, until the timeout. |
data-failed | Present after the copy failed, until the timeout. |
data-disabled | Present when the component is disabled. |
TriggerClipboard.Trigger
A button that copies the value. Its name stays the same in every status: its text, or "Copy" when it has none, followed by the Label. Renders a <button>.
| Prop | Type | Default |
|---|---|---|
focusableWhenDisabledWhether the button stays focusable when disabled. | boolean | false |
nativeButtonWhether the component renders a native <button> element when replacing it | boolean | true |
| Data attribute | Description |
|---|---|
data-copying | Present while the value is being written. |
data-copied | Present after the copy succeeded, until the timeout. |
data-failed | Present after the copy failed, until the timeout. |
data-disabled | Present when the component is disabled. |
ValueClipboard.Value
Shows the value as text; its children replace it. Renders a <span>.
| Data attribute | Description |
|---|---|
data-copying | Present while the value is being written. |
data-copied | Present after the copy succeeded, until the timeout. |
data-failed | Present after the copy failed, until the timeout. |
data-disabled | Present when the component is disabled. |
Shared props
Every part that renders an element takes these.
| Prop | Type |
|---|---|
classNameCSS class applied to the element, or a function that
returns a class based on the component's state. | string | ((state: State) => string | undefined) |
styleStyle applied to the element, or a function that
returns a style object based on the component's state. | React.CSSProperties | ((state: State) => React.CSSProperties | undefined) |
renderAllows you to replace the component's HTML element
with a different tag, or compose it with another component. | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, State> |
Keyboard and accessibility
Keyboard
Clipboard has no keys of its own. The Trigger is a native button, so Enter and Space press it; Tab reaches the Input, which selects its whole value, and a copy from the keyboard there counts as copied too.
Accessibility
| Part | Sets | So that |
|---|---|---|
| Trigger | a button of type button named by its text, or "Copy" (labels) when it has none, followed by the Label | the name says what is copied and never changes, so focus stays put and nothing is re-read |
| Indicator | aria-hidden="true" | the icon or the word for each status is not read inside the button's name |
| Root | a div with no role, and a visually hidden polite, atomic status region as its last child, empty until a result | "Copied" or "Copy failed" is announced once, without moving focus (WCAG 4.1.3) |
| Input | type="text", readonly, the value, named by the Label; it selects its value on focus and stays focusable while disabled | the text can be read, selected and copied by hand when the browser refuses the write |
| Label | a label for the Input, and part of the Trigger's name | the field and the button are named by the same visible words |
| Value | a span with the value | a command or a code reads as text in the flow, with the button after it |
Focus order
- The Input, when there is one, then the Trigger: each one Tab stop.
- Focus stays on the Trigger through the press, the result and the return to
idle. - Nothing takes focus on mount or after a result.