Skip to content

Commit 60ab786

Browse files
committed
feat: enable Kapa AI chat widget
1 parent df72ce7 commit 60ab786

File tree

3 files changed

+71
-179
lines changed

3 files changed

+71
-179
lines changed

apify-docs-theme/src/config.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,8 +322,6 @@ const scripts = [
322322
'data-modal-title': 'Apify AI Assistant',
323323
'data-project-color': '#666666',
324324
'data-button-hide': 'true',
325-
'data-search-mode-enabled': 'true',
326-
'data-search-include-source-names': '["Docs"]',
327325
'data-project-logo': 'https://apify.com/img/apify-logo/logomark-32x32.svg',
328326
'data-modal-example-questions': 'How to run an Actor?,Create a version of an Actor?',
329327
'data-modal-override-open-id': 'ask-ai-input',

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

Lines changed: 51 additions & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
// eslint-disable-next-line simple-import-sort/imports
22
import BrowserOnly from '@docusaurus/BrowserOnly';
33
import RouterLink from '@docusaurus/Link';
4-
// import { useHistory, useLocation } from '@docusaurus/router';
4+
import { useHistory, useLocation } from '@docusaurus/router';
55
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
6-
import clsx from 'clsx';
7-
import React, { useEffect, useState } from 'react';
8-
import { useHotkeys } from 'react-hotkeys-hook';
6+
import { useState, useCallback } from 'react';
97

10-
// import { ApifySearch } from '@apify/docs-search-modal';
11-
import { ControlKeyIcon, SearchIcon } from '@apify/docs-search-modal/dist/utils/icons';
8+
import { ApifySearch } from '@apify/docs-search-modal';
129

1310
// needs to be imported as the last thing, so that it can override the default styles
1411
// TODO: update simple-import-sort to allow importing css as last.
@@ -43,60 +40,51 @@ export function Link(props) {
4340
return <a {...props}>{props.children}</a>;
4441
}
4542

46-
// export default function SearchBar({ onClick }) {
47-
// const { siteConfig } = useDocusaurusContext();
48-
// const location = useLocation();
49-
// const history = useHistory();
50-
//
51-
// const navigate = useCallback((href) => {
52-
// const shortHref = href.substring('https://docs.apify.com'.length);
53-
//
54-
// if (matchesCurrentInstance(shortHref, siteConfig.baseUrl)) {
55-
// return history.push(shortHref);
56-
// }
57-
// return window.location.assign(href);
58-
// }, [history, siteConfig.baseUrl]);
59-
//
60-
// const getVersion = useCallback(() => {
61-
// const match = location.pathname.match(/\/(\d+\.\d+|next)/);
62-
//
63-
// return match ? match[1] : 'latest';
64-
// }, [location]);
65-
//
66-
// return (
67-
// <BrowserOnly>
68-
// {() => (
69-
// <div onClick={onClick}>
70-
// <ApifySearch
71-
// algoliaAppId={siteConfig.themeConfig.algolia.appId}
72-
// algoliaIndexName='apify_sdk_v2'
73-
// algoliaKey={siteConfig.themeConfig.algolia.apiKey}
74-
// filters={`version:${getVersion()}`}
75-
// navigate={navigate}
76-
// />
77-
// </div>
78-
// )}
79-
// </BrowserOnly>
80-
// );
81-
// }
82-
8343
export default function SearchBar({ onClick }) {
84-
const [variant, setVariant] = useState(null);
85-
const [opened, setOpened] = useState(false);
8644
const { siteConfig } = useDocusaurusContext();
87-
const { inkeepApiKey } = siteConfig.customFields;
45+
const location = useLocation();
46+
const history = useHistory();
8847

89-
useEffect(() => {
90-
const storedVariant = localStorage.getItem('search-provider');
48+
const navigate = useCallback((href) => {
49+
const shortHref = href.substring('https://docs.apify.com'.length);
9150

92-
if (storedVariant) {
93-
setVariant(storedVariant);
94-
} else {
95-
const assignedVariant = Math.random() < 0.5 ? 'inkeep' : 'kapa';
96-
localStorage.setItem('search-provider', assignedVariant);
97-
setVariant(assignedVariant);
51+
if (matchesCurrentInstance(shortHref, siteConfig.baseUrl)) {
52+
return history.push(shortHref);
9853
}
99-
}, []);
54+
return window.location.assign(href);
55+
}, [history, siteConfig.baseUrl]);
56+
57+
const getVersion = useCallback(() => {
58+
const match = location.pathname.match(/\/(\d+\.\d+|next)/);
59+
60+
return match ? match[1] : 'latest';
61+
}, [location]);
62+
63+
return (
64+
<BrowserOnly>
65+
{() => (
66+
<div
67+
style={{ display: 'flex', alignItems: 'center' }}
68+
>
69+
70+
<div onClick={onClick} style={{ marginRight: '12px' }}>
71+
<ApifySearch
72+
algoliaAppId={siteConfig.themeConfig.algolia.appId}
73+
algoliaIndexName='apify_sdk_v2'
74+
algoliaKey={siteConfig.themeConfig.algolia.apiKey}
75+
filters={`version:${getVersion()}`}
76+
navigate={navigate}
77+
/>
78+
</div>
79+
<KapaAIButton />
80+
</div>
81+
)}
82+
</BrowserOnly>
83+
);
84+
}
85+
86+
function KapaAIButton({ onClick }) {
87+
const [opened, setOpened] = useState(false);
10088

10189
onClick = () => {
10290
if (opened) {
@@ -105,136 +93,22 @@ export default function SearchBar({ onClick }) {
10593

10694
setOpened(true);
10795

108-
if (variant === 'kapa') {
109-
if (window.Kapa && typeof window.Kapa.open === 'function') {
110-
window.Kapa.open();
111-
window.Kapa('onModalClose', () => {
112-
setOpened(false);
113-
});
114-
} else {
115-
console.error('Kapa.ai widget is not available.');
116-
}
117-
return;
118-
}
119-
120-
if (variant !== 'inkeep') {
121-
console.warn('Unknown search variant:', variant);
122-
return;
123-
}
124-
125-
if (window.Inkeep) {
126-
const config = {
127-
baseSettings: {
128-
apiKey: inkeepApiKey,
129-
organizationDisplayName: 'Apify',
130-
primaryBrandColor: '#FF9013',
131-
transformSource: (source) => {
132-
function getTabForSource(src) {
133-
if (src.url.includes('help.apify.com')) {
134-
return 'Help';
135-
}
136-
return 'Docs';
137-
}
138-
139-
if (source.contentType === 'documentation') {
140-
return {
141-
...source,
142-
tabs: [...(source.tabs || []), getTabForSource(source)],
143-
};
144-
}
145-
return source;
146-
},
147-
trigger: {
148-
disableDefaultTrigger: true,
149-
},
150-
theme: {
151-
styles: [
152-
{
153-
key: 'main',
154-
type: 'link',
155-
value: '/inkeep-overrides.css',
156-
},
157-
],
158-
},
159-
},
160-
modalSettings: {
161-
onOpenChange: handleOpenChange,
162-
},
163-
searchSettings: {
164-
tabs: [
165-
['Docs', { isAlwaysVisible: true }],
166-
'GitHub',
167-
'All',
168-
],
169-
},
170-
aiChatSettings: {
171-
aiAssistantAvatar: 'https://intercom.help/apify/assets/favicon',
172-
chatSubjectName: 'Apify',
173-
exampleQuestions: [
174-
'What is an Actor?',
175-
'How to use my own proxies?',
176-
'How to integrate Apify Actors with GitHub?',
177-
'How to share key-value stores between runs?',
178-
],
179-
getHelpOptions: [
180-
{
181-
action: {
182-
type: 'open_link',
183-
url: 'https://apify.com/contact',
184-
},
185-
icon: {
186-
builtIn: 'IoChatbubblesOutline',
187-
},
188-
name: 'Contact Us',
189-
},
190-
],
191-
},
192-
defaultView: 'chat',
193-
};
194-
const modal = window.Inkeep.ModalSearchAndChat(config);
195-
196-
function handleOpenChange(newOpen) {
197-
modal.update({ modalSettings: { isOpen: newOpen } });
198-
setOpened(newOpen);
199-
}
200-
201-
modal.update({ modalSettings: { isOpen: true } });
96+
if (window.Kapa && typeof window.Kapa.open === 'function') {
97+
window.Kapa.open();
98+
window.Kapa('onModalClose', () => {
99+
setOpened(false);
100+
});
202101
} else {
203-
console.error('Inkeep widget is not available.');
102+
console.error('Kapa.ai widget is not available.');
204103
}
205104
};
206105

207-
const [key, setKey] = useState(null);
208-
209-
useEffect(() => {
210-
if (typeof navigator !== 'undefined') {
211-
const isMac = /Mac|iPod|iPhone|iPad/.test(navigator.platform);
212-
setKey(isMac ? '⌘' : 'ctrl');
213-
}
214-
}, []);
215-
216-
useHotkeys('mod+k, /', () => {
217-
onClick();
218-
}, { preventDefault: true });
219-
220106
return (
221107
<BrowserOnly>
222108
{() => (
223109
<div onClick={onClick}>
224-
<button type="button" className="DocSearch DocSearch-Button" aria-label="Search">
225-
<span className="DocSearch-Button-Container">
226-
<SearchIcon/>
227-
<span className="DocSearch-Button-Placeholder">Search</span>
228-
</span>
229-
<span className="DocSearch-Button-Keys">
230-
{key !== null && (<>
231-
<kbd className={clsx(key === 'ctrl' ? 'ctrl' : 'cmd', 'DocSearch-Button-Key')}>
232-
{key === 'ctrl' ? <ControlKeyIcon/> : key}
233-
</kbd>
234-
<kbd className="DocSearch-Button-Key">K</kbd>
235-
</>)}
236-
</span>
237-
110+
<button type="button" className="AskAI-Button" aria-label="Ask AI">
111+
Ask AI
238112
</button>
239113
</div>
240114
)}

apify-docs-theme/src/theme/SearchBar/styles.css

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,26 @@
2222
color var(--ifm-transition-fast) var(--ifm-transition-timing-default);
2323
}
2424

25+
.AskAI-Button {
26+
height: 4rem;
27+
padding: 0.8rem 1.6rem !important;
28+
background-color: var(--ifm-color-primary);
29+
border-radius: 8px;
30+
color: var(--color-neutral-text-on-primary);
31+
font-size: 1.6rem;
32+
font-weight: 500;
33+
line-height: 2.4rem;
34+
border: none;
35+
box-shadow: none;
36+
outline: none;
37+
box-sizing: border-box;
38+
cursor: pointer;
39+
display: block;
40+
position: relative;
41+
text-align: center;
42+
transition: all var(--ifm-transition-fast) var(--ifm-transition-timing-default);
43+
}
44+
2545
.navbar-sidebar .DocSearch-Button {
2646
display: none;
2747
}

0 commit comments

Comments
 (0)