fix: add desktop search dropdown
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { Info, Search as SearchIcon, X } from "lucide-react";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useEffect, useMemo, useRef, useState, type Ref } from "react";
|
||||
import { getJSON, itemsOrEmpty, readJSONCache } from "../api";
|
||||
import { langQuery, type Lang } from "../i18n";
|
||||
import type { Post, PostListResponse } from "../types/post";
|
||||
@@ -16,6 +16,9 @@ type SearchPanelProps = {
|
||||
query: string;
|
||||
onQueryChange: (value: string) => void;
|
||||
onSearch: () => void;
|
||||
variant?: "mobile" | "desktop";
|
||||
showInput?: boolean;
|
||||
panelRef?: Ref<HTMLDivElement>;
|
||||
};
|
||||
|
||||
const TAG_SOURCE_LIMIT = 80;
|
||||
@@ -59,6 +62,9 @@ export function SearchPanel({
|
||||
query,
|
||||
onQueryChange,
|
||||
onSearch,
|
||||
variant = "mobile",
|
||||
showInput = true,
|
||||
panelRef,
|
||||
}: SearchPanelProps) {
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const [tags, setTags] = useState<TagItem[]>([]);
|
||||
@@ -70,12 +76,13 @@ export function SearchPanel({
|
||||
const langParam = useMemo(() => langQuery(lang), [lang]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!showInput) return;
|
||||
// Avoid scroll-into-view: browsers default-scroll the focused element
|
||||
// into the viewport, which moves the underlying page when the search
|
||||
// overlay opens from a scrolled position. `preventScroll` keeps the page
|
||||
// exactly where it was.
|
||||
inputRef.current?.focus({ preventScroll: true });
|
||||
}, []);
|
||||
}, [showInput]);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
@@ -143,44 +150,62 @@ export function SearchPanel({
|
||||
.finally(() => setIsPostLoading(false));
|
||||
};
|
||||
|
||||
const panelClassName =
|
||||
variant === "desktop"
|
||||
? "ark-header-menu-enter fixed left-1/2 top-[72px] z-50 max-h-[min(70dvh,640px)] w-[min(720px,calc(100vw-3rem))] -translate-x-1/2 overflow-y-auto overscroll-contain rounded-3xl border border-white/10 bg-[#0f0f13] shadow-2xl shadow-black/60"
|
||||
: "ark-header-menu-enter fixed inset-x-0 bottom-0 top-[64px] z-50 overflow-y-auto overscroll-contain bg-[#0f0f13] md:hidden";
|
||||
const innerClassName =
|
||||
variant === "desktop"
|
||||
? "px-5 pb-6 pt-4"
|
||||
: "border-t border-white/10 px-5 pb-6 pt-3 max-[360px]:px-3";
|
||||
|
||||
return (
|
||||
<div className="ark-header-menu-enter fixed inset-x-0 bottom-0 top-[64px] z-50 overflow-y-auto overscroll-contain bg-[#0f0f13] md:hidden">
|
||||
<div className="border-t border-white/10 px-5 pb-6 pt-3 max-[360px]:px-3">
|
||||
<div className="flex h-12 items-center gap-2">
|
||||
<div className="flex h-11 min-w-0 flex-1 items-center gap-2 rounded-full bg-[#191921] px-3 shadow-[0_0_0_2px_rgba(245,180,53,0.12)] ring-1 ring-inset ring-ark-gold">
|
||||
<SearchIcon size={18} className="shrink-0 text-ark-gold" />
|
||||
<input
|
||||
ref={inputRef}
|
||||
value={query}
|
||||
onChange={(e) => onQueryChange(e.target.value)}
|
||||
onKeyDown={(e) => e.key === "Enter" && onSearch()}
|
||||
placeholder={t("searchPanelPlaceholder")}
|
||||
className="min-w-0 flex-1 bg-transparent text-base text-neutral-100 outline-none placeholder:text-[#777985]"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onQueryChange("")}
|
||||
className="shrink-0 rounded-full p-1 text-neutral-500 hover:bg-white/5 hover:text-neutral-200"
|
||||
aria-label={t("clear")}
|
||||
>
|
||||
<X size={18} />
|
||||
</button>
|
||||
<div ref={panelRef} className={panelClassName}>
|
||||
<div className={innerClassName}>
|
||||
{showInput ? (
|
||||
<>
|
||||
<div className="flex h-12 items-center gap-2">
|
||||
<div className="flex h-11 min-w-0 flex-1 items-center gap-2 rounded-full bg-[#191921] px-3 shadow-[0_0_0_2px_rgba(245,180,53,0.12)] ring-1 ring-inset ring-ark-gold">
|
||||
<SearchIcon size={18} className="shrink-0 text-ark-gold" />
|
||||
<input
|
||||
ref={inputRef}
|
||||
value={query}
|
||||
onChange={(e) => onQueryChange(e.target.value)}
|
||||
onKeyDown={(e) => e.key === "Enter" && onSearch()}
|
||||
placeholder={t("searchPanelPlaceholder")}
|
||||
className="min-w-0 flex-1 bg-transparent text-base text-neutral-100 outline-none placeholder:text-[#777985]"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onQueryChange("")}
|
||||
className="shrink-0 rounded-full p-1 text-neutral-500 hover:bg-white/5 hover:text-neutral-200"
|
||||
aria-label={t("clear")}
|
||||
>
|
||||
<X size={18} />
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onSearch}
|
||||
className="h-10 shrink-0 rounded-full bg-ark-gold px-3 text-sm font-bold text-[#111114] transition hover:bg-ark-gold2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/70"
|
||||
>
|
||||
{t("searchSubmit")}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="mt-1 flex items-center gap-1.5 pl-3 text-[12px] leading-4 text-[#777985]">
|
||||
<Info size={14} className="shrink-0" />
|
||||
<span>{t("searchPanelHint")}</span>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="mb-4 flex items-center gap-1.5 pl-1 text-[12px] leading-4 text-[#777985]">
|
||||
<Info size={14} className="shrink-0" />
|
||||
<span>{t("searchPanelHint")}</span>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onSearch}
|
||||
className="h-10 shrink-0 rounded-full bg-ark-gold px-3 text-sm font-bold text-[#111114] transition hover:bg-ark-gold2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/70"
|
||||
>
|
||||
{t("searchSubmit")}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="mt-1 flex items-center gap-1.5 pl-3 text-[12px] leading-4 text-[#777985]">
|
||||
<Info size={14} className="shrink-0" />
|
||||
<span>{t("searchPanelHint")}</span>
|
||||
</div>
|
||||
|
||||
<section className="mt-5">
|
||||
<section className={showInput ? "mt-5" : "mt-0"}>
|
||||
<div className="mb-3 flex items-center justify-between">
|
||||
<h2 className="border-l-4 border-ark-gold pl-3 text-base font-bold text-neutral-100">
|
||||
{t("currentTags")}
|
||||
|
||||
Reference in New Issue
Block a user