@@ -13,10 +13,15 @@ import {
1313 PiMarkdownLogo ,
1414 PiClipboardTextLight ,
1515 PiArrowSquareOutLight ,
16+ PiCheckCircleLight ,
17+ PiXCircleLight ,
1618} from "react-icons/pi" ;
1719
20+ type CopyState = "idle" | "success" | "error" ;
21+
1822export default function CopyPageButton ( ) {
1923 const [ isOpen , setIsOpen ] = useState ( false ) ;
24+ const [ copyState , setCopyState ] = useState < CopyState > ( "idle" ) ;
2025
2126 const { refs, floatingStyles, context } = useFloating ( {
2227 open : isOpen ,
@@ -42,10 +47,25 @@ export default function CopyPageButton() {
4247 const markdownUrl = new URL ( "index.md" , window . location . href ) . toString ( ) ;
4348 try {
4449 const response = await fetch ( markdownUrl ) ;
50+
51+ if ( ! response . ok ) {
52+ throw new Error ( `Received ${ response . status } on ${ response . url } ` ) ;
53+ }
54+
4555 const markdown = await response . text ( ) ;
4656 await navigator . clipboard . writeText ( markdown ) ;
57+
58+ setCopyState ( "success" ) ;
59+ setTimeout ( ( ) => {
60+ setCopyState ( "idle" ) ;
61+ } , 1500 ) ;
4762 } catch ( error ) {
4863 console . error ( "Failed to copy Markdown:" , error ) ;
64+
65+ setCopyState ( "error" ) ;
66+ setTimeout ( ( ) => {
67+ setCopyState ( "idle" ) ;
68+ } , 1500 ) ;
4969 }
5070 } ;
5171
@@ -64,15 +84,41 @@ export default function CopyPageButton() {
6484 } ,
6585 ] ;
6686
87+ const getButtonContent = ( ) => {
88+ if ( copyState === "success" ) {
89+ return (
90+ < >
91+ < PiCheckCircleLight className = "h-4 w-4 text-green-600" />
92+ < span > Copied!</ span >
93+ </ >
94+ ) ;
95+ }
96+
97+ if ( copyState === "error" ) {
98+ return (
99+ < >
100+ < PiXCircleLight className = "h-4 w-4 text-red-600" />
101+ < span > Failed to copy</ span >
102+ </ >
103+ ) ;
104+ }
105+
106+ return (
107+ < >
108+ < PiMarkdownLogo />
109+ < span > Copy Page</ span >
110+ </ >
111+ ) ;
112+ } ;
113+
67114 return (
68115 < >
69116 < button
70117 ref = { refs . setReference }
71118 { ...getReferenceProps ( ) }
72- className = "inline-flex h-8 items-center justify-center gap-2 rounded border border-[--sl-color-hairline] bg-transparent px-3 text-sm text-black"
119+ className = "inline-flex h-8 cursor-pointer items-center justify-center gap-2 rounded border border-[--sl-color-hairline] bg-transparent px-3 text-sm text-black hover:bg-[--sl-color-bg-nav] "
73120 >
74- Copy Page
75- < PiMarkdownLogo />
121+ { getButtonContent ( ) }
76122 </ button >
77123 { isOpen && (
78124 < FloatingPortal >
@@ -86,7 +132,7 @@ export default function CopyPageButton() {
86132 < li key = { label } >
87133 < button
88134 onClick = { onClick }
89- className = "block w-full bg-transparent px-3 py-2 text-left text-black no-underline hover:bg-[--sl-color-bg-nav]"
135+ className = "relative block w-full cursor-pointer bg-transparent px-3 py-2 text-left text-black no-underline hover:bg-[--sl-color-bg-nav]"
90136 >
91137 < div className = "flex items-center gap-2 text-sm" >
92138 < Icon className = "h-4 w-4" />
0 commit comments