Copy button made with web components
npm install @substrate-system/copy-button
An icon button to copy some text to the system clipboard,
made with webcomponents.
Contents
- Install
- Demonstration
- Globals
- Use
* Example with hint text
* Example without a build step
* With a build step
* /copy
* /html
* /client
- CSS
- Attributes
* payload
* duration
* hint
* Screenshots
sh
npm i -S @substrate-system/copy-button
`> [!IMPORTANT]
> Be sure to import
@substrate-system/a11y too.Demonstration
See substrate-system.github.io/copy-button for an example.
Globals
This depends on @substrate-system/a11y for a .visually-hidden class. Install
and import that module as well.CSS variables
--copy-button-success and --copy-button determine the color
of the success checkmark and copy icon.Use
Include this package in your javascript, then use the element in HTML.
Be sure to import @substrate-system/a11y
too; we use class names exposed there for accessible icons.`js
import { CopyButton } from '@substrate-system/copy-button'
import '@substrate-system/a11y'
import '@substrate-system/copy-button/css'
``html
`$3
`html
`$3
#### Copy the files
Copy files so they are accessible by your web server.
##### JS
`sh
cp ./node_modules/@substrate-system/copy-button/dist/index.min.js public/copy-button.js
`##### CSS
`sh
cp ./node_modules/@substrate-system/copy-button/dist/style.min.css public/copy-button.css
`#### Use in HTML
`html
`$3
We expose several import options`js
// default, unminified
import '@substrate-system/copy-button'// minified
import '@substrate-system/copy-button/min'
// style
import '@substrate-system/copy-button/css'
// style, minifed
import '@substrate-system/copy-button/css/min'
`In
vite, for example, import like this`js
import '@substrate-system/copy-button'
import '@substrate-system/copy-button/css'
// or minified css
import '@substrate-system//copy-button/css/min'
`$3
Import just the copy function, no UI. This gives you access to the underlying
clipboard functionality without the web component interface.
#### Basic Usage
`js
import { clipboardCopy } from '@substrate-system/copy-button/copy'clipboardCopy('hello copies')
`#### Handle Errors
The
clipboardCopy function is an async function that returns a Promise,
so you can handle success and error cases:`js
import { clipboardCopy } from '@substrate-system/copy-button/copy'async function handleCopy() {
try {
await clipboardCopy('Text to copy to clipboard')
console.log('Text copied successfully!')
} catch (error) {
console.error('Failed to copy text:', error)
// Handle the error (e.g., show user feedback)
}
}
`#### Copy Multi-line Text
The function preserves formatting including newlines and spaces.
`js
import { clipboardCopy } from '@substrate-system/copy-button/copy'const multilineText =
Line 1clipboardCopy(multilineText)
`#### Browser Compatibility
The
clipboardCopy function automatically handles browser compatibility:- Modern browsers: Use the
Clipboard API,
navigator.clipboard.writeText(), when available
- Fallback: Use the legacy document.execCommand('copy') method for
older browsers
- Security: Requires a secure context (HTTPS) for the Clipboard API,
but falls back gracefully
#### Error Handling
The function may throw a
DOMException with name 'NotAllowedError'
in the following cases:- The page is not served over HTTPS (for Clipboard API)
- The user has not interacted with the page recently (security requirement)
- The browser doesn't support either clipboard method
- Permission is denied by the browser
`js
import { clipboardCopy } from '@substrate-system/copy-button/copy'try {
await clipboardCopy('secure content')
} catch (error) {
if (error.name === 'NotAllowedError') {
console.log('Clipboard access was denied or not available')
// Perhaps show alternative instructions to the user
} else {
}
}
`$3
Import just the HTML generation functions for server-side rendering.
This gives you access to static HTML generation without the web
component behavior, perfect for SSR frameworks like Next.js, SvelteKit, or
Node.js backends.
#### Basic Usage
`js
import { CopyButton } from '@substrate-system/copy-button/html'// Generate a simple copy button
const buttonHTML = CopyButton()
console.log(buttonHTML)
// Output:
`#### With Custom Classes
`js
import { CopyButton } from '@substrate-system/copy-button/html'// Add custom CSS classes
const buttonHTML = CopyButton(['my-custom-class', 'another-class'])
console.log(buttonHTML)
// Output:
`#### Generate Complete Web Component HTML
Use
CopyButton.outerHTML() to generate the full web component markup:`js
import { CopyButton } from '@substrate-system/copy-button/html'// Basic web component
const componentHTML = CopyButton.outerHTML()
console.log(componentHTML)
// Output:
//
//
// With custom classes and attributes
const customHTML = CopyButton.outerHTML(['custom-class'], { noOutline: true })
console.log(customHTML)
// Output:
//
//
`#### Individual SVG Icons
Access the individual SVG icons for custom implementations:
`js
import { CopySvg, SuccessSvg } from '@substrate-system/copy-button/html'// Copy icon SVG
const copyIcon = CopySvg()
console.log(copyIcon)
// Output:
// Success checkmark SVG
const successIcon = SuccessSvg()
console.log(successIcon)
// Output:
`#### Server-Side Rendering Examples
Next.js:
`js
// pages/index.js or app/page.js
import { CopyButton } from '@substrate-system/copy-button/html'export default function HomePage() {
const copyButtonHTML = CopyButton.outerHTML(['my-button'])
return (
My App
)
}
`SvelteKit:
`js
// src/routes/+page.server.js
import { CopyButton } from '@substrate-system/copy-button/html'export function load() {
return {
copyButtonHTML: CopyButton.outerHTML()
}
}
``svelte
My App
{@html data.copyButtonHTML}
`Express.js:
`js
// server.js
import express from 'express'
import { CopyButton } from '@substrate-system/copy-button/html'const app = express()
app.get('/', (req, res) => {
const copyButtonHTML = CopyButton.outerHTML()
res.send(
)
})
`#### Hydration Notes
When using server-side rendering, you'll typically want to hydrate the
static HTML with the interactive web component on the client side:
1. Include the CSS: Import or link the copy-button CSS file
2. Register the component: Import and register the web component in your
client-side JavaScript
3. Set attributes: The
payload attribute should be set on the
element, not the inner