music on atproto
plyr.fm
1<script lang="ts">
2 interface Props {
3 url: string;
4 title?: string;
5 }
6
7 let { url, title = 'share' }: Props = $props();
8
9 let showCopied = $state(false);
10
11 async function copyLink() {
12 try {
13 await navigator.clipboard.writeText(url);
14 showCopied = true;
15 setTimeout(() => {
16 showCopied = false;
17 }, 2000);
18 } catch (err) {
19 console.error('failed to copy:', err);
20 }
21 }
22</script>
23
24<button class="share-btn" onclick={copyLink} {title}>
25 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
26 <circle cx="18" cy="5" r="3"></circle>
27 <circle cx="6" cy="12" r="3"></circle>
28 <circle cx="18" cy="19" r="3"></circle>
29 <line x1="8.59" y1="13.51" x2="15.42" y2="17.49"></line>
30 <line x1="15.41" y1="6.51" x2="8.59" y2="10.49"></line>
31 </svg>
32 {#if showCopied}
33 <span class="copied">copied!</span>
34 {/if}
35</button>
36
37<style>
38 .share-btn {
39 background: var(--glass-btn-bg, transparent);
40 border: 1px solid var(--glass-btn-border, var(--border-default));
41 border-radius: var(--radius-base);
42 width: 32px;
43 height: 32px;
44 padding: 0;
45 color: var(--text-tertiary);
46 cursor: pointer;
47 display: flex;
48 align-items: center;
49 justify-content: center;
50 gap: 0.5rem;
51 transition: all 0.2s;
52 position: relative;
53 }
54
55 .share-btn:hover {
56 background: var(--glass-btn-bg-hover, transparent);
57 border-color: var(--accent);
58 color: var(--accent);
59 }
60
61 .copied {
62 position: absolute;
63 top: -2rem;
64 left: 50%;
65 transform: translateX(-50%);
66 background: var(--bg-tertiary);
67 border: 1px solid var(--accent);
68 color: var(--accent);
69 padding: 0.25rem 0.75rem;
70 border-radius: var(--radius-sm);
71 font-size: var(--text-xs);
72 white-space: nowrap;
73 pointer-events: none;
74 animation: fadeIn 0.2s ease-in;
75 }
76
77 @keyframes fadeIn {
78 from {
79 opacity: 0;
80 transform: translateX(-50%) translateY(-0.25rem);
81 }
82 to {
83 opacity: 1;
84 transform: translateX(-50%) translateY(0);
85 }
86 }
87
88 @media (max-width: 768px) {
89 .share-btn {
90 width: 28px;
91 height: 28px;
92 }
93
94 .share-btn svg {
95 width: 14px;
96 height: 14px;
97 }
98 }
99</style>