11"use client" ;
22
3+ import { useState } from "react" ;
34import { OddIcon } from "@/components/ui/odd-icon" ;
45
56const ISSUES_URL = "https://github.com/jasperdevs/oddicons/issues/new" ;
7+ type Social =
8+ | { id : string ; label : string ; icon : string ; href : string ; copy ?: never }
9+ | { id : string ; label : string ; icon : string ; copy : string ; href ?: never } ;
10+
11+ const SOCIALS : Social [ ] = [
12+ { id : "x" , label : "x" , icon : "x-twitter" , href : "https://x.com/jasperdevs" } ,
13+ { id : "discord" , label : "discord" , icon : "discord" , copy : "jasperdevs" } ,
14+ { id : "gmail" , label : "gmail" , icon : "gmail" , href : "mailto:jasper.mceligott@gmail.com" } ,
15+ ] ;
616
717interface RequestFormProps {
818 heading ?: string ;
@@ -15,6 +25,18 @@ export function RequestForm({
1525 subheading = "tell us what icon you want on GitHub" ,
1626 hideHeader = false ,
1727} : RequestFormProps ) {
28+ const [ copied , setCopied ] = useState < string | null > ( null ) ;
29+
30+ const copySocial = async ( id : string , value : string ) => {
31+ try {
32+ await navigator . clipboard . writeText ( value ) ;
33+ setCopied ( id ) ;
34+ window . setTimeout ( ( ) => setCopied ( ( current ) => ( current === id ? null : current ) ) , 1400 ) ;
35+ } catch {
36+ // ignore
37+ }
38+ } ;
39+
1840 return (
1941 < div className = "flex flex-col gap-4" >
2042 { ! hideHeader && (
@@ -37,7 +59,7 @@ export function RequestForm({
3759 Send an issue with the icon you want.
3860 </ p >
3961 < p className = "text-[12px] leading-[1.55] text-muted-foreground" >
40- Requests are tracked in GitHub issues so they do not get lost .
62+ GitHub is the best place to request new icons .
4163 </ p >
4264 </ div >
4365 </ div >
@@ -51,6 +73,43 @@ export function RequestForm({
5173 < OddIcon name = "github" size = { 20 } />
5274 send GitHub issue
5375 </ a >
76+
77+ < div className = "grid grid-cols-3 gap-1.5 border-t border-border pt-4" >
78+ { SOCIALS . map ( ( social ) => {
79+ const content = (
80+ < >
81+ < OddIcon name = { copied === social . id ? "check" : social . icon } size = { 20 } />
82+ < span className = "truncate" > { copied === social . id ? "copied" : social . label } </ span >
83+ </ >
84+ ) ;
85+ const className = "group/chip flex h-11 items-center justify-center gap-2 rounded-lg border border-border bg-sidebar text-[12px] font-medium text-muted-foreground transition-[color,background-color,border-color,transform] duration-[180ms] hover:-translate-y-0.5 hover:border-foreground/30 hover:bg-accent hover:text-foreground" ;
86+
87+ if ( social . copy !== undefined ) {
88+ return (
89+ < button
90+ key = { social . id }
91+ type = "button"
92+ onClick = { ( ) => copySocial ( social . id , social . copy ) }
93+ className = { className }
94+ >
95+ { content }
96+ </ button >
97+ ) ;
98+ }
99+
100+ return (
101+ < a
102+ key = { social . id }
103+ href = { social . href }
104+ target = { social . href . startsWith ( "mailto:" ) ? undefined : "_blank" }
105+ rel = { social . href . startsWith ( "mailto:" ) ? undefined : "noreferrer" }
106+ className = { className }
107+ >
108+ { content }
109+ </ a >
110+ ) ;
111+ } ) }
112+ </ div >
54113 </ div >
55114 ) ;
56115}
0 commit comments