From 3eb696a92e8e7618a48e19848a64fff418315c54 Mon Sep 17 00:00:00 2001 From: Florent Tapponnier Date: Wed, 24 Jun 2026 15:38:48 +0200 Subject: [PATCH] redesign search trigger as wide input pill (no shortcut badge) - Desktop trigger now looks like a real search field: soft surface, rule border, max-width 440px so it stretches across the header between nav and utilities (CMC-style). - Drop the platform shortcut hint entirely; Cmd+K / Ctrl+K still work but advertising one or the other ships the wrong copy to half the audience. - Header layout: nav links left of search, search in a flex-1 zone, utilities (github + theme) right. The pipe separator was already gone; this commit just gives the search the room it deserves. --- src/components/search/search-trigger.tsx | 38 +++++++++--------------- src/components/site-header.tsx | 26 ++++++++-------- 2 files changed, 26 insertions(+), 38 deletions(-) diff --git a/src/components/search/search-trigger.tsx b/src/components/search/search-trigger.tsx index 02af3dfc..c577f526 100644 --- a/src/components/search/search-trigger.tsx +++ b/src/components/search/search-trigger.tsx @@ -1,21 +1,14 @@ "use client"; import { Search } from "lucide-react"; -import { useSyncExternalStore } from "react"; import { useSearch } from "@/components/search/search-provider"; -const emptySubscribe = () => () => {}; - -function readIsMac(): boolean { - if (typeof navigator === "undefined") return false; - const p = navigator.platform || navigator.userAgent; - return /Mac|iPhone|iPad|iPod/i.test(p); -} - type Props = { /** - * - `desktop`: inline pill-ish button next to "GitHub" / theme toggle - * in the desktop nav. Hidden below md. + * - `desktop`: wide input-style pill shown in the desktop nav. Reads + * visually as a real search field (light surface, rounded, full + * width within its container) so users discover the feature without + * needing the keyboard shortcut. * - `mobile`: 44×44 icon-only square sized to the same min-tap target * as the hamburger. Hidden at md+. */ @@ -24,11 +17,6 @@ type Props = { export function SearchTrigger({ variant }: Props) { const { open } = useSearch(); - // Read once on the client. SSR snapshot is `false` so we render the - // Ctrl variant; the client snapshot replaces it on hydration if the - // platform actually is macOS. Avoids the set-state-in-effect lint - // and stays consistent with how ThemeToggle reads the DOM. - const isMac = useSyncExternalStore(emptySubscribe, readIsMac, () => false); if (variant === "mobile") { return ( @@ -36,26 +24,28 @@ export function SearchTrigger({ variant }: Props) { type="button" onClick={open} aria-label="Open search" - className="md:hidden inline-flex items-center justify-center min-h-[44px] min-w-[44px] rounded text-ink-muted hover:text-ink transition-colors" + className="md:hidden inline-flex items-center justify-center min-h-[44px] min-w-[44px] rounded-md text-ink-muted hover:text-ink transition-colors" > ); } - const shortcut = isMac ? "⌘K" : "Ctrl K"; + // Input-look trigger. Soft surface + rule border so the affordance + // reads as a text field even though it actually opens the cmdk modal. + // No platform-specific shortcut hint: ⌘K is wrong on Windows/Linux, + // Ctrl K is wrong on Mac, and a dynamic swap creates hydration + // flicker for two-character gain. Shortcut still works, just not + // advertised in the chrome. return ( ); } diff --git a/src/components/site-header.tsx b/src/components/site-header.tsx index 653f9434..8d414265 100644 --- a/src/components/site-header.tsx +++ b/src/components/site-header.tsx @@ -59,12 +59,6 @@ export function SiteHeader() { return () => mql.removeEventListener("change", onChange); }, [open]); - // Close the mobile menu on route change so a tap on a nav item collapses - // the drawer without the consumer having to wire onClick on every link. - useEffect(() => { - setOpen(false); - }, [pathname]); - return (
-
-
+
+
- {/* Center nav - CMC-style: underline under the active section. + {/* Nav links - CMC-style: underline under the active section. Items keep a constant pb to avoid layout shift between active / inactive states. */} -