Skip to content

feat: add Kapa.ai Ask AI widget to docs header#180

Merged
marc0olo merged 8 commits into
mainfrom
infra/kapa-widget
Apr 30, 2026
Merged

feat: add Kapa.ai Ask AI widget to docs header#180
marc0olo merged 8 commits into
mainfrom
infra/kapa-widget

Conversation

@marc0olo
Copy link
Copy Markdown
Member

Summary

  • Adds a branded Ask AI button to the site header, placed right of the Pagefind search with an 8 px gap — visually related but clearly a separate control
  • Button uses a three-star sparkle SVG icon (terracotta, --icp-accent) with a gentle idle pulse animation; shows "Ask AI" label on desktop, icon-only on mobile
  • Kapa widget script is injected dynamically from public/kapa.js (not inlined in astro.config.mjs) so the code is readable and independently editable
  • Initial theme colours are resolved at inject time by reading data-theme on <html> (set synchronously by ThemeProvider before any other scripts run)
  • Dark mode live switching: a MutationObserver watches data-theme changes and flips data-mantine-color-scheme on kapa's #kapa-widget-root inside the open shadow root, then injects a <style> with ICP brand tokens (--mantine-color-body, --mantine-color-text, etc.) — no widget re-initialisation required
  • CSP extended for widget.kapa.ai, proxy.kapa.ai, metrics.kapa.ai, and hCaptcha (script-src, style-src, img-src, connect-src, frame-src)
  • Reuses the portal's website ID (73cafe70-9be1-494b-bd31-b849fc29799f)

Files changed

File Change
src/components/AskAIButton.astro New — button component with sparkle SVG
public/kapa.js New — widget bootstrap + dark mode sync logic
src/components/Header.astro Import and render AskAIButton next to Search
src/styles/custom.css Button styles + sparkle animation
astro.config.mjs Add <script src="/kapa.js" defer> to head
public/.ic-assets.json5 Extend CSP for kapa and hCaptcha domains

Sync recommendation

hand-written — no upstream source material; implementation informed by the portal's kapa config in .sources/portal/docusaurus.config.js and DOM inspection of the live widget.

Adds the Kapa.ai AI assistant widget with a branded "Ask AI" button
in the site header, clearly distinguished from the Pagefind doc search.

- AskAIButton.astro: sparkle icon + "Ask AI" label, icon-only on mobile
- kapa.js: dynamic widget bootstrap that reads data-theme before injecting
  kapa's script, so initial colours are always correct for the active mode
- Dark mode live switching: MutationObserver flips data-mantine-color-scheme
  on kapa's open shadow root and injects ICP brand tokens as CSS variable
  overrides, keeping the modal in sync when the user toggles theme mid-session
- CSP updated: script-src, style-src, img-src, connect-src, and frame-src
  extended for widget.kapa.ai, proxy.kapa.ai, metrics.kapa.ai, and hCaptcha
- Add coding agents question, reorder to two full-width intros
- Fix header layout shift on modal open with scrollbar-gutter: stable
react-remove-scroll stamps data-scroll-locked on body and injects
`body[data-scroll-locked] { margin-right: 17px !important }` to
compensate for the scrollbar disappearing on scroll-lock. With
scrollbar-gutter: stable already reserving that space, the margin
double-compensates and shifts content 17px left.

Primary fix: @layer kapa-fix in custom.css — a layered !important
beats an unlayered !important per CSS Cascade 5 regardless of
specificity or source order. Backup: MutationObserver in kapa.js
patches the injected node's text content directly.
Starlight's header grid column 1 formula places search aligned with the
content area start on sidebar+TOC pages. On splash pages (no sidebar),
column 1 collapsed to the site title width, leaving search noticeably
left of its position on docs pages at wider viewports.

Fix: override grid-template-columns on :root:not([data-has-sidebar])
using the same formula Starlight derives for sidebar+TOC pages —
(sidebar-width - nav-pad-x) + max(0, (100% - 2×sidebar-width - content-width) / 2 - nav-gap).

Starlight hardcodes --sl-content-width: 67.5rem (= 45rem × 1.5) on
splash pages, which would corrupt the centering calc. A mirror variable
--icp-content-width tracks the real responsive content-width values and
is used in the formula instead.
@marc0olo marc0olo merged commit a259e3b into main Apr 30, 2026
1 check passed
@marc0olo marc0olo deleted the infra/kapa-widget branch April 30, 2026 13:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant