Clipboard
The clipboard machine lets users quickly copy content to the clipboard.
Installation
Install the clipboard package:
npm install @zag-js/clipboard @zag-js/react # or yarn add @zag-js/clipboard @zag-js/react
npm install @zag-js/clipboard @zag-js/solid # or yarn add @zag-js/clipboard @zag-js/solid
npm install @zag-js/clipboard @zag-js/vue # or yarn add @zag-js/clipboard @zag-js/vue
npm install @zag-js/clipboard @zag-js/svelte # or yarn add @zag-js/clipboard @zag-js/svelte
Anatomy
Check the clipboard anatomy and part names.
Each part includes a
data-partattribute to help identify them in the DOM.
Usage
Import the clipboard package:
import * as clipboard from "@zag-js/clipboard"
The clipboard package exports two key functions:
machine- State machine logic.connect- Maps machine state to JSX props and event handlers.
Pass a unique
idtouseMachineso generated element ids stay predictable.
Then use the framework integration helpers:
import * as clipboard from "@zag-js/clipboard" import { useMachine, normalizeProps } from "@zag-js/react" import { ClipboardCheck, ClipboardCopyIcon } from "lucide-react" import { useId } from "react" function Clipboard() { const service = useMachine(clipboard.machine, { id: useId(), value: "https://github.com/chakra-ui/zag", }) const api = clipboard.connect(service, normalizeProps) return ( <div {...api.getRootProps()}> <label {...api.getLabelProps()}>Copy this link</label> <div {...api.getControlProps()}> <input {...api.getInputProps()} /> <button {...api.getTriggerProps()}> {api.copied ? <ClipboardCheck /> : <ClipboardCopyIcon />} </button> </div> </div> ) }
import * as clipboard from "@zag-js/clipboard" import { useMachine, normalizeProps } from "@zag-js/solid" import { ClipboardCheck, ClipboardCopyIcon } from "lucide-solid" import { createMemo, createUniqueId } from "solid-js" function Clipboard() { const service = useMachine(clipboard.machine, { id: createUniqueId(), value: "https://github.com/chakra-ui/zag", }) const api = createMemo(() => clipboard.connect(service, normalizeProps)) return ( <div {...api().getRootProps()}> <label {...api().getLabelProps()}>Copy this link</label> <div {...api().getControlProps()}> <input {...api().getInputProps()} /> <button {...api().getTriggerProps()}> <Show when={api().copied} fallback={<ClipboardCopyIcon />}> <ClipboardCheck /> </Show> </button> </div> </div> ) }
<script setup> import * as clipboard from "@zag-js/clipboard" import { useMachine, normalizeProps } from "@zag-js/vue" import { ClipboardCheck, ClipboardCopyIcon } from "lucide-vue-next" import { computed } from "vue" const service = useMachine(clipboard.machine, { id: "1", value: "https://github.com/chakra-ui/zag", }) const api = computed(() => clipboard.connect(service, normalizeProps)) </script> <template> <div v-bind="api.getRootProps()"> <label v-bind="api.getLabelProps()">Copy this link</label> <div v-bind="api.getControlProps()"> <input v-bind="api.getInputProps()" style="width: 100%" /> <button v-bind="api.getTriggerProps()"> <ClipboardCheck v-if="api.copied" /> <ClipboardCopyIcon v-else /> </button> </div> </div> </template>
<script lang="ts"> import * as clipboard from "@zag-js/clipboard" import { useMachine, normalizeProps } from "@zag-js/react" import { ClipboardCheck, ClipboardCopyIcon } from "lucide-svelte" import { useId } from "react" const id = $props.id() const service = useMachine( clipboard.machine, ({ id: id, value: "https://github/com/chakra-ui/zag", }), ) const api = $derived(clipboard.connect(service, normalizeProps)) </script> <div {...api.getRootProps()}> <label {...api.getLabelProps()}>Copy this link</label> <div {...api.getControlProps()}> <input {...api.getInputProps()} /> <button {...api.getTriggerProps()}> {api.copied ? <ClipboardCheck /> : <ClipboardCopyIcon />} </button> </div> </div>
Setting the clipboard value
Set value to control what gets copied.
const service = useMachine(clipboard.machine, { value: "Hello, world!", })
Setting an initial value
Use defaultValue for uncontrolled initial value.
const service = useMachine(clipboard.machine, { defaultValue: "Hello, world!", })
Listening for value changes
Use onValueChange to react when the clipboard value changes.
const service = useMachine(clipboard.machine, { onValueChange(details) { console.log("Value changed to", details.value) }, })
Listening to copy events
When the value is copied, onStatusChange is fired.
const service = useMachine(clipboard.machine, { onStatusChange: (details) => { console.log("Copy status changed to", details.copied) }, })
Checking if the value is copied
Use api.copied to check if the value was copied.
const api = clipboard.connect(service) if (api.copied) { console.log("Value is copied to the clipboard") }
Changing the timeout
By default, the copied feedback resets after 3000ms. Set timeout to change
this delay.
const service = useMachine(clipboard.machine, { timeout: 5000, })
Styling guide
Each part includes a data-part attribute you can target in CSS.
[data-scope="clipboard"][data-part="root"] { /* styles for the root part */ }
Methods and Properties
Machine Context
The clipboard machine exposes the following context properties:
idsPartial<{ root: string; input: string; label: string; }>The ids of the elements in the clipboard. Useful for composition.valuestringThe controlled value of the clipboarddefaultValuestringThe initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard.onValueChange(details: ValueChangeDetails) => voidThe function to be called when the value changesonStatusChange(details: CopyStatusDetails) => voidThe function to be called when the value is copied to the clipboardtimeoutnumberThe timeout for the copy operationidstringThe unique identifier of the machine.getRootNode() => ShadowRoot | Node | DocumentA root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.
Machine API
The clipboard api exposes the following methods:
copiedbooleanWhether the value has been copied to the clipboardvaluestringThe value to be copied to the clipboardsetValue(value: string) => voidSet the value to be copied to the clipboardcopyVoidFunctionCopy the value to the clipboard