Skip to content

Commit bc4a431

Browse files
benitavJoshua Brink
authored andcommitted
Inkeep (#153)
* inkeep config * it works * Use mintlify search in search bar, AI search as separate button * Separate button for AI search next to search bar * order questions differently * hide on mobile
1 parent 0fd1955 commit bc4a431

File tree

1 file changed

+226
-0
lines changed

1 file changed

+226
-0
lines changed

inkeep.js

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
// customize
2+
const inkeepSettings = {
3+
baseSettings: {
4+
apiKey: "1c24ba8dde97e56465741f2e64a51389662f75793a7d0ec1", // required
5+
primaryBrandColor: "#4e89ff", // required -- your brand color, the color scheme is derived from this
6+
organizationDisplayName: "PowerSync",
7+
// ...optional settings
8+
},
9+
aiChatSettings: {
10+
// ...optional settings
11+
// aiAssistantAvatar: "https://mydomain.com/mylogo.svg",
12+
exampleQuestions: [
13+
"How do I get started?",
14+
"What backend databases are supported?",
15+
"What SDKs are available on the client-side?"
16+
]
17+
}
18+
};
19+
20+
// The Mintlify search triggers, which we'll reuse to trigger the Inkeep modal
21+
// const searchButtonContainerIds = [
22+
// "search-bar-entry",
23+
// "search-bar-entry-mobile",
24+
// ];
25+
26+
// Clone and replace, needed to remove existing event listeners
27+
// const clonedSearchButtonContainers = searchButtonContainerIds.map((id) => {
28+
// const originalElement = document.getElementById(id);
29+
// const clonedElement = originalElement.cloneNode(true);
30+
// originalElement.parentNode.replaceChild(clonedElement, originalElement);
31+
32+
// return clonedElement;
33+
// });
34+
35+
// Load the Inkeep component library
36+
const inkeepScript = document.createElement("script");
37+
inkeepScript.type = "module";
38+
inkeepScript.src = "https://unpkg.com/@inkeep/cxkit-js@^0.5.36/dist/embed.js";
39+
document.body.appendChild(inkeepScript);
40+
41+
// Once the Inkeep library is loaded, instantiate the UI components
42+
inkeepScript.addEventListener("load", function () {
43+
// Customization settings
44+
45+
// Instantiate the 'Ask AI' floating action button
46+
Inkeep.ChatButton({
47+
baseSettings: {
48+
...inkeepSettings.baseSettings,
49+
colorMode: {
50+
sync: {
51+
target: document.documentElement,
52+
attributes: ["class"],
53+
isDarkMode: (attributes) => !!attributes.class?.includes("dark"),
54+
},
55+
},
56+
},
57+
aiChatSettings: {
58+
...inkeepSettings.aiChatSettings,
59+
}
60+
});
61+
62+
// Create and add the 'Ask AI' button next to the search bar
63+
function addAskAIButton() {
64+
// Function to create the Ask AI button
65+
function createAskAIButton() {
66+
const button = document.createElement("button");
67+
button.id = "ask-ai-button";
68+
button.innerHTML = "Ask AI";
69+
button.className = "ask-ai-button";
70+
71+
// Style the button to match the "Get Started" button
72+
button.style.backgroundColor = inkeepSettings.baseSettings.primaryBrandColor;
73+
button.style.color = "white";
74+
button.style.border = "none";
75+
button.style.borderRadius = "12px"; // Pill-shaped to match the search bar in the screenshot
76+
button.style.padding = "8px 8px"; // Slightly wider padding
77+
button.style.marginLeft = "10px";
78+
button.style.cursor = "pointer";
79+
button.style.fontWeight = "500";
80+
button.style.fontSize = "14px";
81+
button.style.display = "flex";
82+
button.style.alignItems = "center";
83+
button.style.justifyContent = "center"; // Center text horizontally
84+
button.style.minWidth = "100px"; // Ensure the button has a minimum width
85+
button.style.boxShadow = "0 2px 4px rgba(0, 0, 0, 0.1)"; // Subtle shadow for depth
86+
button.style.transition = "all 0.2s ease"; // Smooth transition for hover effects
87+
88+
// Add a subtle hover effect
89+
button.onmouseover = function() {
90+
this.style.backgroundColor = "#3a78f2"; // Slightly darker shade when hovering
91+
this.style.transform = "translateY(-1px)"; // Slight lift effect
92+
this.style.boxShadow = "0 4px 8px rgba(0, 0, 0, 0.15)"; // Enhanced shadow on hover
93+
};
94+
button.onmouseout = function() {
95+
this.style.backgroundColor = inkeepSettings.baseSettings.primaryBrandColor;
96+
this.style.transform = "translateY(0)"; // Reset position
97+
this.style.boxShadow = "0 2px 4px rgba(0, 0, 0, 0.1)"; // Reset shadow
98+
};
99+
100+
return button;
101+
}
102+
103+
// Add the button only to the main search bar entry
104+
const searchContainer = document.getElementById("search-bar-entry");
105+
if (searchContainer) {
106+
const buttonContainer = document.createElement("div");
107+
buttonContainer.id = "ask-ai-button-container";
108+
buttonContainer.style.display = "flex";
109+
buttonContainer.style.alignItems = "center";
110+
111+
const askAIButton = createAskAIButton();
112+
113+
// Add click event to the button
114+
askAIButton.addEventListener("click", () => {
115+
modalChat.update({ modalSettings: { isOpen: true } });
116+
});
117+
118+
// Insert the button after the search container
119+
buttonContainer.appendChild(askAIButton);
120+
121+
// Insert the button container after the search container
122+
searchContainer.parentNode.insertBefore(buttonContainer, searchContainer.nextSibling);
123+
124+
// Add CSS to hide the button on mobile
125+
const style = document.createElement('style');
126+
style.textContent = `
127+
@media (max-width: 768px) {
128+
#ask-ai-button-container {
129+
display: none !important;
130+
}
131+
}
132+
`;
133+
document.head.appendChild(style);
134+
}
135+
}
136+
137+
// Instantiate the 'Ask AI' modal chat
138+
const modalChat = Inkeep.ModalChat({
139+
baseSettings: {
140+
...inkeepSettings.baseSettings,
141+
colorMode: {
142+
sync: {
143+
target: document.documentElement,
144+
attributes: ["class"],
145+
isDarkMode: (attributes) => !!attributes.class?.includes("dark"),
146+
},
147+
},
148+
},
149+
aiChatSettings: {
150+
...inkeepSettings.aiChatSettings,
151+
},
152+
modalSettings: {
153+
onOpenChange: handleOpenChange,
154+
},
155+
});
156+
157+
function handleOpenChange(newOpen) {
158+
modalChat.update({ modalSettings: { isOpen: newOpen } });
159+
}
160+
161+
// Add the Ask AI button once the DOM is fully loaded
162+
if (document.readyState === "complete") {
163+
addAskAIButton();
164+
} else {
165+
window.addEventListener("load", addAskAIButton);
166+
}
167+
168+
// The existing chat-button listener (if the element exists)
169+
const existingChatButton = document.querySelector("#chat-button");
170+
if (existingChatButton) {
171+
existingChatButton.addEventListener("click", () => {
172+
modalChat.update({ modalSettings: { isOpen: true } });
173+
});
174+
}
175+
176+
// Access chat methods
177+
modalChat.clearChat();
178+
179+
// Instantiate the search bar modal
180+
// const inkeepSearchModal = Inkeep.ModalSearchAndChat({
181+
// baseSettings: {
182+
// ...inkeepSettings.baseSettings,
183+
// colorMode: {
184+
// sync: {
185+
// target: document.documentElement,
186+
// attributes: ["class"],
187+
// isDarkMode: (attributes) => !!attributes.class?.includes("dark"),
188+
// },
189+
// },
190+
// },
191+
// modalSettings: {
192+
// onOpenChange: handleOpenChange,
193+
// },
194+
// });
195+
196+
// function handleOpenChange(newOpen) {
197+
// inkeepSearchModal.update({ modalSettings: { isOpen: newOpen } });
198+
// }
199+
200+
// When the Mintlify search bar elements are clicked, open the Inkeep search modal
201+
// clonedSearchButtonContainers.forEach((trigger) => {
202+
// trigger.addEventListener("click", function () {
203+
// inkeepSearchModal.update({
204+
// modalSettings: { isOpen: true },
205+
// });
206+
// });
207+
// });
208+
209+
// Open the Inkeep Modal with cmd+k
210+
// window.addEventListener(
211+
// "keydown",
212+
// (event) => {
213+
// if (
214+
// (event.metaKey || event.ctrlKey) &&
215+
// (event.key === "k" || event.key === "K")
216+
// ) {
217+
// event.stopPropagation();
218+
// inkeepSearchModal.update({
219+
// modalSettings: { isOpen: true },
220+
// });
221+
// return false;
222+
// }
223+
// },
224+
// true
225+
// );
226+
});

0 commit comments

Comments
 (0)