Skip to content

docs: redesign search dialog with persistent Ask AI footer + cleaner results#53

Open
hongyi-chen wants to merge 11 commits intomainfrom
oz/search-dialog-redesign
Open

docs: redesign search dialog with persistent Ask AI footer + cleaner results#53
hongyi-chen wants to merge 11 commits intomainfrom
oz/search-dialog-redesign

Conversation

@hongyi-chen
Copy link
Copy Markdown
Collaborator

@hongyi-chen hongyi-chen commented May 10, 2026

Summary

Redesigns the docs site's search dialog so it reads as part of the same Scalar-style chrome family as the rest of the site, with GitBook-style affordances on top. The new dialog has a persistent Ask AI footer, surfaces keyboard shortcuts, groups page results into single cards with indented sub-results, and tightens the chrome throughout — light and dark modes, desktop and mobile.

What changed (user-visible)

Persistent footer at the bottom of the dialog

  • Ask AI CTA with a live label that flips between Ask AI and Ask AI: "<query>" as the user types. Clicking routes the typed query into the Kapa Ask chat panel (handoff via window.__warpAskAiQuery).
  • ⌘+I / Ctrl+I keyboard chip is always visible on the CTA; the platform glyph swaps based on navigator.platform.
  • Keyboard hint strip (↑↓ Navigate · ↵ Select · Esc Close) below the CTA on desktop, hidden under 50rem.
  • The footer is flex-pinned at the bottom of the dialog; the results area scrolls between the form and the footer.
  • Opening the Kapa Ask panel (via the global shortcut, sidebar trigger, or in-search CTA) now closes the search dialog so the two modals don't stack.

Cleaner result cards

  • Breadcrumb above each result title (Topic › Section), derived from the URL with a small topic-label map mirrored from src/sidebar.ts.
  • Per-page card chrome: each .pagefind-ui__result (the <li> per page) carries the background + hairline border + radius, so the parent title and its sub-results render as one grouped card.
  • Continuous left-rail on sub-results: a 2px border-inline-start on each .pagefind-ui__result-nested, combined with --sl-search-result-spacing: 0, paints one unbroken vertical bar from the first sub-result down through the last. Sub-results are smaller-typeface (--sl-text-xs semibold title, --sl-text-2xs excerpt) so hierarchy is obvious.
  • Page-level excerpt suppressed when sub-results exist (via :has()), so each card shows breadcrumb + title + sub-results without repeating the same matched content.
  • Copy page dropdown is excluded from the Pagefind index (data-pagefind-ignore on CopyPageButton.astro), so its strings stop leaking into every excerpt.
  • <mark> highlight restyled to a neutral chip in both themes; light-mode --sl-color-black (which evaluates to white) overrides removed so query + mark text are legible.

Search-bar polish

  • Magnifier and clear (X) icons unified to matched Lucide SVGs (stroke-width: 2, rounded caps/joins) via mask-image. Both pinned to 16×16 so the X stops ballooning on narrow viewports.
  • Focus border uses the neutral chrome hover ladder (--warp-control-border-hover) instead of the saturated Warp blue accent. Browser default focus outline on the input is stripped — the form border swap is the visible affordance.
  • Mobile Cancel button hidden; the search input now spans the full dialog width at narrow widths. Mobile users still close via backdrop tap and ESC.

Empty state + spacing

  • Dropped Starlight's dialog { min-height: 15rem } so the empty dialog sizes to form + footer with no dead space.
  • Hard-zeroed margins on .pagefind-ui__form / .pagefind-ui__drawer / .pagefind-ui__results-area / .pagefind-ui__results so the "N results" message sits flush against the form above and the first card below.

Modal hygiene + scoping

  • Scoped ::selection inside the dialog so drag-selecting result text uses the chrome palette instead of the OS accent.
  • Dialog body uses --sl-color-bg (same as the page canvas) with a hairline border + soft scrim, in family with the rest of the chrome.

Files touched

  • src/styles/warp-components.css — bulk of the work in §18 (search dialog chrome) and §19 (footer, Ask AI CTA, keyboard hints, breadcrumb).
  • src/components/CustomSidebar.astro — rewrote the inline <script is:inline> that augments the Pagefind dialog (footer build, breadcrumb injection, arrow-key nav with Ask AI as the last navigable item, live label updates).
  • src/components/KapaChatLauncher.tsxopenPanel() closes any open search dialog before opening Kapa, covering all three open-paths.
  • src/components/CopyPageButton.astrodata-pagefind-ignore on the dropdown wrapper.

