Clipboard
A simple component to copy text to the clipboard
import { CheckIcon, ClipboardCopyIcon } from 'lucide-react'
import { Clipboard } from '~/components/ui/clipboard'
import { FormLabel } from '~/components/ui/form-label'
import { IconButton } from '~/components/ui/icon-button'
import { Input } from '~/components/ui/input'
export const Demo = (props: Clipboard.RootProps) => {
return (
<Clipboard.Root value="https://park-ui.com" {...props}>
<Clipboard.Label asChild>
<FormLabel>Copy this link</FormLabel>
</Clipboard.Label>
<Clipboard.Control>
<Clipboard.Input asChild>
<Input />
</Clipboard.Input>
<Clipboard.Trigger asChild>
<IconButton variant="outline">
<Clipboard.Indicator copied={<CheckIcon />}>
<ClipboardCopyIcon />
</Clipboard.Indicator>
</IconButton>
</Clipboard.Trigger>
</Clipboard.Control>
</Clipboard.Root>
)
}
import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid'
import { Clipboard } from '~/components/ui/clipboard'
import { FormLabel } from '~/components/ui/form-label'
import { IconButton } from '~/components/ui/icon-button'
import { Input } from '~/components/ui/input'
export const Demo = (props: Clipboard.RootProps) => {
return (
<Clipboard.Root value="https://park-ui.com" {...props}>
<Clipboard.Label asChild={(labelProps) => <FormLabel {...labelProps()} />}>
Copy this link
</Clipboard.Label>
<Clipboard.Control>
<Clipboard.Input asChild={(inputProps) => <Input {...inputProps()} />} />
<Clipboard.Trigger
asChild={(triggerProps) => (
<IconButton variant="outline" {...triggerProps()}>
<Clipboard.Indicator copied={<CheckIcon />}>
<ClipboardCopyIcon />
</Clipboard.Indicator>
</IconButton>
)}
/>
</Clipboard.Control>
</Clipboard.Root>
)
}
Usage
import { Clipboard } from '~/components/ui/clipboard'
Installation
npx @park-ui/cli components add clipboard
1
Add Styled Primitive
Copy the code snippet below into ~/components/ui/styled/clipboard.tsx
'use client'
import type { Assign } from '@ark-ui/react'
import { Clipboard } from '@ark-ui/react/clipboard'
import { type ClipboardVariantProps, clipboard } from 'styled-system/recipes'
import type { ComponentProps, HTMLStyledProps } from 'styled-system/types'
import { createStyleContext } from './utils/create-style-context'
const { withProvider, withContext } = createStyleContext(clipboard)
export type RootProviderProps = ComponentProps<typeof RootProvider>
export const RootProvider = withProvider<
HTMLDivElement,
Assign<Assign<HTMLStyledProps<'div'>, Clipboard.RootProviderBaseProps>, ClipboardVariantProps>
>(Clipboard.RootProvider, 'root')
export type RootProps = ComponentProps<typeof Root>
export const Root = withProvider<
HTMLDivElement,
Assign<Assign<HTMLStyledProps<'div'>, Clipboard.RootBaseProps>, ClipboardVariantProps>
>(Clipboard.Root, 'root')
export const Control = withContext<
HTMLDivElement,
Assign<HTMLStyledProps<'div'>, Clipboard.ControlBaseProps>
>(Clipboard.Control, 'control')
export const Indicator = withContext<
HTMLDivElement,
Assign<HTMLStyledProps<'div'>, Clipboard.IndicatorBaseProps>
>(Clipboard.Indicator, 'indicator')
export const Input = withContext<
HTMLInputElement,
Assign<HTMLStyledProps<'input'>, Clipboard.InputBaseProps>
>(Clipboard.Input, 'input')
export const Label = withContext<
HTMLLabelElement,
Assign<HTMLStyledProps<'label'>, Clipboard.LabelBaseProps>
>(Clipboard.Label, 'label')
export const Trigger = withContext<
HTMLButtonElement,
Assign<HTMLStyledProps<'button'>, Clipboard.TriggerBaseProps>
>(Clipboard.Trigger, 'trigger')
export { ClipboardContext as Context } from '@ark-ui/react/clipboard'
import { type Assign, Clipboard } from '@ark-ui/solid'
import type { ComponentProps } from 'solid-js'
import { type ClipboardVariantProps, clipboard } from 'styled-system/recipes'
import type { HTMLStyledProps } from 'styled-system/types'
import { createStyleContext } from './utils/create-style-context'
const { withProvider, withContext } = createStyleContext(clipboard)
export type RootProviderProps = ComponentProps<typeof RootProvider>
export const RootProvider = withProvider<
Assign<Assign<HTMLStyledProps<'div'>, Clipboard.RootProviderBaseProps>, ClipboardVariantProps>
>(Clipboard.RootProvider, 'root')
export type RootProps = ComponentProps<typeof Root>
export const Root = withProvider<
Assign<Assign<HTMLStyledProps<'div'>, Clipboard.RootBaseProps>, ClipboardVariantProps>
>(Clipboard.Root, 'root')
export const Control = withContext<Assign<HTMLStyledProps<'div'>, Clipboard.ControlBaseProps>>(
Clipboard.Control,
'control',
)
export const Indicator = withContext<Assign<HTMLStyledProps<'div'>, Clipboard.IndicatorBaseProps>>(
Clipboard.Indicator,
'indicator',
)
export const Input = withContext<Assign<HTMLStyledProps<'input'>, Clipboard.InputBaseProps>>(
Clipboard.Input,
'input',
)
export const Label = withContext<Assign<HTMLStyledProps<'label'>, Clipboard.LabelBaseProps>>(
Clipboard.Label,
'label',
)
export const Trigger = withContext<Assign<HTMLStyledProps<'button'>, Clipboard.TriggerBaseProps>>(
Clipboard.Trigger,
'trigger',
)
export { ClipboardContext as Context } from '@ark-ui/solid'
No snippet found
2
Add Re-Export
To improve the developer experience, re-export the styled primitives in~/components/ui/clipboard.tsx
.
export * as Clipboard from './styled/clipboard'
export * as Clipboard from './styled/clipboard'
3
Integrate Recipe
If you're not using @park-ui/preset
, add the following recipe to yourpanda.config.ts
:
import { clipboardAnatomy } from '@ark-ui/anatomy'
import { defineSlotRecipe } from '@pandacss/dev'
export const clipboard = defineSlotRecipe({
className: 'clipboard',
slots: clipboardAnatomy.keys(),
base: {
root: {
display: 'flex',
flexDirection: 'column',
gap: '1.5',
},
control: {
display: 'flex',
gap: '3',
},
},
})