Skip to content

Commit 5455d61

Browse files
committed
feat(docs): LLMs dropdown
1 parent 99b0145 commit 5455d61

File tree

8 files changed

+211
-170
lines changed

8 files changed

+211
-170
lines changed

apify-docs-theme/src/theme/DocItemContent/index.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import LLMButtons from '@theme/LLMButtons';
66
import MDXContent from '@theme/MDXContent';
77
import clsx from 'clsx';
88
import React from 'react';
9+
import styles from './styles.module.css';
910

1011
function useSyntheticTitle() {
1112
const { metadata, frontMatter, contentTitle } = useDoc();
@@ -62,11 +63,13 @@ export default function DocItemContent({ children }) {
6263
const shouldShowLLMButtons = allowedPaths.some((path) => location.pathname.startsWith(path))
6364
&& !disallowedPaths.some((path) => location.pathname.includes(path));
6465

65-
return (
66-
<div className={clsx(ThemeClassNames.docs.docMarkdown, 'markdown')}>
67-
{syntheticTitle && <Heading as="h1">{syntheticTitle}</Heading>}
68-
{shouldShowLLMButtons && <LLMButtons />}
69-
<MDXContent>{children}</MDXContent>
70-
</div>
71-
);
66+
return (
67+
<div className={clsx(ThemeClassNames.docs.docMarkdown, 'markdown')}>
68+
<div className={styles.docItemContent}>
69+
{syntheticTitle && <Heading as="h1">{syntheticTitle}</Heading>}
70+
{shouldShowLLMButtons && <LLMButtons />}
71+
</div>
72+
<MDXContent>{children}</MDXContent>
73+
</div>
74+
);
7275
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.docItemContent {
2+
display: flex;
3+
flex-direction: row;
4+
justify-content: space-between;
5+
align-items: center;
6+
column-gap: 12px;
7+
flex-wrap: wrap;
8+
}

apify-docs-theme/src/theme/LLMButtons/CopyForLLM/index.jsx

Lines changed: 0 additions & 71 deletions
This file was deleted.

apify-docs-theme/src/theme/LLMButtons/ViewAsMarkdown/index.jsx

Lines changed: 0 additions & 37 deletions
This file was deleted.
Lines changed: 145 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,152 @@
1-
import React from 'react';
1+
import React, { useState } from 'react';
22

3-
import CopyForLLM from './CopyForLLM';
43
import styles from './styles.module.css';
5-
import ViewAsMarkdown from './ViewAsMarkdown';
4+
import { Menu, Text, theme, PlainMenuBaseComponent } from '@apify/ui-library';
5+
import {
6+
CopyIcon,
7+
ExternalLinkIcon,
8+
MarkdownIcon,
9+
ChevronDownIcon,
10+
} from '@apify/ui-icons';
611

712
export default function LLMButtons() {
13+
const [isCopyingLoading, setCopyingIsLoading] = useState(false);
14+
const [isCopied, setIsCopied] = useState(false);
15+
16+
const onCopyAsMarkdownClick = async () => {
17+
if (window.analytics) {
18+
window.analytics.track('Clicked', {
19+
app: 'docs',
20+
button_text: 'Copy for LLM',
21+
element: 'llm-buttons.copyForLLM',
22+
});
23+
}
24+
25+
try {
26+
setCopyingIsLoading(true);
27+
28+
const currentUrl = window.location.href;
29+
const markdownUrl = `${currentUrl}.md`;
30+
31+
// Fetch the markdown content
32+
const response = await fetch(markdownUrl);
33+
34+
if (!response.ok) {
35+
throw new Error(`Failed to fetch markdown: ${response.status}`);
36+
}
37+
38+
const markdownContent = await response.text();
39+
40+
// Copy to clipboard
41+
await navigator.clipboard.writeText(markdownContent);
42+
43+
// Show success feedback
44+
setIsCopied(true);
45+
setTimeout(() => setIsCopied(false), 2000);
46+
} catch (error) {
47+
console.error('Failed to copy markdown content:', error);
48+
} finally {
49+
setCopyingIsLoading(false);
50+
}
51+
};
52+
53+
const onViewAsMarkdownClick = () => {
54+
if (window.analytics) {
55+
window.analytics.track('Clicked', {
56+
app: 'docs',
57+
button_text: 'View as Markdown',
58+
element: 'llm-buttons.viewAsMarkdown',
59+
});
60+
}
61+
62+
try {
63+
const currentUrl = window.location.href;
64+
const markdownUrl = `${currentUrl}.md`;
65+
window.open(markdownUrl, '_blank');
66+
} catch (error) {
67+
console.error('Error opening markdown file:', error);
68+
}
69+
};
70+
71+
const onMenuOptionClick = (value) => {
72+
switch (value) {
73+
case 'copyForLLM':
74+
onCopyAsMarkdownClick();
75+
break;
76+
case 'viewAsMarkdown':
77+
onViewAsMarkdownClick();
78+
break;
79+
default:
80+
break;
81+
}
82+
};
83+
884
return (
9-
<div className={styles.llmButtonsContainer}>
10-
<ViewAsMarkdown />
11-
<div className={styles.llmButtonsSeparator}></div>
12-
<CopyForLLM />
13-
</div>
85+
<Menu
86+
components={{
87+
MenuBase: ({ children, ref, ...props }) => {
88+
console.log(props);
89+
return (
90+
<div ref={ref} className={styles.llmButton}>
91+
<CopyIcon size={16} />
92+
<Text
93+
size="regular"
94+
className={styles.llmButtonText}
95+
onClick={onCopyAsMarkdownClick}
96+
>
97+
{isCopyingLoading
98+
? 'Copying...'
99+
: isCopied
100+
? 'Copied!'
101+
: 'Copy for LLM'}
102+
</Text>
103+
<ChevronDownIcon
104+
{...props}
105+
size="16"
106+
color={theme.color.neutral.icon}
107+
className={styles.chevronIcon}
108+
/>
109+
</div>
110+
);
111+
},
112+
}}
113+
onSelect={onMenuOptionClick}
114+
options={[
115+
{
116+
label: 'Copy page',
117+
description: 'Copy page as Markdown for LLMs',
118+
showExternalIcon: false,
119+
icon: CopyIcon,
120+
value: 'copyForLLM',
121+
},
122+
{
123+
label: 'View as Markdown',
124+
description: 'View this page as plain text',
125+
showExternalIcon: true,
126+
icon: MarkdownIcon,
127+
value: 'viewAsMarkdown',
128+
},
129+
]}
130+
renderOption={(option) => (
131+
<div className={styles.menuOption}>
132+
<option.icon size={16} className={styles.menuOptionIcon} />
133+
<div className={styles.menuOptionText}>
134+
<Text size="regular">{option.label}</Text>
135+
<Text
136+
size="small"
137+
color={theme.color.neutral.textSubtle}
138+
>
139+
{option.description}
140+
</Text>
141+
</div>
142+
{option.showExternalIcon && (
143+
<ExternalLinkIcon
144+
size={16}
145+
className={styles.menuOptionExternalIcon}
146+
/>
147+
)}
148+
</div>
149+
)}
150+
/>
14151
);
15152
}

0 commit comments

Comments
 (0)