feat(quick-260411-0zq): convert TopNav search button to real input with navigation
- Replace fake button with real text input and search icon - Navigate to /global-items?q=query on Enter or icon click - Clear input after navigation - Remove openCatalogSearch usage from TopNav (FAB/BottomTabBar flows unchanged)
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { Link, useMatchRoute } from "@tanstack/react-router";
|
import { Link, useMatchRoute, useNavigate } from "@tanstack/react-router";
|
||||||
|
import { useState } from "react";
|
||||||
import { useAuth } from "../hooks/useAuth";
|
import { useAuth } from "../hooks/useAuth";
|
||||||
import { LucideIcon } from "../lib/iconData";
|
import { LucideIcon } from "../lib/iconData";
|
||||||
import { useUIStore } from "../stores/uiStore";
|
import { useUIStore } from "../stores/uiStore";
|
||||||
@@ -43,14 +44,22 @@ function NavLinkOrButton({
|
|||||||
export function TopNav() {
|
export function TopNav() {
|
||||||
const { data: auth } = useAuth();
|
const { data: auth } = useAuth();
|
||||||
const isAuthenticated = !!auth?.user;
|
const isAuthenticated = !!auth?.user;
|
||||||
const openCatalogSearch = useUIStore((s) => s.openCatalogSearch);
|
|
||||||
const openAuthPrompt = useUIStore((s) => s.openAuthPrompt);
|
const openAuthPrompt = useUIStore((s) => s.openAuthPrompt);
|
||||||
const matchRoute = useMatchRoute();
|
const matchRoute = useMatchRoute();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [searchQuery, setSearchQuery] = useState("");
|
||||||
|
|
||||||
const isHome = !!matchRoute({ to: "/" });
|
const isHome = !!matchRoute({ to: "/" });
|
||||||
const isCollection = !!matchRoute({ to: "/collection", fuzzy: true });
|
const isCollection = !!matchRoute({ to: "/collection", fuzzy: true });
|
||||||
const isSetups = !!matchRoute({ to: "/setups", fuzzy: true });
|
const isSetups = !!matchRoute({ to: "/setups", fuzzy: true });
|
||||||
|
|
||||||
|
function handleSearch() {
|
||||||
|
const trimmed = searchQuery.trim();
|
||||||
|
if (!trimmed) return;
|
||||||
|
navigate({ to: "/global-items", search: { q: trimmed } });
|
||||||
|
setSearchQuery("");
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="sticky top-0 z-10 bg-white border-b border-gray-100">
|
<div className="sticky top-0 z-10 bg-white border-b border-gray-100">
|
||||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||||
@@ -98,17 +107,27 @@ export function TopNav() {
|
|||||||
{/* Right: Search bar (desktop only) + User section */}
|
{/* Right: Search bar (desktop only) + User section */}
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
{/* Search bar — desktop only */}
|
{/* Search bar — desktop only */}
|
||||||
|
<div className="relative hidden md:flex items-center">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => openCatalogSearch("collection")}
|
onClick={handleSearch}
|
||||||
onKeyDown={(e) => {
|
className="absolute left-2.5 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors"
|
||||||
if (e.key === "Enter") openCatalogSearch("collection");
|
tabIndex={-1}
|
||||||
}}
|
aria-label="Search"
|
||||||
className="hidden md:flex items-center gap-2 bg-gray-50 border border-gray-200 rounded-lg px-3 py-1.5 text-sm text-gray-400 cursor-pointer hover:border-gray-300 transition-colors"
|
|
||||||
>
|
>
|
||||||
<LucideIcon name="search" size={16} />
|
<LucideIcon name="search" size={16} />
|
||||||
<span className="hidden lg:inline">Search catalog...</span>
|
|
||||||
</button>
|
</button>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={searchQuery}
|
||||||
|
onChange={(e) => setSearchQuery(e.target.value)}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === "Enter") handleSearch();
|
||||||
|
}}
|
||||||
|
placeholder="Search catalog..."
|
||||||
|
className="bg-gray-50 border border-gray-200 rounded-lg pl-9 pr-3 py-2 text-sm text-gray-900 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-gray-200 focus:border-gray-300 w-48 lg:w-64 transition-colors"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* User section */}
|
{/* User section */}
|
||||||
{isAuthenticated ? (
|
{isAuthenticated ? (
|
||||||
|
|||||||
Reference in New Issue
Block a user