bsc

Comprehensive codebase and cou...
Log | Files | Refs | README | LICENSE

CopyLinkButton.vue (2755B)


      1 <template>
      2   <div class="copy-link-wrap">
      3     <button class="copy-link-btn" @click="copyLink" aria-label="Copy page link">
      4       <svg
      5         class="icon link-icon"
      6         :class="{ hidden: copied }"
      7         xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"
      8         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
      9       >
     10         <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/>
     11         <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>
     12       </svg>
     13       <svg
     14         class="icon check-icon"
     15         :class="{ visible: copied }"
     16         xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"
     17         fill="none" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"
     18       >
     19         <path
     20           ref="checkPath"
     21           d="M4 12l5 5L20 6"
     22           stroke-dasharray="24"
     23           :stroke-dashoffset="copied ? 0 : 24"
     24         />
     25       </svg>
     26     </button>
     27   </div>
     28 </template>
     29 
     30 <script setup>
     31 import { ref } from 'vue'
     32 
     33 const copied = ref(false)
     34 let resetTimer = null
     35 
     36 function copyLink() {
     37   const url = window.location.href
     38 
     39   navigator.clipboard.writeText(url).then(showCopied).catch(() => {
     40     fallbackCopy(url)
     41   })
     42 }
     43 
     44 function fallbackCopy(text) {
     45   const textarea = document.createElement('textarea')
     46   textarea.value = text
     47   textarea.style.position = 'fixed'
     48   textarea.style.opacity = '0'
     49   document.body.appendChild(textarea)
     50   textarea.focus()
     51   textarea.select()
     52 
     53   try {
     54     document.execCommand('copy')
     55     showCopied()
     56   } catch (err) {
     57     console.error('Copy failed:', err)
     58   }
     59 
     60   document.body.removeChild(textarea)
     61 }
     62 
     63 function showCopied() {
     64   clearTimeout(resetTimer)
     65   copied.value = true
     66   resetTimer = setTimeout(() => {
     67     copied.value = false
     68   }, 1400)
     69 }
     70 </script>
     71 
     72 <style scoped>
     73 .copy-link-wrap {
     74   display: flex;
     75   justify-content: flex-end;
     76   margin-bottom: 12px;
     77 }
     78 
     79 .copy-link-btn {
     80   position: relative;
     81   width: 32px;
     82   height: 32px;
     83   border-radius: 6px;
     84   border: 1px solid var(--vp-c-divider);
     85   background: var(--vp-c-bg-soft);
     86   display: flex;
     87   align-items: center;
     88   justify-content: center;
     89   cursor: pointer;
     90   transition: border-color 0.2s;
     91 }
     92 
     93 .copy-link-btn:hover {
     94   border-color: var(--vp-c-brand);
     95 }
     96 
     97 .icon {
     98   position: absolute;
     99   transition: opacity 0.2s ease, transform 0.2s ease;
    100 }
    101 
    102 .link-icon {
    103   color: var(--vp-c-text-2);
    104   opacity: 1;
    105   transform: scale(1);
    106 }
    107 
    108 .link-icon.hidden {
    109   opacity: 0;
    110   transform: scale(0.5);
    111 }
    112 
    113 .check-icon {
    114   opacity: 0;
    115   transform: scale(0.5);
    116 }
    117 
    118 .check-icon.visible {
    119   opacity: 1;
    120   transform: scale(1);
    121 }
    122 
    123 .check-icon path {
    124   transition: stroke-dashoffset 0.35s ease;
    125 }
    126 </style>
© notamitgamer • Site Built: 2026-07-21 13:58:23 UTC • git-mirror commit: 1037f62 [view raw info]
Originally created with stagit • modified by notamitgamer
Forked from github.com/notamitgamer/git-mirror