diff --git a/src/components/sticky.tsx b/src/components/sticky.tsx deleted file mode 100644 index a8dae9d..0000000 --- a/src/components/sticky.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { createSignal, JSX, onCleanup, onMount } from "solid-js"; - -export const StickyOverlay = (props: { children?: JSX.Element }) => { - const [filterStuck, setFilterStuck] = createSignal(false); - - return ( - <> -
{ - onMount(() => { - const observer = new IntersectionObserver( - ([entry]) => setFilterStuck(!entry.isIntersecting), - { - rootMargin: "-8px 0px 0px 0px", - threshold: 0, - }, - ); - - observer.observe(trigger); - - onCleanup(() => { - observer.unobserve(trigger); - observer.disconnect(); - }); - }); - }} - class="pointer-events-none h-0" - aria-hidden="true" - /> - -
- {props.children} -
- - ); -}; diff --git a/src/utils/keyboard.ts b/src/utils/keyboard.ts new file mode 100644 index 0000000..16d0bca --- /dev/null +++ b/src/utils/keyboard.ts @@ -0,0 +1,16 @@ +import { onCleanup } from "solid-js"; + +export const useFilterShortcut = (getRef: () => HTMLInputElement | undefined) => { + const handleKeyDown = (e: KeyboardEvent) => { + if ( + e.key === "/" && + !["INPUT", "TEXTAREA"].includes((e.target as HTMLElement)?.tagName) && + !document.querySelector("[data-modal]") + ) { + e.preventDefault(); + getRef()?.focus(); + } + }; + document.addEventListener("keydown", handleKeyDown); + onCleanup(() => document.removeEventListener("keydown", handleKeyDown)); +}; diff --git a/src/views/collection.tsx b/src/views/collection.tsx index 2df0e08..ab5599f 100644 --- a/src/views/collection.tsx +++ b/src/views/collection.tsx @@ -4,7 +4,7 @@ import { $type, ActorIdentifier, InferXRPCBodyOutput } from "@atcute/lexicons"; import * as TID from "@atcute/tid"; import { Title } from "@solidjs/meta"; import { A, useBeforeLeave, useParams, useSearchParams } from "@solidjs/router"; -import { createMemo, createResource, createSignal, For, onCleanup, onMount, Show } from "solid-js"; +import { createMemo, createResource, createSignal, For, onMount, Show } from "solid-js"; import { createStore } from "solid-js/store"; import { agent } from "../auth/state"; import { Button } from "../components/button.jsx"; @@ -17,6 +17,7 @@ import Tooltip from "../components/tooltip.jsx"; import { canHover } from "../layout.jsx"; import { resolvePDS } from "../utils/api.js"; import { localDateFromTimestamp } from "../utils/date.js"; +import { useFilterShortcut } from "../utils/keyboard.js"; import { clearCollectionCache, getCollectionCache, @@ -104,18 +105,7 @@ const CollectionView = () => { }); } - const handleKeyDown = (e: KeyboardEvent) => { - if ( - e.key === "/" && - !["INPUT", "TEXTAREA"].includes((e.target as HTMLElement)?.tagName) && - !document.querySelector("[data-modal]") - ) { - e.preventDefault(); - filterInputRef?.focus(); - } - }; - document.addEventListener("keydown", handleKeyDown); - onCleanup(() => document.removeEventListener("keydown", handleKeyDown)); + useFilterShortcut(() => filterInputRef); }); useBeforeLeave((e) => { diff --git a/src/views/labels.tsx b/src/views/labels.tsx index da96acb..1d6d2e9 100644 --- a/src/views/labels.tsx +++ b/src/views/labels.tsx @@ -8,10 +8,11 @@ import { createMemo, createSignal, For, onMount, Show } from "solid-js"; import { Button } from "../components/button.jsx"; import DidHoverCard from "../components/hover-card/did.jsx"; import RecordHoverCard from "../components/hover-card/record.jsx"; -import { StickyOverlay } from "../components/sticky.jsx"; import { TextInput } from "../components/text-input.jsx"; +import { canHover } from "../layout.jsx"; import { labelerCache, resolveHandle, resolvePDS } from "../utils/api.js"; import { localDateFromTimestamp } from "../utils/date.js"; +import { useFilterShortcut } from "../utils/keyboard.js"; const LABELS_PER_PAGE = 50; const DEFAULT_LABELER_DID = "did:plc:ar7c4by46qjdydhdevvrndac"; @@ -67,6 +68,7 @@ export const LabelView = () => { let rpc: Client | undefined; let formRef!: HTMLFormElement; + let filterInputRef: HTMLInputElement | undefined; const filteredLabels = createMemo(() => { const filterValue = filter().trim(); @@ -116,6 +118,8 @@ export const LabelView = () => { const hasSearched = createMemo(() => Boolean(searchParams.uriPatterns)); onMount(async () => { + useFilterShortcut(() => filterInputRef); + if (searchParams.did && searchParams.uriPatterns) { const formData = new FormData(); formData.append("did", searchParams.did.toString()); @@ -128,7 +132,7 @@ export const LabelView = () => { let did = formData.get("did")?.toString()?.trim() || DEFAULT_LABELER_DID; const uriPatterns = formData.get("uriPatterns")?.toString()?.trim(); - if (!did || !uriPatterns) { + if (!uriPatterns) { setError("Please provide both DID and URI patterns"); return; } @@ -244,43 +248,7 @@ export const LabelView = () => { - -
- setFilter(e.currentTarget.value)} - class="min-w-0 grow text-sm placeholder:text-xs" - /> -
- 0}> - - {filteredLabels().length}/{labels().length} - - - - - - -
-
-
- -
+
@@ -312,6 +280,65 @@ export const LabelView = () => {
+ +
+
{ + const input = e.currentTarget.querySelector("input"); + if (e.target !== input) input?.focus(); + }} + > + + setFilter(e.currentTarget.value)} + /> + + + / + + +
+ +
+
+ +
+ + {filteredLabels().length} + / + + {labels().length} labels +
+ +
+ + + +
+
+
diff --git a/src/views/repo.tsx b/src/views/repo.tsx index 5445924..6e2c19f 100644 --- a/src/views/repo.tsx +++ b/src/views/repo.tsx @@ -9,7 +9,6 @@ import { createSignal, ErrorBoundary, For, - onCleanup, onMount, Show, Suspense, @@ -42,6 +41,7 @@ import { validateHandle, } from "../utils/api.js"; import { detectDidKeyType, detectKeyType } from "../utils/key.js"; +import { useFilterShortcut } from "../utils/keyboard.js"; import { BlobView } from "./blob.jsx"; import { PlcLogView } from "./logs.jsx"; import { plcDirectory } from "./settings.jsx"; @@ -80,19 +80,7 @@ export const RepoView = () => { }); onMount(() => { - const handleKeyDown = (e: KeyboardEvent) => { - if ( - e.key === "/" && - !["INPUT", "TEXTAREA"].includes((e.target as HTMLElement)?.tagName) && - !document.querySelector("[data-modal]") - ) { - e.preventDefault(); - filterInputRef?.focus(); - } - }; - - document.addEventListener("keydown", handleKeyDown); - onCleanup(() => document.removeEventListener("keydown", handleKeyDown)); + useFilterShortcut(() => filterInputRef); }); const RepoTab = (props: {