feat: add keyboard navigation
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import Link from "next/link";
|
import { useRouter } from "next/router";
|
||||||
import {
|
import {
|
||||||
Combobox,
|
Combobox,
|
||||||
ComboboxInput,
|
ComboboxInput,
|
||||||
@@ -43,6 +43,7 @@ export default function CommandPallette({
|
|||||||
}) {
|
}) {
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
const { workspace } = useWorkspace();
|
const { workspace } = useWorkspace();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
// Debounce to avoid too many reqs
|
// Debounce to avoid too many reqs
|
||||||
const [debouncedQuery] = useDebounce(query, 300);
|
const [debouncedQuery] = useDebounce(query, 300);
|
||||||
@@ -99,6 +100,21 @@ export default function CommandPallette({
|
|||||||
placeholder="Search boards and cards..."
|
placeholder="Search boards and cards..."
|
||||||
value={query}
|
value={query}
|
||||||
onChange={(event) => setQuery(event.target.value)}
|
onChange={(event) => setQuery(event.target.value)}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
if (event.key === "Enter" && results.length > 0) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
// Find the active option or fallback to first option
|
||||||
|
const targetOption =
|
||||||
|
document.querySelector(
|
||||||
|
'[data-headlessui-state*="active"][role="option"]',
|
||||||
|
) ?? document.querySelector('[role="option"]');
|
||||||
|
|
||||||
|
if (targetOption) {
|
||||||
|
(targetOption as HTMLElement).click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<HiMagnifyingGlass
|
<HiMagnifyingGlass
|
||||||
className="pointer-events-none col-start-1 row-start-1 ml-4 size-5 self-center text-light-700 dark:text-dark-700"
|
className="pointer-events-none col-start-1 row-start-1 ml-4 size-5 self-center text-light-700 dark:text-dark-700"
|
||||||
@@ -113,20 +129,20 @@ export default function CommandPallette({
|
|||||||
isPlaceholderData ? "opacity-75" : ""
|
isPlaceholderData ? "opacity-75" : ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{results.map((result) => (
|
{results.map((result) => {
|
||||||
<ComboboxOption
|
const url =
|
||||||
key={`${result.type}-${result.publicId}`}
|
result.type === "board"
|
||||||
value={result}
|
? `/boards/${result.publicId}`
|
||||||
className="group"
|
: `/cards/${result.publicId}`;
|
||||||
>
|
|
||||||
<Link
|
return (
|
||||||
href={
|
<ComboboxOption
|
||||||
result.type === "board"
|
key={`${result.type}-${result.publicId}`}
|
||||||
? `/boards/${result.publicId}`
|
value={result}
|
||||||
: `/cards/${result.publicId}`
|
className="cursor-pointer select-none px-4 py-3 data-[focus]:bg-light-200 hover:bg-light-200 focus:outline-none dark:data-[focus]:bg-dark-200 dark:hover:bg-dark-200"
|
||||||
}
|
|
||||||
className="block cursor-pointer select-none px-4 py-3 data-[focus]:bg-light-200 hover:bg-light-200 focus:outline-none dark:data-[focus]:bg-dark-200 dark:hover:bg-dark-200"
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
console.log("clicked", url);
|
||||||
|
void router.push(url);
|
||||||
onClose();
|
onClose();
|
||||||
setQuery("");
|
setQuery("");
|
||||||
}}
|
}}
|
||||||
@@ -143,9 +159,9 @@ export default function CommandPallette({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</ComboboxOption>
|
||||||
</ComboboxOption>
|
);
|
||||||
))}
|
})}
|
||||||
</ComboboxOptions>
|
</ComboboxOptions>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user