This commit is contained in:
Michael Zhang 2024-05-27 01:47:22 -05:00
parent a7e4e82765
commit 66a770faec
2 changed files with 87 additions and 7 deletions

View file

@ -6,10 +6,15 @@
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
min-width: 500px;
width: 500px;
min-height: 200px;
padding: 12px;
padding: 6px;
text-wrap: wrap;
white-space: pre-wrap;
word-wrap: break-word;
overflow-wrap: break-word;
}
.entry {
@ -18,4 +23,31 @@
border-radius: 4px;
border: none;
outline: none;
}
.searchResults {
display: flex;
flex-direction: column;
align-items: stretch;
}
.searchResult {
padding: 12px;
cursor: pointer;
border-radius: 4px;
text-align: left;
background-color: unset;
border: none;
&:hover {
background-color: rgba(0, 0, 0, 0.05);
}
.title {
font-size: 1rem;
}
.subtitle {
font-size: .75rem;
}
}

View file

@ -11,10 +11,18 @@ import {
useFocus,
useInteractions,
} from "@floating-ui/react";
import { useState } from "react";
import { useDebounce } from "use-debounce";
import { useEffect, useState } from "react";
import { atom, useAtom, useSetAtom } from "jotai";
import { nodesOpenedAtom } from "../App";
const searchQueryAtom = atom("");
const showMenuAtom = atom(false);
export default function SearchBar() {
const [showMenu, setShowMenu] = useState(() => false);
const [showMenu, setShowMenu] = useAtom(showMenuAtom);
const [searchQuery, setSearchQuery] = useAtom(searchQueryAtom);
const [searchResults, setSearchResults] = useState([]);
const { refs, context, floatingStyles } = useFloating({
placement: "bottom-start",
@ -29,6 +37,22 @@ export default function SearchBar() {
useDismiss(context),
]);
useEffect(() => {
setSearchResults([]);
const trimmed = searchQuery.trim();
if (trimmed === "") return;
(async () => {
const params = new URLSearchParams();
params.set("query", trimmed);
const resp = await fetch(
`http://localhost:5195/node/search?${params.toString()}`,
);
const data = await resp.json();
setSearchResults(data.results);
})();
}, [searchQuery]);
return (
<>
<div>
@ -38,6 +62,8 @@ export default function SearchBar() {
placeholder="Search..."
onFocus={() => setShowMenu(true)}
ref={refs.setReference}
value={searchQuery}
onChange={(evt) => setSearchQuery(evt.target.value)}
{...getReferenceProps()}
/>
</div>
@ -51,7 +77,7 @@ export default function SearchBar() {
style={{ ...floatingStyles }}
{...getFloatingProps()}
>
<SearchMenu />
<SearchMenu results={searchResults} />
</div>
</FloatingOverlay>
</FloatingPortal>
@ -60,6 +86,28 @@ export default function SearchBar() {
);
}
function SearchMenu() {
return <>Search suggestions...</>;
function SearchMenu({ results }) {
const setNodesOpened = useSetAtom(nodesOpenedAtom);
const setSearchQuery = useSetAtom(searchQueryAtom);
const setShowMenu = useSetAtom(showMenuAtom);
return (
<div className={styles.searchResults}>
{results.map((result) => (
<button
type="button"
key={result.score.toString()}
className={styles.searchResult}
onClick={() => {
setSearchQuery("");
setShowMenu(false);
setNodesOpened((prev) => [result.node_id, ...prev]);
}}
>
<div className={styles.title}>{result.title}</div>
<div className={styles.subtitle}>{result.score}</div>
</button>
))}
</div>
);
}