diff --git a/.vitepress/config.mts b/.vitepress/config.mts
index a6088b2b8..9f0a29be1 100644
--- a/.vitepress/config.mts
+++ b/.vitepress/config.mts
@@ -286,23 +286,366 @@ function getHeadConfig(){
}
],
['meta', {property: 'og:url', content: 'https://gardener.cloud/'}],
+ // Kapa.ai: Custom consent management with dual-mode loading
[
'script',
- {
- async: 'true',
- src: 'https://widget.kapa.ai/kapa-widget.bundle.js',
- 'data-website-id': '3dac305b-ea27-43c5-8421-dc61f4fefa23',
- 'data-project-name': 'Gardener',
- 'data-project-color': '#009f76',
- 'data-modal-header-bg-color': '#009f76',
- 'data-modal-title-color': '#FFFFFF',
- 'data-project-logo': 'https://gardener.cloud/gardener-logo-white.svg',
- 'data-consent-required': 'true',
- 'data-consent-screen-disclaimer': 'This AI assistant uses your questions to provide answers based on Gardener documentation. Your questions and interactions may be anonymously collected and analyzed to improve the search functionality and overall user experience. We don\'t collect any personally identifiable information. By clicking "Accept", you consent to using this AI-powered feature and the collection of your data. AI-generated responses may contain inaccuracies - please verify important information with the official documentation.',
- 'data-consent-screen-accept-button-text': 'I agree, let\'s chat!',
- 'data-consent-screen-reject-button-text': 'No, not interested',
- 'data-modal-example-questions': "How do I access my shoot cluster after it's created?,What happens during the daily maintenance window?,How do I configure worker nodes for my cluster?"
- }
+ {},
+ `(function() {
+ const CONSENT_KEY = 'gardener-kapa-consent';
+
+ // Inject CSS to prevent search bar background changes
+ function injectLayoutFixes() {
+ const style = document.createElement('style');
+ style.textContent = \`
+ /* Prevent search bar background from changing */
+ .VPNavBarSearch .DocSearch-Button,
+ .VPNavBarSearch .DocSearch-Button:hover,
+ .VPNavBarSearch .DocSearch-Button:focus,
+ .VPNavBarSearch .DocSearch-Button:active {
+ background-color: var(--vp-c-bg-alt) !important;
+ }
+
+ /* Wrapper inherits layout from VitePress - transparent wrapper */
+ #kapa-search-wrapper {
+ display: contents;
+ }
+
+ /* Settings button positioned right next to search bar */
+ #kapa-settings-btn {
+ margin-left: 12px;
+ }
+
+ /* Ensure VitePress navbar maintains proper responsive layout */
+ .VPNavBar .container,
+ .VPNavBar .content {
+ max-width: 100% !important;
+ }
+
+ /* Prevent navbar overflow on pages with sidebar */
+ @media (min-width: 960px) {
+ .has-sidebar .VPNavBar .container {
+ padding-right: 32px !important;
+ }
+ }
+
+ /* Ensure navbar doesn't extend beyond viewport */
+ .VPNav {
+ position: sticky !important;
+ top: 0 !important;
+ width: 100% !important;
+ max-width: 100vw !important;
+ }
+
+ /* Dark mode support for Kapa.ai widget */
+ .dark [id*="kapa"][role="dialog"],
+ .dark [class*="kapa-modal"],
+ .dark [class*="kapa"] [role="dialog"] {
+ background-color: #1e1e1e !important;
+ color: #e0e0e0 !important;
+ }
+
+ .dark [id*="kapa"][role="dialog"] [class*="header"],
+ .dark [id*="kapa"][role="dialog"] [class*="title"] {
+ background-color: #009f76 !important;
+ color: white !important;
+ }
+
+ .dark [id*="kapa"][role="dialog"] input,
+ .dark [id*="kapa"][role="dialog"] textarea {
+ background-color: #2a2a2a !important;
+ color: #e0e0e0 !important;
+ border-color: #444 !important;
+ }
+ \`;
+ document.head.appendChild(style);
+ }
+
+ // Inject CSS immediately
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', injectLayoutFixes);
+ } else {
+ injectLayoutFixes();
+ }
+
+ function getConsent() {
+ return localStorage.getItem(CONSENT_KEY);
+ }
+
+ function setConsent(value) {
+ localStorage.setItem(CONSENT_KEY, value);
+ }
+
+ function loadKapaWidget(withConsent) {
+ const script = document.createElement('script');
+ script.async = true;
+ script.src = 'https://widget.kapa.ai/kapa-widget.bundle.js';
+ script.setAttribute('data-website-id', '3f78706b-eb4b-4bdd-867c-abcd6a8eb778');
+ script.setAttribute('data-project-name', 'Gardener');
+ script.setAttribute('data-project-color', '#009f76');
+ script.setAttribute('data-modal-header-bg-color', '#009f76');
+ script.setAttribute('data-modal-title-color', '#FFFFFF');
+ script.setAttribute('data-project-logo', 'https://gardener.cloud/gardener-logo-white.svg');
+ script.setAttribute('data-modal-override-open-selector-search', 'div#local-search');
+ script.setAttribute('data-modal-open-on-command-k', 'true');
+ script.setAttribute('data-modal-command-k-search-mode-default', 'true');
+ script.setAttribute('data-modal-example-questions', "How do I access my shoot cluster after it's created?,What happens during the daily maintenance window?,How do I configure worker nodes for my cluster?");
+
+ if (withConsent) {
+ script.setAttribute('data-search-mode', 'integrated');
+ script.setAttribute('data-search-mode-enabled', 'true');
+ } else {
+ script.setAttribute('data-search-mode', 'search-only');
+ script.setAttribute('data-button-hide', 'true');
+ script.setAttribute('data-user-analytics-cookie-enabled', 'false');
+ }
+
+ document.head.appendChild(script);
+ }
+
+ function showConsentModal() {
+ const isDark = document.documentElement.classList.contains('dark');
+ const modal = document.createElement('div');
+ modal.id = 'kapa-consent-modal';
+ modal.style.cssText = 'position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.6);display:flex;align-items:center;justify-content:center;z-index:999999;';
+
+ const content = document.createElement('div');
+ content.style.cssText = 'background:' + (isDark ? '#1e1e1e' : 'white') + ';border-radius:8px;max-width:500px;padding:32px;margin:20px;box-shadow:0 4px 20px rgba(0,0,0,0.2);';
+
+ const title = document.createElement('h2');
+ title.textContent = 'Gardener AI Assistant';
+ title.style.cssText = 'margin:0 0 16px 0;color:#009f76;font-size:24px;';
+
+ const text = document.createElement('p');
+ text.innerHTML = 'Our AI assistant uses your questions to provide answers based on Gardener documentation. Your questions and interactions may be anonymously collected and analyzed to improve the search functionality and overall user experience. We don\\'t collect any personally identifiable information. By accepting, you consent to using this AI-powered feature and the collection of your data. AI-generated responses may contain inaccuracies - please verify important information with the official documentation.';
+ text.style.cssText = 'margin:0 0 24px 0;line-height:1.6;color:' + (isDark ? '#d0d0d0' : '#333') + ';font-size:15px;';
+
+ const buttons = document.createElement('div');
+ buttons.style.cssText = 'display:flex;gap:12px;justify-content:flex-end;';
+
+ const cancelBtn = document.createElement('button');
+ cancelBtn.textContent = 'Cancel';
+ cancelBtn.style.cssText = 'padding:10px 20px;border:1px solid #ddd;background:white;color:#333;border-radius:6px;cursor:pointer;font-size:14px;font-weight:500;';
+ cancelBtn.onmouseover = () => {
+ cancelBtn.style.background = '#f5f5f5';
+ cancelBtn.style.color = '#000';
+ };
+ cancelBtn.onmouseout = () => {
+ cancelBtn.style.background = 'white';
+ cancelBtn.style.color = '#333';
+ };
+ cancelBtn.onclick = () => {
+ document.body.removeChild(modal);
+ // Reset body styles that might affect layout
+ document.body.style.overflow = '';
+ document.body.style.paddingRight = '';
+ };
+
+ const rejectBtn = document.createElement('button');
+ rejectBtn.textContent = 'Reject';
+ rejectBtn.style.cssText = 'padding:10px 20px;border:1px solid #ddd;background:white;color:#333;border-radius:6px;cursor:pointer;font-size:14px;font-weight:500;';
+ rejectBtn.onmouseover = () => {
+ rejectBtn.style.background = '#f5f5f5';
+ rejectBtn.style.color = '#000';
+ };
+ rejectBtn.onmouseout = () => {
+ rejectBtn.style.background = 'white';
+ rejectBtn.style.color = '#333';
+ };
+ rejectBtn.onclick = () => {
+ setConsent('rejected');
+ document.body.removeChild(modal);
+ const placeholder = document.getElementById('kapa-placeholder-btn');
+ if (placeholder) placeholder.remove();
+ // Reset body styles that might affect layout
+ document.body.style.overflow = '';
+ document.body.style.paddingRight = '';
+ };
+
+ const acceptBtn = document.createElement('button');
+ acceptBtn.textContent = 'Accept';
+ acceptBtn.style.cssText = 'padding:10px 20px;border:none;background:#009f76;color:white;border-radius:6px;cursor:pointer;font-size:14px;';
+ acceptBtn.onmouseover = () => acceptBtn.style.background = '#00885f';
+ acceptBtn.onmouseout = () => acceptBtn.style.background = '#009f76';
+ acceptBtn.onclick = () => {
+ setConsent('accepted');
+ document.body.removeChild(modal);
+ const placeholder = document.getElementById('kapa-placeholder-btn');
+ if (placeholder) placeholder.remove();
+ // Reset body styles before reload
+ document.body.style.overflow = '';
+ document.body.style.paddingRight = '';
+ window.location.reload();
+ };
+
+ buttons.appendChild(cancelBtn);
+ buttons.appendChild(rejectBtn);
+ buttons.appendChild(acceptBtn);
+ content.appendChild(title);
+ content.appendChild(text);
+ content.appendChild(buttons);
+ modal.appendChild(content);
+ document.body.appendChild(modal);
+
+ modal.onclick = (e) => {
+ if (e.target === modal) {
+ document.body.removeChild(modal);
+ // Reset body styles that might affect layout
+ document.body.style.overflow = '';
+ document.body.style.paddingRight = '';
+ }
+ };
+ }
+
+ function createPlaceholderButton() {
+ const btn = document.createElement('button');
+ btn.id = 'kapa-placeholder-btn';
+ btn.title = 'AI Chat Assistant';
+ btn.innerHTML = '';
+ btn.style.cssText = 'position:fixed;bottom:20px;right:20px;width:56px;height:56px;border-radius:50%;background:#009f76;color:white;border:none;cursor:pointer;box-shadow:0 4px 12px rgba(0,0,0,0.2);display:flex;align-items:center;justify-content:center;z-index:9999;transition:transform 0.2s;';
+ btn.onmouseenter = () => btn.style.transform = 'scale(1.05)';
+ btn.onmouseleave = () => btn.style.transform = 'scale(1)';
+ btn.onclick = showConsentModal;
+ document.body.appendChild(btn);
+ }
+
+ function createSettingsButton() {
+ const btn = document.createElement('button');
+ btn.id = 'kapa-settings-btn';
+ btn.title = 'AI Assistant Preferences';
+ btn.innerHTML = '';
+ // Initial minimal styling - will be fully styled when inserted
+ btn.style.cssText = 'display:none;';
+ btn.onmouseover = () => {
+ btn.style.borderColor = '#009f76';
+ btn.style.color = '#009f76';
+ };
+ btn.onmouseout = () => {
+ btn.style.borderColor = 'var(--vp-c-divider)';
+ btn.style.color = 'var(--vp-c-text-2)';
+ };
+ btn.onclick = () => {
+ const isDark = document.documentElement.classList.contains('dark');
+ const currentConsent = getConsent();
+ const modal = document.createElement('div');
+ modal.style.cssText = 'position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.6);display:flex;align-items:center;justify-content:center;z-index:999999;';
+
+ const content = document.createElement('div');
+ content.style.cssText = 'background:' + (isDark ? '#1e1e1e' : 'white') + ';border-radius:8px;max-width:500px;padding:32px;margin:20px;box-shadow:0 4px 20px rgba(0,0,0,0.2);';
+
+ const title = document.createElement('h2');
+ title.textContent = 'AI Assistant Preferences';
+ title.style.cssText = 'margin:0 0 16px 0;color:#009f76;font-size:24px;';
+
+ const status = document.createElement('p');
+ status.innerHTML = 'Current status: ' + (currentConsent === 'accepted' ? 'AI Chat enabled with analytics' : 'Search only, no analytics');
+ status.style.cssText = 'margin:0 0 16px 0;padding:12px;background:' + (currentConsent === 'accepted' ? '#e8f5e9' : '#fff3e0') + ';border-radius:4px;color:' + (currentConsent === 'accepted' ? '#2e7d32' : '#e65100') + ';';
+
+ const text = document.createElement('p');
+ text.innerHTML = 'Our AI assistant uses your questions to provide answers based on Gardener documentation. Your questions and interactions may be anonymously collected and analyzed to improve the search functionality and overall user experience. We don\\'t collect any personally identifiable information. By accepting, you consent to using this AI-powered feature and the collection of your data. AI-generated responses may contain inaccuracies - please verify important information with the official documentation.';
+ text.style.cssText = 'margin:0 0 24px 0;line-height:1.6;color:' + (isDark ? '#d0d0d0' : '#333') + ';font-size:15px;';
+
+ const buttons = document.createElement('div');
+ buttons.style.cssText = 'display:flex;gap:12px;justify-content:flex-end;';
+
+ const closeBtn = document.createElement('button');
+ closeBtn.textContent = 'Close';
+ closeBtn.style.cssText = 'padding:10px 20px;border:1px solid #ddd;background:white;color:#333;border-radius:6px;cursor:pointer;font-size:14px;font-weight:500;';
+ closeBtn.onmouseover = () => {
+ closeBtn.style.background = '#f5f5f5';
+ closeBtn.style.color = '#000';
+ };
+ closeBtn.onmouseout = () => {
+ closeBtn.style.background = 'white';
+ closeBtn.style.color = '#333';
+ };
+ closeBtn.onclick = () => {
+ document.body.removeChild(modal);
+ // Reset body styles that might affect layout
+ document.body.style.overflow = '';
+ document.body.style.paddingRight = '';
+ };
+
+ const toggleBtn = document.createElement('button');
+ toggleBtn.textContent = currentConsent === 'accepted' ? 'Disable AI Chat' : 'Enable AI Chat';
+ toggleBtn.style.cssText = 'padding:10px 20px;border:none;background:#009f76;color:white;border-radius:6px;cursor:pointer;font-size:14px;';
+ toggleBtn.onmouseover = () => toggleBtn.style.background = '#00885f';
+ toggleBtn.onmouseout = () => toggleBtn.style.background = '#009f76';
+ toggleBtn.onclick = () => {
+ setConsent(currentConsent === 'accepted' ? 'rejected' : 'accepted');
+ document.body.removeChild(modal);
+ // Reset body styles before reload
+ document.body.style.overflow = '';
+ document.body.style.paddingRight = '';
+ window.location.reload();
+ };
+
+ buttons.appendChild(closeBtn);
+ buttons.appendChild(toggleBtn);
+ content.appendChild(title);
+ content.appendChild(status);
+ content.appendChild(text);
+ content.appendChild(buttons);
+ modal.appendChild(content);
+ document.body.appendChild(modal);
+
+ modal.onclick = (e) => {
+ if (e.target === modal) {
+ document.body.removeChild(modal);
+ // Reset body styles that might affect layout
+ document.body.style.overflow = '';
+ document.body.style.paddingRight = '';
+ }
+ };
+ };
+
+ // Wrap search bar and insert button next to it
+ const insertButton = setInterval(() => {
+ const searchBar = document.querySelector('.VPNavBarSearch');
+ if (searchBar && !document.getElementById('kapa-settings-btn')) {
+ clearInterval(insertButton);
+
+ // Create wrapper div
+ const wrapper = document.createElement('div');
+ wrapper.id = 'kapa-search-wrapper';
+
+ // Insert wrapper in place of search bar
+ searchBar.parentNode.insertBefore(wrapper, searchBar);
+
+ // Move search bar into wrapper
+ wrapper.appendChild(searchBar);
+
+ // Style the button for inline positioning
+ btn.style.cssText = 'width:32px;height:32px;border-radius:6px;background:var(--vp-c-bg);color:var(--vp-c-text-2);border:1px solid var(--vp-c-divider);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all 0.2s;box-shadow:0 1px 2px rgba(0,0,0,0.1);flex-shrink:0;';
+
+ // Add button to wrapper
+ wrapper.appendChild(btn);
+ }
+ }, 100);
+
+ setTimeout(() => clearInterval(insertButton), 5000);
+ }
+
+ const consent = getConsent();
+ if (consent === 'accepted') {
+ loadKapaWidget(true);
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', createSettingsButton);
+ } else {
+ createSettingsButton();
+ }
+ } else {
+ loadKapaWidget(false);
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', () => {
+ if (!consent) createPlaceholderButton();
+ createSettingsButton();
+ });
+ } else {
+ if (!consent) createPlaceholderButton();
+ createSettingsButton();
+ }
+ }
+ })();`
],
[
'script',
diff --git a/.vitepress/theme/style.css b/.vitepress/theme/style.css
index 52c27b328..a1e2c0659 100644
--- a/.vitepress/theme/style.css
+++ b/.vitepress/theme/style.css
@@ -106,3 +106,8 @@ img[src='/search.png'] {
display: inline-flex;
align-items: center;
}
+
+/* Hide VitePress local search modal to use kapa.ai search instead */
+.VPLocalSearchBox {
+ display: none !important;
+}