Components

Clipboard

Headless text-copy behavior with coordinated value, native controls, truthful asynchronous status, and accessible authored feedback.

When to Use

Use Clipboard when a user needs to copy a known text value, such as a command, URL, token, or code sample. Applications provide all styling, icons, and status wording. Clipboard does not read, paste, cut, or copy binary data.

Import

import { Clipboard } from "@flowstack-ui/atom";
// or: import { Clipboard } from "@flowstack-ui/atom/clipboard";

Anatomy

<Clipboard.Root defaultValue="npm install @flowstack-ui/atom">
  <Clipboard.Label>Install command</Clipboard.Label>
  <Clipboard.Control>
    <Clipboard.Input readOnly />
    <Clipboard.Trigger>Copy</Clipboard.Trigger>
  </Clipboard.Control>
  <Clipboard.Status>
    <Clipboard.Indicator when="copying">Copying…</Clipboard.Indicator>
    <Clipboard.Indicator when="copied">Copied</Clipboard.Indicator>
    <Clipboard.Indicator when="error">Copy failed</Clipboard.Indicator>
  </Clipboard.Status>
</Clipboard.Root>

Behavior

Trigger writes Root's current value with navigator.clipboard.writeText. State moves through idle, copying, and either copied or error; copied and error reset to idle after timeout. A newer attempt always wins over an older pending attempt. Atom does not claim success when the browser rejects or lacks the API, and it does not use the deprecated execCommand fallback.

API Reference

Root

PropTypeDefault
valuestring-
defaultValuestring""
onValueChange(value: string) => void-
disabledbooleanfalse
timeoutnumber3000
onStatusChange(details: { status; error? }) => void-
writeValue(value: string) => void | Promise<void>Clipboard API
render / asChildRenderProp / boolean- / false

writeValue is an explicit adapter for controlled environments and tests. Its resolution or rejection remains authoritative.

Parts

  • Label renders label and associates itself with Input.
  • Control renders a structural div.
  • Input renders an editable native text input coordinated with Root value.
  • ValueText renders Root value when children are omitted.
  • Trigger renders button type="button"; render and asChild are supported.
  • Indicator renders only while its required when state matches.
  • Status renders a polite, atomic role="status" live region.

Native props and refs pass through. Consumer Trigger handlers run first; preventDefault() cancels the copy attempt.

Data Attributes

Data attributeValues
[data-slot]Part-specific default or consumer override
[data-state]idle, copying, copied, error
[data-disabled]Present while disabled

Accessibility

  • Give Trigger a stable accessible name such as “Copy install command.”
  • Put short authored feedback inside Status; Atom supplies no English strings.
  • Use Label with Input whenever the editable or read-only value is exposed.
  • Keep keyboard focus on Trigger after success or failure.
  • Clipboard writes require a secure context and may require user activation or browser permission. Preserve the error presentation instead of implying the write succeeded.

Server Rendering

Clipboard is a client primitive because it owns state, event handlers, timers, and a browser API. Initial markup is deterministic in the idle state; copying only begins from Trigger activation after hydration.

  • Button supplies headless activation without clipboard state.
  • Input supplies general form input behavior.
  • Styled libraries may compose Clipboard into a Code Block copy control.

Changelog

0.8.0

  • Added controlled and uncontrolled text values, native Label/Input relationships, asynchronous copy status, timeout reset, latest-operation concurrency, disabled state, authored live feedback, and composition APIs.