1
1
'use client' ;
2
+
2
3
import { useAIChatController , useAIChatState } from '@/components/AI/useAIChat' ;
3
4
import AIChatIcon from '@/components/AIChat/AIChatIcon' ;
4
5
import { Button } from '@/components/primitives/Button' ;
5
6
import { DropdownMenu , DropdownMenuItem } from '@/components/primitives/DropdownMenu' ;
6
7
import { tString , useLanguage } from '@/intl/client' ;
7
8
import { Icon , type IconName , IconStyle } from '@gitbook/icons' ;
8
- import { useEffect , useRef } from 'react' ;
9
+ import { useRef } from 'react' ;
9
10
10
- type Action = {
11
+ type AIAction = {
11
12
icon ?: IconName | React . ReactNode ;
12
13
label : string ;
13
14
description ?: string ;
@@ -18,7 +19,12 @@ type Action = {
18
19
onClick ?: ( ) => void ;
19
20
} ;
20
21
21
- export function AIActionsDropdown ( ) {
22
+ export function AIActionsDropdown ( props : {
23
+ markdown ?: string ;
24
+ markdownUrl : string ;
25
+ } ) {
26
+ const { markdown, markdownUrl } = props ;
27
+
22
28
const chatController = useAIChatController ( ) ;
23
29
const chat = useAIChatState ( ) ;
24
30
const language = useLanguage ( ) ;
@@ -36,82 +42,45 @@ export function AIActionsDropdown() {
36
42
} ) ;
37
43
} ;
38
44
39
- const handleCopyPage = async ( ) => {
40
- const markdownUrl = `${ window . location . href } .md` ;
41
-
42
- // Get the page content
43
- const markdown = await fetch ( markdownUrl ) . then ( ( res ) => res . text ( ) ) ;
44
-
45
- // Copy the markdown to the clipboard
46
- navigator . clipboard . writeText ( markdown ) ;
47
- } ;
48
-
49
- const handleViewAsMarkdown = ( ) => {
50
- // Open the page in Markdown format
51
- const currentUrl = window . location . href ;
52
- const markdownUrl = `${ currentUrl } .md` ;
53
- window . open ( markdownUrl , '_blank' ) ;
54
- } ;
55
-
56
- const actions : Action [ ] = [
45
+ const actions : AIAction [ ] = [
57
46
{
58
- icon : 'copy' ,
59
- label : 'Copy page ' ,
60
- description : 'Copy the page content ' ,
61
- onClick : handleCopyPage ,
47
+ icon : < AIChatIcon /> ,
48
+ label : 'Ask Docs Assistant ' ,
49
+ description : 'Ask our Docs Assistant about this page ' ,
50
+ onClick : ( ) => { } ,
62
51
} ,
52
+ ...( markdown
53
+ ? [
54
+ {
55
+ icon : 'copy' ,
56
+ label : 'Copy for LLMs' ,
57
+ description : 'Copy page as Markdown' ,
58
+ onClick : ( ) => {
59
+ if ( ! markdown ) return ;
60
+ navigator . clipboard . writeText ( markdown ) ;
61
+ } ,
62
+ } ,
63
+ ]
64
+ : [ ] ) ,
63
65
{
64
- icon : 'markdown' ,
66
+ icon : (
67
+ < svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 471 289.85" className = "size-5" >
68
+ < title > markdown icon</ title >
69
+ < path d = "M437,289.85H34a34,34,0,0,1-34-34V34A34,34,0,0,1,34,0H437a34,34,0,0,1,34,34V255.88A34,34,0,0,1,437,289.85ZM34,22.64A11.34,11.34,0,0,0,22.64,34V255.88A11.34,11.34,0,0,0,34,267.2H437a11.34,11.34,0,0,0,11.33-11.32V34A11.34,11.34,0,0,0,437,22.64Z" />
70
+ < path d = "M67.93,221.91v-154h45.29l45.29,56.61L203.8,67.93h45.29v154H203.8V133.6l-45.29,56.61L113.22,133.6v88.31Zm283.06,0-67.94-74.72h45.29V67.93h45.29v79.26h45.29Z" />
71
+ </ svg >
72
+ ) ,
65
73
label : 'View as Markdown' ,
66
- description : 'Open a Markdown version of this page ' ,
74
+ description : 'View this page as plain text ' ,
67
75
isExternal : true ,
68
- onClick : handleViewAsMarkdown ,
76
+ onClick : ( ) => {
77
+ window . open ( markdownUrl , '_blank' ) ;
78
+ } ,
69
79
} ,
70
80
] ;
71
81
72
- // Get the header width with title and check if there is enough space to show the dropdown
73
- useEffect ( ( ) => {
74
- const getHeaderAvailableSpace = ( ) => {
75
- const header = document . getElementById ( 'page-header' ) ;
76
- const headerTitle = header ?. getElementsByTagName ( 'h1' ) [ 0 ] ;
77
-
78
- return (
79
- ( header ?. getBoundingClientRect ( ) . width ?? 0 ) -
80
- ( headerTitle ?. getBoundingClientRect ( ) . width ?? 0 )
81
- ) ;
82
- } ;
83
-
84
- const dropdownWidth = 202 ;
85
-
86
- window . addEventListener ( 'resize' , ( ) => {
87
- const headerAvailableSpace = getHeaderAvailableSpace ( ) ;
88
- if ( ref . current ) {
89
- if ( headerAvailableSpace <= dropdownWidth ) {
90
- ref . current . classList . add ( '-mt-3' ) ;
91
- ref . current . classList . remove ( 'mt-3' ) ;
92
- } else {
93
- ref . current . classList . remove ( '-mt-3' ) ;
94
- ref . current . classList . add ( 'mt-3' ) ;
95
- }
96
- }
97
- } ) ;
98
-
99
- window . addEventListener ( 'load' , ( ) => {
100
- const headerAvailableSpace = getHeaderAvailableSpace ( ) ;
101
- if ( ref . current ) {
102
- if ( headerAvailableSpace <= dropdownWidth ) {
103
- ref . current . classList . add ( '-mt-3' ) ;
104
- ref . current . classList . remove ( 'mt-3' ) ;
105
- } else {
106
- ref . current . classList . remove ( '-mt-3' ) ;
107
- ref . current . classList . add ( 'mt-3' ) ;
108
- }
109
- }
110
- } ) ;
111
- } , [ ] ) ;
112
-
113
82
return (
114
- < div ref = { ref } className = "hidden items-stretch justify-start md:flex" >
83
+ < div ref = { ref } className = "hidden h-fit items-stretch justify-start md:flex" >
115
84
< Button
116
85
icon = { < AIChatIcon className = "size-3.5" /> }
117
86
size = "small"
@@ -145,17 +114,19 @@ export function AIActionsDropdown() {
145
114
{ typeof action . icon === 'string' ? (
146
115
< Icon
147
116
icon = { action . icon as IconName }
148
- iconStyle = { IconStyle . Light }
149
- className = "size-full"
117
+ iconStyle = { IconStyle . Regular }
118
+ className = "size-full fill-transparent stroke-current "
150
119
/>
151
120
) : (
152
121
action . icon
153
122
) }
154
123
</ div >
155
124
) : null }
156
- < div className = "flex flex-1 flex-col" >
157
- < span className = "flex items-center gap-1.5 text-tint-strong" >
158
- < span className = "truncate font-medium" > { action . label } </ span >
125
+ < div className = "flex flex-1 flex-col gap-0.5" >
126
+ < span className = "flex items-center gap-2 text-tint-strong" >
127
+ < span className = "truncate font-medium text-[0.9375rem]" >
128
+ { action . label }
129
+ </ span >
159
130
{ action . isExternal ? (
160
131
< Icon icon = "arrow-up-right" className = "size-3" />
161
132
) : null }
0 commit comments