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-left-radius: 4px;
border-bottom-right-radius: 4px; border-bottom-right-radius: 4px;
min-width: 500px; width: 500px;
min-height: 200px; min-height: 200px;
padding: 12px; padding: 6px;
text-wrap: wrap;
white-space: pre-wrap;
word-wrap: break-word;
overflow-wrap: break-word;
} }
.entry { .entry {
@ -19,3 +24,30 @@
border: none; border: none;
outline: 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, useFocus,
useInteractions, useInteractions,
} from "@floating-ui/react"; } 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() { 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({ const { refs, context, floatingStyles } = useFloating({
placement: "bottom-start", placement: "bottom-start",
@ -29,6 +37,22 @@ export default function SearchBar() {
useDismiss(context), 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 ( return (
<> <>
<div> <div>
@ -38,6 +62,8 @@ export default function SearchBar() {
placeholder="Search..." placeholder="Search..."
onFocus={() => setShowMenu(true)} onFocus={() => setShowMenu(true)}
ref={refs.setReference} ref={refs.setReference}
value={searchQuery}
onChange={(evt) => setSearchQuery(evt.target.value)}
{...getReferenceProps()} {...getReferenceProps()}
/> />
</div> </div>
@ -51,7 +77,7 @@ export default function SearchBar() {
style={{ ...floatingStyles }} style={{ ...floatingStyles }}
{...getFloatingProps()} {...getFloatingProps()}
> >
<SearchMenu /> <SearchMenu results={searchResults} />
</div> </div>
</FloatingOverlay> </FloatingOverlay>
</FloatingPortal> </FloatingPortal>
@ -60,6 +86,28 @@ export default function SearchBar() {
); );
} }
function SearchMenu() { function SearchMenu({ results }) {
return <>Search suggestions...</>; 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>
);
} }