Validation

  • npm run build ✅ — 316 pages, Pagefind index rebuilds cleanly.
  • CI green on the latest push (Analyze JS/TS, Python, Actions, CodeQL, Vercel preview).
  • Manual smoke:
    • ⌘K opens the dialog; type → Ask AI label flips to Ask AI: "<query>"; arrow-down past last result lands on Ask AI; Enter opens Kapa with the query auto-submitted.
    • Toggle light/dark theme → marks, breadcrumbs, query span, kbd chips all legible.
    • Narrow viewport → no Cancel button, X icon at 16px, search bar spans full width.
    • Drag-select inside the dialog → neutral selection wash, no OS accent leak.
    • Search changelog → page-grouped cards with continuous left rail on the sub-results.

Out of scope (follow-ups for later)

  • Migrating from @pagefind/default-ui to Pagefind 1.5's Component UI (<pagefind-modal>) — much larger refactor.
  • Empty-state placeholder copy ("Start typing to search…").
  • Filter chips (no Pagefind filters configured today).

Artifacts

Co-Authored-By: Oz [email protected]

…results

- Add sticky bottom footer with 'Ask AI: "<query>"' CTA + keyboard hint strip
- Make search form sticky at top of dialog
- Add Topic > Section breadcrumb above each result; tighten title/excerpt
- Restyle <mark> highlight to a neutral chip; drop tree-diagram icon
- Move Ask AI to last navigable item; always show ⌘+I/Ctrl+I shortcut
- Close search dialog when Kapa Ask panel opens (all open paths)

Co-Authored-By: Oz <[email protected]>
@cla-bot cla-bot Bot added the cla-signed label May 10, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented May 10, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment May 10, 2026 11:46pm

Request Review

- Switch dialog frame to flex column so the results scroll and the
  footer is pinned by layout (restores Pagefind's magnifier + clear
  icons that were broken by the sticky-form padding)
- Exclude CopyPageButton from the Pagefind index via
  data-pagefind-ignore so 'Copy page', 'Copy page as Markdown for
  LLMs', etc. stop leaking into every result excerpt
- Footer: bump surface to var(--sl-color-gray-6), border-top to
  var(--sl-color-hairline), and add a soft scrim above so it reads
  as clearly pinned
- Light-mode fixes: drop the broken var(--sl-color-black) overrides
  on <mark> and the Ask AI query span (--sl-color-black is WHITE in
  light mode); --sl-color-white is mode-aware and works in both
- Style the 'Load more results' button + tighten 'N results' message
  spacing and footer gap/padding
- Add scoped ::selection so dragging across results uses the chrome
  palette instead of the saturated OS accent

Co-Authored-By: Oz <[email protected]>
Set --pagefind-ui-border AND border-color on .pagefind-ui__form:focus-within
directly (CSS variables don't cascade upward, so the prior override on
input:focus alone never repainted the form). Also kill the browser's
default focus outline on the input \u2014 the form border swap is the visible
focus affordance.

Co-Authored-By: Oz <[email protected]>
var(--sl-color-gray-6) is Oz #252b37 in dark mode \u2014 visibly cool/blue
against the neutral #121212 canvas, out of family with the rest of the
chrome. Move back to var(--sl-color-bg) (matches the dialog body) and
strengthen the box-shadow scrim above the footer to keep the pinned
separation crisp.

Co-Authored-By: Oz <[email protected]>
- Move card chrome (bg + border + radius) to .pagefind-ui__result so the
  parent title and its sub-results render as one grouped card per page,
  with the parent title at top and sub-results indented inside
- Sub-results (.pagefind-ui__result-nested) get a 1px left rule + indent
  so they read as children of the parent above
- Inter-card spacing (margin-bottom: 0.75rem on .pagefind-ui__result) is
  visibly larger than intra-card spacing (--sl-search-result-spacing:
  0.125rem) so different pages are clearly separated
- Tighten 'N results for <query>' message: reset .pagefind-ui__drawer
  and .pagefind-ui__results margin-top to 0, message bottom margin 0.5rem
- Empty state: override Starlight's dialog min-height: 15rem -> auto so
  the dialog sizes to its content (form + footer) instead of forcing
  ~150px of dead space when no results are shown

Co-Authored-By: Oz <[email protected]>
- Hard zero the chrome around 'N results' message: reset margins/padding
  on .pagefind-ui__form, .pagefind-ui__drawer, .pagefind-ui__results-area,
  and .pagefind-ui__results so the message sits flush against the form
  above and the first card below
- Drop the left rule on sub-results (read as a hard outline competing
  with the card edge); use indent + smaller type-scale to signal
  hierarchy (sub-result title --sl-text-xs, excerpt --sl-text-2xs)
- Hide redundant parent excerpt when sub-results exist via :has() so
  each card shows breadcrumb + title + sub-results without repeating
  the same matched content
- Softer hover wash on sub-results (rgba white/black 0.04) so hovering
  stays inside the card surface
- Subtler card border via --sl-color-hairline-light + tighter card
  padding (0.5rem 0) + inter-card margin-bottom: 0.5rem
- Unify the magnifier + clear-X icons by overriding Pagefind's mask-image
  with matched Lucide SVGs (stroke-width:2, rounded caps/joins) so the
  pair reads as one icon family inside the dialog

Co-Authored-By: Oz <[email protected]>
- Hide Starlight's upstream <button data-close-modal>Cancel</button> on
  all viewports so the search bar takes full width on mobile. Backdrop
  tap + ESC still close the dialog.
- Pin .pagefind-ui__form::before and .pagefind-ui__search-clear::before
  to width: 16px; height: 16px so the Lucide mask icons stop being
  stretched to Pagefind's scaled default sizes (the X was rendering
  ~40px on mobile).
- Restore a continuous left rail on sub-results: 2px
  border-inline-start on .pagefind-ui__result-nested using
  --warp-control-border-hover, plus --sl-search-result-spacing: 0 so
  rows stack flush and the per-row border paints one unbroken vertical
  bar. Margin-inline-start: 0.625rem insets the rail from the card edge.

Co-Authored-By: Oz <[email protected]>
- Refresh stale section headers + docstrings so they describe what
  actually ships: \u00a719 'sticky footer' \u2192 'flex-pinned footer';
  --sl-search-result-pad-* docstring updated to current 0.5rem block
  values; result-row transparent-bg comment rewritten to point at the
  rail rule it now coexists with; .warp-search-keyboard-hints rationale
  updated now that the Cancel button is hidden.
- Remove the unused .warp-search-breadcrumb__separator rule (the
  breadcrumb is rendered as a single textContent string with an
  embedded U+203A, no per-separator span ever exists).
- Move the inline 'margin:0 0.0625rem' on the kbd '+' span out of the
  script-built markup and into a dedicated .warp-search-ask-ai-row__kbd-plus
  CSS class.

Co-Authored-By: Oz <[email protected]>
- Collapse Pagefind's translated 'Clear' text node via font-size:0 +
  line-height:0 so only the X icon shows; the text stays in the DOM so
  screen readers still announce the button as 'Clear'.
- Drop the standalone :focus outline on .pagefind-ui__search-clear (it
  painted a partial-row chip-within-chip box at the top-right of the
  input). Extend the hover icon-color shift to :focus-visible so
  keyboard users still get a visible focus signal; the form's
  :focus-within border keeps signalling that the search input as a
  whole has focus.

Co-Authored-By: Oz <[email protected]>
- Drop the X mask to 13x13 (vs the magnifier's 16x16). Lucide's X spans
  almost the full viewBox while the magnifier's circle only fills the
  inner ~half, so identical pixel sizes made the X visually heavier.
  13px matches the optical weight of the magnifier circle.
- Push the clear button to inset-inline-end: 18px so it sits ~the same
  distance from the input's right edge as the magnifier sits from the
  left edge (~20px), giving the icon pair symmetric breathing room.

Co-Authored-By: Oz <[email protected]>
Both entry points into Kapa (the ⌘+I / Ctrl+I global shortcut and the
'Ask AI' footer CTA inside the search dialog) now hand the live search
query off to Kapa's input. Previously the ⌘+I path passed nothing, and
the Ask AI button auto-submitted via a window-stashed variable instead
of pre-filling.

- KapaChatLauncher#openPanel() is now the single owner of the handoff:
  reads .pagefind-ui__search-input.value before closing the search
  dialog (closing tears down the input), then setQuery(pendingQuery)
  so the value appears in the controlled Kapa input.
- Pre-fills instead of auto-submits so the user can refine before
  sending. The existing open-dialog effect focuses inputRef, so the
  cursor lands at the end of the pre-filled text — Enter or edit.
- Drops the timeout-based submitQuery hack. Keeps __warpAskAiQuery as
  a legacy fallback in case any other caller still uses it.
- CustomSidebar's Ask AI click handler is simplified to just route
  the click; openPanel reads the input and closes the search dialog.

Co-Authored-By: Oz <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants