Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(react): add CopyButton component #1603

Merged
merged 18 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from 16 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
114 changes: 0 additions & 114 deletions docs/components/CopyToClipboardButton.tsx

This file was deleted.

33 changes: 27 additions & 6 deletions docs/components/Example.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,43 @@
import React from 'react';
import { Code } from '@deque/cauldron-react';
import CopyToClipboardButton from './CopyToClipboardButton';
import React, { useEffect, useState, useRef } from 'react';
import { Code, CopyButton } from '@deque/cauldron-react';
import './example.css';

interface ExampleProps extends React.HTMLAttributes<HTMLDivElement> {
raw: string;
}

export default function Example({ children, raw, ...props }: ExampleProps) {
const label = 'copy code example to clipboard';
const [accessibleName, setAccessibleName] = useState(label);
const ref = useRef<HTMLButtonElement>();

useEffect(() => {
// We don't know what context this button will be included in, so providing
// a minimal accessible name of "example, x of y"
const elements = Array.from(
document.querySelectorAll('[data-copy-example]')
);
const index = elements.findIndex((element) => element === ref.current);
if (index !== -1 && elements.length) {
setAccessibleName(`${label}, ${index + 1} of ${elements.length}`);
}
}, [raw]);

return (
<section className="Component__example" {...props}>
{children}
<div className="Component__example__code">
<Code children={raw} scrollable />
<CopyToClipboardButton
label="copy code example to clipboard"
<CopyButton
ref={ref}
data-copy-example
value={raw}
/>
notificationLabel="copied"
hideVisibleLabel
thin
>
{accessibleName}
</CopyButton>
</div>
</section>
);
Expand Down
1 change: 1 addition & 0 deletions docs/components/example.css
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ body.cauldron--theme-dark {
display: flex;
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
align-items: flex-start;
}

.Component__example__code pre.Code {
Expand Down
99 changes: 99 additions & 0 deletions docs/pages/components/CopyButton.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
title: CopyButton
description: An interactive component that copies the provided value to the user's clipboard when clicked.
source: https://github.com/dequelabs/cauldron/tree/develop/packages/react/src/components/CopyButton/index.tsx
---

import { CopyButton } from '@deque/cauldron-react'

```js
import { CopyButton } from '@deque/cauldron-react'
```

## Examples

### Default

```jsx example
<CopyButton value="text to copy" />
```

### Label

Both the accessible name and the notification label can be customized.

```jsx example
<CopyButton
value="body { color: green; }"
notificationLabel="CSS Selector Copied!"
>
Copy CSS Selector
</CopyButton>
```

### Hide Visible Label

When space is limited, the visible label of the button can be optionally hidden, with the label show on hover or focus with a tooltip.

```jsx example
<CopyButton
value="text to copy"
hideVisibleLabel
/>
```

### Variants

`CopyButton` is an extension of `Button` and limited variants are available to be used:

```jsx example
<CopyButton variant="primary" value="text to copy" />
<CopyButton variant="secondary" value="text to copy" thin />
```

## Props

Unless otherwise noted, prop types are inherited from [Button](./Button).

<ComponentProps
children={{
type: 'ContentNode',
description: 'The accessible name of the button. Defaults to "Copy".'
}}
refType="HTMLButtonElement"
props={[
{
name: 'value',
required: true,
description: 'The text to copy upon activation of the button.'
},
{
name: 'variant',
type: ['primary', 'secondary', 'tertiary'],
defaultValue: 'tertiary',
description: 'Visual style of the button.'
},
{
name: 'notificationLabel',
type: 'ContentNode',
defaultValue: '"Copied"',
description: 'The status notification that appears after the text has been copied.'
},
{
name: 'tooltipPlacement',
type: 'string',
defaultValue: 'auto',
description: 'The placement of the tooltip relative to the button.'
},
{
name: 'onCopy',
type: 'function',
description: 'Callback function invoked with the value of the copied text after the text has been copied.'
}

]}
/>

## Related Components

- [Button](./Button)
Binary file added e2e/screenshots/copybutton-condensed-.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added e2e/screenshots/copybutton-condensed-thin-.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added e2e/screenshots/copybutton-thin-.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added e2e/screenshots/copybutton.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added e2e/screenshots/dark--copybutton-condensed-.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added e2e/screenshots/dark--copybutton-thin-.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added e2e/screenshots/dark--copybutton.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@
"exclude": [
"lib",
"coverage",
"test/**/*.js"
"test/**/*.js",
"test/**/*.e2e.tsx"
]
}
}
Loading
Loading