mirror of
https://github.com/infinilabs/coco-app.git
synced 2025-12-16 11:37:47 +01:00
feat: support pageup/pagedown to navigate search results (#920)
* feat: support pageup/pagedown to navigate search results * docs: add release note
This commit is contained in:
@@ -16,6 +16,7 @@ Information about release notes of Coco App is provided here.
|
||||
feat: support switching groups via keyboard shortcuts #911
|
||||
feat: support opening logs from about page #915
|
||||
feat: support moving cursor with home and end keys #918
|
||||
feat: support pageup/pagedown to navigate search results #920
|
||||
|
||||
### 🐛 Bug fix
|
||||
|
||||
|
||||
47
src/components/Common/Scrollbar.tsx
Normal file
47
src/components/Common/Scrollbar.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import { useEventListener } from "ahooks";
|
||||
import clsx from "clsx";
|
||||
import {
|
||||
forwardRef,
|
||||
HTMLAttributes,
|
||||
useImperativeHandle,
|
||||
useRef,
|
||||
} from "react";
|
||||
|
||||
const Scrollbar = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
|
||||
(props, ref) => {
|
||||
const { children, className, ...rest } = props;
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useImperativeHandle(ref, () => containerRef.current as HTMLDivElement);
|
||||
|
||||
useEventListener("keydown", (event) => {
|
||||
const { key } = event;
|
||||
|
||||
if (key !== "PageDown" && key !== "PageUp") return;
|
||||
|
||||
if (!containerRef.current) return;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
const delta = key === "PageDown" ? 1 : -1;
|
||||
const el = containerRef.current;
|
||||
|
||||
el.scrollBy({
|
||||
top: delta * el.clientHeight * 0.9,
|
||||
behavior: "smooth",
|
||||
});
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
{...rest}
|
||||
ref={containerRef}
|
||||
className={clsx("custom-scrollbar", className)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default Scrollbar;
|
||||
@@ -1,6 +1,9 @@
|
||||
import React, { useState, useRef, useEffect, useCallback } from "react";
|
||||
import { useInfiniteScroll } from "ahooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Data } from "ahooks/lib/useInfiniteScroll/types";
|
||||
import { nanoid } from "nanoid";
|
||||
import { isNil } from "lodash-es";
|
||||
|
||||
import { useSearchStore } from "@/stores/searchStore";
|
||||
import { SearchHeader } from "./SearchHeader";
|
||||
@@ -11,9 +14,7 @@ import { Get } from "@/api/axiosRequest";
|
||||
import { useAppStore } from "@/stores/appStore";
|
||||
import { useConnectStore } from "@/stores/connectStore";
|
||||
import SearchEmpty from "../Common/SearchEmpty";
|
||||
import { Data } from "ahooks/lib/useInfiniteScroll/types";
|
||||
import { nanoid } from "nanoid";
|
||||
import { isNil } from "lodash-es";
|
||||
import Scrollbar from "@/components/Common/Scrollbar";
|
||||
|
||||
interface DocumentListProps {
|
||||
onSelectDocument: (id: string) => void;
|
||||
@@ -297,8 +298,8 @@ export const DocumentList: React.FC<DocumentListProps> = ({
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="flex-1 overflow-auto custom-scrollbar pr-0.5"
|
||||
<Scrollbar
|
||||
className="flex-1 overflow-auto pr-0.5"
|
||||
ref={containerRef}
|
||||
>
|
||||
{data?.list && data.list.length > 0 && (
|
||||
@@ -334,7 +335,7 @@ export const DocumentList: React.FC<DocumentListProps> = ({
|
||||
<SearchEmpty />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Scrollbar>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@ import { useKeyboardNavigation } from "@/hooks/useKeyboardNavigation";
|
||||
import { SearchSource } from "./SearchSource";
|
||||
import DropdownListItem from "./DropdownListItem";
|
||||
import platformAdapter from "@/utils/platformAdapter";
|
||||
import Scrollbar from "@/components/Common/Scrollbar";
|
||||
|
||||
type ISearchData = Record<string, QueryHits[]>;
|
||||
|
||||
@@ -149,10 +150,10 @@ function DropdownList({
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
<Scrollbar
|
||||
ref={containerRef}
|
||||
data-tauri-drag-region
|
||||
className="h-full w-full p-2 flex flex-col overflow-y-auto custom-scrollbar focus:outline-none"
|
||||
className="h-full w-full p-2 flex flex-col overflow-y-auto focus:outline-none"
|
||||
tabIndex={0}
|
||||
role="listbox"
|
||||
aria-label={t("search.header.results")}
|
||||
@@ -189,7 +190,7 @@ function DropdownList({
|
||||
})}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Scrollbar>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user