Second version of my personal website. luccaromaniello.com/
css personal-website bun tailwindcss portflio design typescript code ux-ui astro javascript
at dev 90 lines 2.4 kB view raw
1--- 2import { SOCIAL_ICONS } from "@constants"; 3 4interface Props { 5 icon?: keyof typeof SOCIAL_ICONS; 6 label: string; 7 href: string; 8 external?: boolean; 9 theme?: "dark" | "light"; 10 track?: boolean; 11 trackEvent?: string; 12 copyToClipboard?: string; 13} 14 15const { 16 icon, 17 label, 18 href, 19 external = true, 20 theme = "light", 21 track = false, 22 trackEvent, 23 copyToClipboard, 24} = Astro.props; 25const IconComponent = icon ? SOCIAL_ICONS[icon].icon : null; 26 27const themeClasses = { 28 dark: "border-white text-white hover:bg-white hover:text-black", 29 light: "border-black text-black hover:bg-black hover:text-white", 30}; 31 32const sharedClasses = [ 33 "w-full md:w-auto inline-flex flex-row items-center justify-center gap-2 py-2 md:py-3 px-4 md:py-2 border-2 rounded-sm shadow-[3px_3px_0_0_#AE1E5F] text-sm text-center uppercase font-semibold cursor-pointer", 34 themeClasses[theme], 35]; 36--- 37 38{ 39 copyToClipboard ? ( 40 <button 41 data-copy={copyToClipboard} 42 aria-label={label} 43 data-umami-event={trackEvent} 44 class:list={["copy-btn", ...sharedClasses]} 45 > 46 {IconComponent && <IconComponent class="w-4 h-4" />} 47 <span data-copy-label>{label}</span> 48 </button> 49 ) : ( 50 <a 51 href={href} 52 aria-label={label} 53 rel={track ? undefined : "noopener noreferrer"} 54 target={external ? "_blank" : "_self"} 55 data-umami-event={trackEvent} 56 class:list={sharedClasses} 57 > 58 {IconComponent && <IconComponent class="w-4 h-4" />} 59 {label} 60 </a> 61 ) 62} 63 64<script> 65 document.querySelectorAll(".copy-btn").forEach((btn) => { 66 let timeout: ReturnType<typeof setTimeout> | null = null; 67 68 btn.addEventListener("click", () => { 69 const value = btn.getAttribute("data-copy"); 70 const label = btn.querySelector("[data-copy-label]") as HTMLElement; 71 if (!value || !label) return; 72 73 const original = 74 btn.getAttribute("data-original-label") ?? label.innerText; 75 if (!btn.getAttribute("data-original-label")) { 76 btn.setAttribute("data-original-label", label.innerText); 77 label.style.minWidth = `${label.offsetWidth}px`; 78 } 79 80 navigator.clipboard.writeText(value); 81 82 if (timeout) clearTimeout(timeout); 83 label.innerText = "Copied!"; 84 timeout = setTimeout(() => { 85 label.innerText = original; 86 timeout = null; 87 }, 1500); 88 }); 89 }); 90</script>