CopyButton
Copies text to the clipboard and says so for a moment, to the eye and to screen readers.
Demo
quillo run app.qweGet it
It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.
$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/copy_button.qwemain.qwe
import ui/theme.qwe use theme_cssuse ui/copy_button.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>Example
The code of the preview above.
demos/copy_button.qwe
view CopyButtonDemo() = <div.demo-stack> <div.demo-row> <code style="padding: 8px 12px; border-radius: var(--ui-radius-sm); background: var(--ui-subtle); font: 13px var(--ui-mono)">quillo run app.qwe</code> <CopyButton text="quillo run app.qwe"/> </div> <div.demo-row> <CopyButton text="https://quillolang.org/components/" label="Copy link" variant="soft" size="sm"/> <CopyButton text="demo-key-not-a-secret" label="Copy key" done="Key copied" variant="ghost"/> </div> </div>Source
ui/copy_button.qwe
// CopyButton: copies a piece of text to the clipboard, then says "Copied" for a// moment (and tells screen readers so).//// <CopyButton text={invite_link}/>// <CopyButton text={api_key} label="Copy key" variant="soft" size="sm"/>//// text: what it copies. label ("Copy") and done ("Copied"): what it says before// and after; failed ("Could not copy") shows if the browser refuses (the page is// not https, or the user said no).// variant: "outline" (default), "soft", "ghost" or "solid"; size: "sm", "md" or "lg".// It is styled as a Button when button_css is on the page.import ui/theme.qwe use ui_clslet copy_button_css = css`.ui-copy-btn { position: relative; }.ui-copy-btn svg { width: 16px; height: 16px; flex: none; }.ui-copy-btn .ui-copy-check, .ui-copy-ok .ui-copy-icon { display: none; }.ui-copy-ok .ui-copy-check { display: block; color: var(--ui-success); }.ui-copy-labels { display: inline-grid; }.ui-copy-labels > span { grid-area: 1 / 1; text-align: center; }.ui-copy-btn:not(.ui-copy-ok) .ui-copy-done, .ui-copy-ok .ui-copy-label { visibility: hidden; }.ui-copy-fail, .ui-copy-bad .ui-copy-label, .ui-copy-bad .ui-copy-done { display: none; }.ui-copy-bad .ui-copy-fail { display: inline; }`component CopyButton(text: str, label: str = "Copy", done: str = "Copied", failed: str = "Could not copy", variant: str = "outline", size: str = "md", class: str? = null) { style global copy_button_css state result = "" // "", "ok" or "bad" if result != "" { every(1500, () => { result = "" }) } <span> <button type="button" class={ui_cls(["ui-btn", `ui-btn-${variant}`, size != "md" && `ui-btn-${size}`, "ui-copy-btn", result != "" && `ui-copy-${result}`, class])} @click={() => { if js("isSecureContext") != true { result = "bad" } else { // The promise's callbacks are given undefined, which is no argument: hence `= null`. js("navigator.clipboard.writeText", text).then((_ = null) => { result = "ok" }, (_ = null) => { result = "bad" }) } }}> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path class="ui-copy-icon" d="M10 8h10a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H10a2 2 0 0 1-2-2V10a2 2 0 0 1 2-2ZM4 16a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2"/> <path class="ui-copy-check" d="M20 6 9 17l-5-5"/> </svg> <span.ui-copy-labels> <span.ui-copy-label>{label}</span> <span.ui-copy-done aria-hidden="true">{done}</span> <span.ui-copy-fail aria-hidden="true">{failed}</span> </span> </button> <span.ui-sr role="status">{result == "ok" ? done : result == "bad" ? failed : ""}</span> </span>}Related
BookmarkButtonA save-for-later toggle whose bookmark fills when pressed, with or without its label.8 views · 8 downloadsButtonA button, or a link that looks like one: four variants, three tones, three sizes, loading.7 views · 7 downloadsButtonGroupButtons joined edge to edge into one control, or spaced in a row; across or upright.6 views · 6 downloadsDownloadButtonA link that downloads a file, showing its kind and size so nobody is surprised by a big one.7 views · 6 downloadsDropdownMenuA button that opens a short list of links and actions; Escape or a click elsewhere closes it.6 views · 7 downloadsFabA round floating action button fixed to a corner of the screen, with an icon and an optional label.5 views · 7 downloads
Thread
Thread 0 posts
On CopyButton: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.