From 03b4a5bc871f92fd4bebd19b7ab1dccb5a82d15b Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Sun, 12 Apr 2026 15:02:35 +0200 Subject: [PATCH 1/2] Add Kapa AI to the search widget Signed-off-by: Julius Volz --- docs-config.ts | 10 +++++- public/assets/prometheus-logo.svg | 1 + src/app/layout.tsx | 9 +++-- src/components/Header.tsx | 2 +- src/components/KapaWidget.tsx | 28 ++++++++++++++++ src/components/SpotlightSearch.tsx | 53 +++++++++++++++++++++++++----- src/docs-config-types.ts | 8 +++++ 7 files changed, 97 insertions(+), 14 deletions(-) create mode 100644 public/assets/prometheus-logo.svg create mode 100644 src/components/KapaWidget.tsx diff --git a/docs-config.ts b/docs-config.ts index c031e5bc9..2eec1892a 100644 --- a/docs-config.ts +++ b/docs-config.ts @@ -5,11 +5,19 @@ export default { announcement: { text: "Take the [Prometheus User Survey (Edition 03.2026)](https://forms.gle/uuEsawKm7u9wCT4T8) and help the community prioritize future development!", - mobileText: "[Prometheus User Survey (Edition 03.2026)](https://forms.gle/uuEsawKm7u9wCT4T8)", + mobileText: + "[Prometheus User Survey (Edition 03.2026)](https://forms.gle/uuEsawKm7u9wCT4T8)", startDate: "2026-03-24", endDate: "2026-04-07", }, + kapa: { + websiteId: "80cbacc9-0b84-48aa-bfb8-0002270176bf", + projectName: "Prometheus", + projectColor: "#D86444", + projectLogoPath: "/assets/prometheus-logo.svg", + }, + // Docs to load from repo-local files. localMarkdownSources: [ { diff --git a/public/assets/prometheus-logo.svg b/public/assets/prometheus-logo.svg new file mode 100644 index 000000000..c4788dab1 --- /dev/null +++ b/public/assets/prometheus-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index d2dbe1d2e..3132eff56 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -21,6 +21,7 @@ import "@mantine/code-highlight/styles.layer.css"; import "@mantine/spotlight/styles.layer.css"; import "./globals.css"; import { Header } from "@/components/Header"; +import KapaWidget from "@/components/KapaWidget"; import { ANNOUNCEMENT_HEIGHT_PX, isAnnouncementActive, @@ -53,8 +54,7 @@ export default function RootLayout({ children: React.ReactNode; }>) { const activeAnnouncement = - docsConfig.announcement && - isAnnouncementActive(docsConfig.announcement) + docsConfig.announcement && isAnnouncementActive(docsConfig.announcement) ? docsConfig.announcement : undefined; @@ -67,13 +67,16 @@ export default function RootLayout({ lang="en" {...mantineHtmlProps} className={`${interFont.variable} ${latoFont.variable}`} - style={{ "--header-height": `${headerHeightPx}px` } as React.CSSProperties} + style={ + { "--header-height": `${headerHeightPx}px` } as React.CSSProperties + } > +
diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 35efb233e..3723197d0 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -141,7 +141,7 @@ export const Header = ({ + ); +} diff --git a/src/components/SpotlightSearch.tsx b/src/components/SpotlightSearch.tsx index d26a9400b..0754518cc 100644 --- a/src/components/SpotlightSearch.tsx +++ b/src/components/SpotlightSearch.tsx @@ -1,17 +1,25 @@ "use client"; -import { Spotlight } from "@mantine/spotlight"; -import { IconSearch } from "@tabler/icons-react"; +import { Spotlight, spotlight } from "@mantine/spotlight"; +import { IconSearch, IconSparkles } from "@tabler/icons-react"; import { useRouter } from "next/navigation"; -import { Divider, Group, Highlight, Loader, Space } from "@mantine/core"; -import React, { useState, useEffect } from "react"; +import { + Button, + Divider, + Group, + Highlight, + Loader, + Space, +} from "@mantine/core"; +import React, { useState, useEffect, useRef } from "react"; import { decode } from "html-entities"; -// Extend Window interface to include pagefind +// Extend Window interface to include pagefind and Kapa declare global { interface Window { /* eslint-disable @typescript-eslint/no-explicit-any */ pagefind: any; + Kapa: any; } } @@ -127,6 +135,7 @@ type PagefindResult = { export default function SpotlightSearch() { const [activeQuery, setActiveQuery] = useState(""); const [results, setResults] = useState([]); + const queryRef = useRef(""); useEffect(() => { async function loadPagefind() { @@ -175,12 +184,24 @@ export default function SpotlightSearch() { loadPagefind(); }, []); + const handleAskAI = () => { + const query = queryRef.current.trim(); + spotlight.close(); + // Small delay to let the Spotlight close animation finish before opening Kapa. + setTimeout(() => { + if (window.Kapa) { + window.Kapa.open({ mode: "ai", query, submit: query.length > 0 }); + } + }, 100); + }; + return ( { + queryRef.current = query; const search = await window.pagefind.debouncedSearch(query); if (search === null) { // A more recent search call has been made, nothing to do. @@ -190,10 +211,24 @@ export default function SpotlightSearch() { setActiveQuery(query); }} > - } - /> + + } + style={{ flex: 1 }} + /> + + {results.length > 0 ? ( results.map((result, idx) => ( diff --git a/src/docs-config-types.ts b/src/docs-config-types.ts index 55aac1f22..9130c9caf 100644 --- a/src/docs-config-types.ts +++ b/src/docs-config-types.ts @@ -10,9 +10,17 @@ export type Announcement = { endDate?: string; }; +export type KapaConfig = { + websiteId: string; + projectName: string; + projectColor: string; + projectLogoPath: string; +}; + export type DocsConfig = { siteUrl: string; announcement?: Announcement; + kapa?: KapaConfig; localMarkdownSources: LocalMarkdownSource[]; githubMarkdownSources: GithubMarkdownSource[]; ltsVersions: LTSConfig; From 71d8bba147952844f4157e29e8b0f3423bd3cf16 Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Mon, 13 Apr 2026 13:19:49 +0200 Subject: [PATCH 2/2] Make Kapa AI widget use the site's light/dark theme Signed-off-by: Julius Volz --- src/components/KapaWidget.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/components/KapaWidget.tsx b/src/components/KapaWidget.tsx index cb8b876ec..bade03394 100644 --- a/src/components/KapaWidget.tsx +++ b/src/components/KapaWidget.tsx @@ -1,7 +1,20 @@ +"use client"; + +import { useComputedColorScheme } from "@mantine/core"; import Script from "next/script"; +import { useEffect } from "react"; import docsConfig from "../../docs-config"; export default function KapaWidget() { + const colorScheme = useComputedColorScheme("light"); + + // Sync the resolved Mantine color scheme to a data-theme attribute on + // so that the Kapa widget can detect theme changes. Kapa only watches + // class, data-theme, data-color-mode, and data-bs-theme. + useEffect(() => { + document.documentElement.setAttribute("data-theme", colorScheme); + }, [colorScheme]); + if (!docsConfig.kapa) { return null; } @@ -23,6 +36,7 @@ export default function KapaWidget() { data-project-color={projectColor} data-project-logo={projectLogoUrl} data-button-hide="true" + data-color-scheme-selector="[data-theme='dark']" /> ); }