@@ -6,6 +6,9 @@ import { FaXTwitter } from "react-icons/fa6";
66import "./SocialShare.css" ;
77
88const COPY_RESET_DELAY_MS = 2000 ;
9+ const COPY_DEFAULT_LABEL = "Copy link" ;
10+ const COPY_SUCCESS_LABEL = "Link copied" ;
11+ const COPY_ERROR_LABEL = "Unable to copy link" ;
912
1013type SocialShareProps = {
1114 permalink ?: string ;
@@ -17,17 +20,17 @@ export default function SocialShare({
1720 title,
1821} : SocialShareProps ) : JSX . Element | null {
1922 const { siteConfig } = useDocusaurusContext ( ) ;
20- const [ copied , setCopied ] = useState ( false ) ;
23+ const [ copyState , setCopyState ] = useState < "idle" | "copied" | "error" > ( "idle" ) ;
2124
2225 useEffect ( ( ) => {
23- if ( ! copied ) {
26+ if ( copyState === "idle" ) {
2427 return undefined ;
2528 }
2629
27- const timeout = window . setTimeout ( ( ) => setCopied ( false ) , COPY_RESET_DELAY_MS ) ;
30+ const timeout = window . setTimeout ( ( ) => setCopyState ( "idle" ) , COPY_RESET_DELAY_MS ) ;
2831
2932 return ( ) => window . clearTimeout ( timeout ) ;
30- } , [ copied ] ) ;
33+ } , [ copyState ] ) ;
3134
3235 if ( ! permalink || ! title ) {
3336 return null ;
@@ -61,13 +64,25 @@ export default function SocialShare({
6164
6265 const handleCopyLink = async ( ) => {
6366 if ( typeof navigator === "undefined" || ! navigator . clipboard ) {
67+ setCopyState ( "error" ) ;
6468 return ;
6569 }
6670
67- await navigator . clipboard . writeText ( blogUrl ) ;
68- setCopied ( true ) ;
71+ try {
72+ await navigator . clipboard . writeText ( blogUrl ) ;
73+ setCopyState ( "copied" ) ;
74+ } catch {
75+ setCopyState ( "error" ) ;
76+ }
6977 } ;
7078
79+ const copyLabel =
80+ copyState === "copied"
81+ ? COPY_SUCCESS_LABEL
82+ : copyState === "error"
83+ ? COPY_ERROR_LABEL
84+ : COPY_DEFAULT_LABEL ;
85+
7186 return (
7287 < section className = "blog-post-share-section" aria-label = "Share this post" >
7388 < p className = "share-title" > Share this post</ p >
@@ -87,12 +102,12 @@ export default function SocialShare({
87102 ) ) }
88103 < button
89104 type = "button"
90- className = { `share-btn-circle copy${ copied ? " copied" : "" } ` }
105+ className = { `share-btn-circle copy${ copyState === " copied" ? " copied" : "" } ${ copyState === "error" ? " copy-error " : "" } ` }
91106 onClick = { ( ) => {
92107 void handleCopyLink ( ) ;
93108 } }
94- title = { copied ? "Link copied" : "Copy link" }
95- aria-label = { copied ? "Link copied" : "Copy link" }
109+ title = { copyLabel }
110+ aria-label = { copyLabel }
96111 >
97112 < FaLink aria-hidden = "true" />
98113 </ button >
0 commit comments