@@ -14,8 +14,12 @@ import Tag from 'components/Tag';
1414import { H1 } from './MDX/Heading' ;
1515import type { RouteTag , RouteItem } from './Layout/getRouteMeta' ;
1616import * as React from 'react' ;
17+ import { useState , useEffect } from 'react' ;
18+ import { useRouter } from 'next/router' ;
1719import { IconCanary } from './Icon/IconCanary' ;
1820import { IconExperimental } from './Icon/IconExperimental' ;
21+ import { IconCopy } from './Icon/IconCopy' ;
22+ import { Button } from './Button' ;
1923
2024interface PageHeadingProps {
2125 title : string ;
@@ -27,6 +31,44 @@ interface PageHeadingProps {
2731 breadcrumbs : RouteItem [ ] ;
2832}
2933
34+ function CopyAsMarkdownButton ( ) {
35+ const { asPath} = useRouter ( ) ;
36+ const [ copied , setCopied ] = useState ( false ) ;
37+
38+ useEffect ( ( ) => {
39+ if ( ! copied ) return ;
40+ const timer = setTimeout ( ( ) => setCopied ( false ) , 2000 ) ;
41+ return ( ) => clearTimeout ( timer ) ;
42+ } , [ copied ] ) ;
43+
44+ async function handleCopy ( ) {
45+ const cleanPath = asPath . split ( / [ ? # ] / ) [ 0 ] ;
46+ try {
47+ const res = await fetch ( cleanPath + '.md' ) ;
48+ if ( ! res . ok ) return ;
49+ const text = await res . text ( ) ;
50+ await navigator . clipboard . writeText ( text ) ;
51+ setCopied ( true ) ;
52+ } catch {
53+ // Silently fail
54+ }
55+ }
56+
57+ return (
58+ < Button onClick = { handleCopy } className = "text-sm py-1 px-3" >
59+ < IconCopy className = "w-3.5 h-3.5 me-1.5" />
60+ { copied ? (
61+ 'Copied!'
62+ ) : (
63+ < >
64+ < span className = "hidden sm:inline" > Copy page</ span >
65+ < span className = "sm:hidden" > Copy</ span >
66+ </ >
67+ ) }
68+ </ Button >
69+ ) ;
70+ }
71+
3072function PageHeading ( {
3173 title,
3274 status,
@@ -37,7 +79,12 @@ function PageHeading({
3779 return (
3880 < div className = "px-5 sm:px-12 pt-3.5" >
3981 < div className = "max-w-4xl ms-0 2xl:mx-auto" >
40- { breadcrumbs ? < Breadcrumbs breadcrumbs = { breadcrumbs } /> : null }
82+ < div className = "flex justify-between items-start" >
83+ < div className = "flex-1" >
84+ { breadcrumbs ? < Breadcrumbs breadcrumbs = { breadcrumbs } /> : null }
85+ </ div >
86+ < CopyAsMarkdownButton />
87+ </ div >
4188 < H1 className = "mt-0 text-primary dark:text-primary-dark -mx-.5 break-words" >
4289 { title }
4390 { version === 'canary' && (
0 commit comments