Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 109 additions & 56 deletions _components/SearchInput.tsx
Original file line number Diff line number Diff line change
@@ -1,76 +1,129 @@
export default function SearchInput() {
return (
<div className="md:relative w-full">
{/* ☝️ That md:relative class is crucial for making the search bar pop up in the right place. Don't change it, or add any other positioning classes, unless you're ready to account for positioning across all breakpoints. */}
<div className="relative">
<input
type="search"
placeholder="Search"
id="orama-search-input"
className="w-full min-w-24 rounded-lg placeholder:text-sm text-base leading-normal p-1 pl-8 border transition-all duration-150
text-foreground-primary border-foreground-secondary hover:bg-background-secondary focus:bg-background-secondary focus:outline-offset-1"
style="background: url(/img/search.svg) no-repeat 0.5em 50%; background-size: 1.25em; background-color: var(--color-background-raw);"
/>
<kbd
id="search-key"
className="hidden xs:flex pointer-events-none absolute font-sans rounded-sm top-1 right-1 bottom-1 w-auto border-1 border-foreground-tertiary border-b-2 border-r-2 bg-background-primary text-foreground-secondary text-center text-xs font-bold p-2 items-center justify-center dark:bg-background-secondary dark:border-gray-700"
>
⌘K
</kbd>
<div
id="orama-search-loading"
className="absolute left-2 top-1/2 transform -translate-y-1/2 hidden bg-background-raw"
>
<div className="animate-spin rounded-full h-4 w-4 border-2 border-transparent border-r-foreground-primary bg-background-raw" />
</div>
<div
className="sr-only"
aria-live="polite"
id="orama-results-announcer"
>
{/* Text updated by JavaScript. */}
<>
{/* Search Input Trigger */}
<div className="md:relative w-full">
<div className="relative">
<input
type="search"
placeholder="Search documentation..."
id="orama-search-input"
className="w-full min-w-24 rounded-lg placeholder:text-sm text-base leading-normal p-1 px-8 border transition-colors duration-200
text-foreground-primary border-foreground-secondary hover:bg-background-secondary focus:bg-background-secondary focus:outline-offset-1
cursor-pointer"
style="background: url(/img/search.svg) no-repeat 0.5em 50%; background-size: 1.25em; background-color: var(--color-background-raw);"
readOnly
/>
<kbd
id="search-key"
className="hidden xs:flex pointer-events-none absolute font-sans rounded-sm top-1 right-1 bottom-1 w-auto border-1 border-foreground-tertiary border-b-2 border-r-2 bg-background-primary text-foreground-secondary text-center text-xs font-bold p-2 items-center justify-center dark:bg-background-secondary dark:border-gray-700"
>
⌘K
</kbd>
</div>
</div>

{/* Enhanced Popover for Search Results */}
<div
id="orama-search-results"
className="absolute inset-2 left-2 right-2 h-[calc(100vh-8rem)] top-10 md:top-full md:left-auto md:right-0 mt-2 bg-background-raw border border-foreground-tertiary rounded-xl shadow-2xl z-50 md:max-h-128 overflow-hidden hidden md:min-w-160 max-w-2xl"
{/* Search Modal */}
<dialog
id="orama-search-modal"
className="w-full h-full min-h-dvh bg-black/30 [-webkit-backdrop-filter:blur(10px)] backdrop-blur-sm fixed inset-0 max-w-none max-h-none z-50 overflow-y-auto p-4 sm:p-6 md:p-20 transition-all duration-200"
role="dialog"
>
<div
id="orama-search-results-content"
className="overflow-y-auto h-full"
>
{/* Results will be populated via JavaScript */}
</div>
<div className="flex flex-col justify-between mx-auto max-w-2xl w-full transform overflow-hidden rounded-xl bg-background-raw shadow-2xl border border-foreground-primary dark:border-gray-700">
{/* Search Header */}
<div className="relative flex items-center justify-between px-2">
<input
type="search"
id="orama-search-input-modal"
className="h-12 w-full border-0 bg-transparent text-foreground-primary placeholder:text-foreground-secondary focus:ring-0 text-base focus-visible:outline-none"
placeholder="Search documentation..."
autoFocus
autoComplete="off"
autoCorrect="off"
spellcheck={false}
style="background: url(/img/search.svg) no-repeat 0.5em 50%; background-size: 1.25em; background-color: var(--color-background-raw);"
/>

{/* Mode Toggle */}
<div className="inset-y-0 right-0 flex items-center shrink-0">
<button
type="button"
id="search-mode-toggle"
className="flex items-center px-2 py-1 gap-x-1 text-xs font-medium text-foreground-secondary hover:text-foreground-primary transition-colors cursor-pointer"
title="Toggle AI search mode (Ctrl+Shift+K)"
aria-pressed="false"
>
<div
id="search-mode-toggle__indicator"
className="flex items-center w-6 h-4 rounded-full bg-foreground-tertiary p-0.5 relative dark:bg-gray-600"
>
<div class="aspect-square h-3 bg-background-raw rounded-full transition-transform duration-200" />
</div>
<span>Ask AI</span>
</button>
</div>

{/* Loading Indicator */}
<div
id="orama-search-loading"
className="absolute left-4 px-px top-1/2 transform -translate-y-1/2 hidden bg-background-raw"
>
<div className="animate-spin rounded-full h-4 w-4 border-2 border-transparent border-r-foreground-primary" />
</div>
</div>

{/* Footer with search tips */}
<div className="border-t border-foreground-tertiary bg-background-secondary px-4 py-2 sticky bottom-0">
<div className="flex items-center gap-6 text-xs text-foreground-secondary">
{/* Search Results */}
<div
id="orama-search-results"
className="max-h-[calc(100vh-18rem)] lg:max-h-80 scroll-py-2 overflow-y-auto text-sm"
>
<div
id="orama-search-results-content"
style="scrollbar-gutter: stable;"
>
{/* Results will be populated via JavaScript */}
</div>
</div>

{/* Footer with keyboard shortcuts */}
<footer className="hidden xs:flex flex-wrap gap-x-6 gap-y-2 items-center bg-background-secondary px-4 py-3 text-xs text-foreground-secondary">
<span>
<kbd className="px-1.5 py-0.5 text-xs font-semibold text-foreground-secondary bg-background-primary border-r-2 border-b-2 border border-foreground-tertiary rounded mr-1">
<kbd class="font-sans px-1.5 py-0.5 text-xs font-semibold text-foreground-secondary bg-background-primary border-r-2 border-b-2 border border-foreground-tertiary rounded mr-1">
<span aria-hidden="true">↑↓</span>
<span className="sr-only">Up or down to</span>
</kbd>
navigate
<span class="sr-only">Up or down to</span>
</kbd>navigate
</span>
<span>
<kbd className="px-1.5 py-0.5 text-xs font-semibold text-foreground-secondary bg-background-primary border-r-2 border-b-2 border border-foreground-tertiary rounded mr-1">
<kbd class="font-sans px-1.5 py-0.5 text-xs font-semibold text-foreground-secondary bg-background-primary border-r-2 border-b-2 border border-foreground-tertiary rounded mr-1">
<span aria-hidden="true">↵</span>
<span className="sr-only">Enter to</span>
</kbd>
select
<span class="sr-only">Enter to</span>
</kbd>select
</span>
<span>
<kbd className="px-1.5 py-0.5 text-xs font-semibold text-foreground-secondary bg-background-primary border-r-2 border-b-2 border border-foreground-tertiary rounded mr-1">
<kbd class="font-sans px-1.5 py-0.5 text-xs font-semibold text-foreground-secondary bg-background-primary border-r-2 border-b-2 border border-foreground-tertiary rounded mr-1">
<span aria-hidden="true">ESC</span>
<span className="sr-only">Escape to</span>
<span class="sr-only">Escape to</span>
</kbd>close
</span>
<span className="flex items-center ml-auto">
<kbd class="font-sans px-1.5 py-0.5 text-xs font-semibold text-foreground-secondary bg-background-primary border-r-2 border-b-2 border border-foreground-tertiary rounded mr-1">
⌘⇧K
</kbd>
close
<span className="hidden sm:inline">Toggle AI</span>
<span className="sm:hidden">AI</span>
</span>
</div>
</footer>
</div>
</div>
</div>

{/* Screen reader announcements */}
<div
className="sr-only"
aria-live="polite"
id="orama-results-announcer"
>
{/* Text updated by JavaScript */}
</div>
</dialog>
</>
);
}
Loading