component Clipboard { outputs { copy(payload: { value: string; sourceEvent?: Event }) success(payload: { value: string; sourceEvent?: Event }) error(payload: { error: Error | string; value: string; sourceEvent?: Event }) } props { value: string = "" label: string = "Copy" copiedLabel: string = "Copied" errorLabel: string = "Copy failed" title: string = "Clipboard" description: string = "" iconOnly: boolean = false code: boolean = true size: string = "default" color: string = "primary" disabled: boolean = false class: string = "" } state status = "idle" functions { client function resetStatus() { status = "idle" } client function copySucceeded() { status = "success" output.success({ value: value }) setTimeout(resetStatus, 1600) } client function copyFailed(error) { status = "error" output.error({ error: error, value: value }) setTimeout(resetStatus, 1600) } client function copyValue(sourceEvent) { if (disabled || status === "copying") { return } status = "copying" output.copy({ value: value, sourceEvent: sourceEvent }) if (!window.navigator.clipboard || !window.navigator.clipboard.writeText) { copyFailed(new Error("Clipboard API is unavailable")) return } return window.navigator.clipboard.writeText(value).then(copySucceeded).catch(copyFailed) } } view {
{#if title}{title}{/if} {#if description}

{description}

{/if}
{#if code} {value} {:else} {value} {/if}
} style { .wrn-clipboard { display: grid; gap: 0.375rem; color: var(--wrn-color-text); } .wrn-clipboard__title { font-size: 0.8125rem; font-weight: 600; } .wrn-clipboard__description { margin: 0; color: var(--wrn-color-text-muted, var(--wrn-color-muted)); font-size: 0.78rem; } /* Plain values sit in a recessed field well; code values (the default) sit on the code surface so they read as something to paste. */ .wrn-clipboard__control { display: flex; min-width: 0; min-height: 2.75rem; align-items: center; gap: 0.5rem; padding: 0.3125rem 0.3125rem 0.3125rem 0.875rem; border: 1px solid var(--wrn-color-input-border, var(--wrn-color-border)); border-radius: var(--wrn-radius-sm); background: var(--wrn-color-input-background, var(--wrn-color-surface)); box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.04); } .wrn-clipboard:has(code.wrn-clipboard__value) .wrn-clipboard__control { border-color: var(--wrn-color-code-border, #262a33); background: var(--wrn-color-code-background, #14161b); box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.04); } .wrn-clipboard__value { min-width: 0; flex: 1; overflow-x: auto; padding: 0.25rem 0; color: var(--wrn-color-text); background: transparent; font: inherit; font-size: 0.8125rem; white-space: nowrap; scrollbar-width: none; } code.wrn-clipboard__value { color: var(--wrn-color-code-text, #e6e9f0); font-family: var(--wrn-font-mono, ui-monospace, monospace); font-size: 0.8rem; } .wrn-clipboard__value::-webkit-scrollbar { display: none; } .wrn-clipboard__button { display: inline-flex; flex: none; align-items: center; gap: 0.375rem; min-height: 2rem; padding: 0 0.7rem; border: 1px solid var(--wrn-color-border); border-bottom-color: var(--wrn-color-border-strong, var(--wrn-color-border)); border-radius: calc(var(--wrn-radius-sm) - 2px); color: var(--wrn-color-text); background: linear-gradient(180deg, var(--wrn-color-surface), var(--wrn-color-surface-soft, var(--wrn-color-surface))); box-shadow: var(--wrn-shadow-1); font: inherit; font-size: 0.78rem; font-weight: 600; cursor: pointer; transition: color 120ms ease, background 120ms ease, border-color 120ms ease; } .wrn-clipboard:has(code.wrn-clipboard__value) .wrn-clipboard__button { border-color: rgb(255 255 255 / 0.12); color: var(--wrn-color-code-text, #e6e9f0); background: rgb(255 255 255 / 0.06); box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.06); } .wrn-clipboard__button:hover:not(:disabled) { background: var(--wrn-color-surface); } .wrn-clipboard:has(code.wrn-clipboard__value) .wrn-clipboard__button:hover:not(:disabled) { background: rgb(255 255 255 / 0.12); } .wrn-clipboard__button:active:not(:disabled) { transform: translateY(1px); } .wrn-clipboard__button:focus-visible { outline: 2px solid var(--wrn-color-focus); outline-offset: 2px; } .wrn-clipboard__button:disabled { cursor: not-allowed; opacity: 0.5; } .wrn-clipboard[data-status="success"] .wrn-clipboard__button, .wrn-clipboard[data-status="success"]:has(code.wrn-clipboard__value) .wrn-clipboard__button { border-color: color-mix(in srgb, var(--wrn-color-success) 50%, transparent); color: var(--wrn-color-success); background: color-mix(in srgb, var(--wrn-color-success) 14%, transparent); } .wrn-clipboard[data-status="error"] .wrn-clipboard__button, .wrn-clipboard[data-status="error"]:has(code.wrn-clipboard__value) .wrn-clipboard__button { border-color: color-mix(in srgb, var(--wrn-color-danger) 50%, transparent); color: var(--wrn-color-danger); background: color-mix(in srgb, var(--wrn-color-danger) 12%, transparent); } .wrn-clipboard__icon { width: 0.875rem; height: 0.875rem; flex: none; } } }