All checks were successful
Test and deploy staging / staging (push) Successful in 11m52s
49 lines
1.0 KiB
Svelte
49 lines
1.0 KiB
Svelte
<script lang="ts">
|
|
import type { Component } from 'svelte';
|
|
import { Button } from '$lib/components/ui/button/index.js';
|
|
|
|
let {
|
|
icon: Icon,
|
|
label,
|
|
value
|
|
}: {
|
|
icon: Component;
|
|
label: string;
|
|
value: string;
|
|
} = $props();
|
|
|
|
let copied = $state(false);
|
|
|
|
async function copy(): Promise<void> {
|
|
try {
|
|
await navigator.clipboard.writeText(value);
|
|
copied = true;
|
|
} catch {
|
|
// clipboard blocked
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<div
|
|
class="group relative"
|
|
role="group"
|
|
onmouseleave={(): void => {
|
|
copied = false;
|
|
}}
|
|
>
|
|
<Button variant="ghost" size="icon-lg" onclick={copy} aria-label={`Copy ${label}: ${value}`}>
|
|
<Icon class="size-6" />
|
|
</Button>
|
|
|
|
<span
|
|
role="tooltip"
|
|
class="pointer-events-none absolute top-full left-1/2 mt-2 -translate-x-1/2
|
|
rounded bg-neutral-800 px-2 py-1 text-xs whitespace-nowrap text-white
|
|
opacity-0 transition group-hover:opacity-100"
|
|
>
|
|
{copied ? 'Copied!' : value}
|
|
</span>
|
|
</div>
|
|
|
|
<div aria-live="polite" class="sr-only">{copied ? `${label} copied` : ''}</div>
|