Skip to content

rebuild search dialog CMC-style (recent + featured + trending) - #687

Merged
Flotapponnier merged 1 commit into
devfrom
feat/header-search-bar
Jun 24, 2026
Merged

rebuild search dialog CMC-style (recent + featured + trending)#687
Flotapponnier merged 1 commit into
devfrom
feat/header-search-bar

Conversation

@Flotapponnier

Copy link
Copy Markdown
Collaborator

Summary

Full rebuild of the search dialog modelled on CoinMarketCap's pattern (the user's reference) with Linear's chrome polish (the canonical command-palette ref).

What's new

Idle state (no query) surfaces three sections:

  • Recent chips — horizontal scroll with edge fade, X to remove individually, "Clear" link in the header. Persisted to localStorage (`ocb:search:recent:v1`, cap 7, dedup on id, same-tab sync via custom event).
  • Live leaders cards — horizontal snap-scroll, 6 hand-curated benches. Each card shows the bench title + current drop journal framing #1 provider (with logo) + p50 value in mono accent. Data fetched once from `/api/citable` (already edge-cached 300s) on dialog mount.
  • Trending list — vertical, 6 more curated benches with the same logo + leader + value treatment.

Query state — grouped by kind (Benchmarks / Products / Compare / Alternatives / Answers / Chains / Pages). Every row gets:

  • Leader logo for benches, entity logo for products/chains, kind icon (Lucide) for the rest.
  • Title + tiny kind label + description.
  • ArrowRight that lights up on the selected row.

Polish

  • Linear-style chrome: hairline border (`border-rule-strong/50`), single shadow, no accent focus ring, snappy 150ms open animation (handcrafted CSS keyframes: fade + 4px slide-down; tailwindcss-animate isn't installed).
  • Mobile: full-bleed sheet, kbd footer hidden, X close button instead of esc kbd.
  • Accessibility: dialog/aria-modal/aria-label, focus trap from cmdk, reduced-motion fallback in CSS, kbd hints rendered as real `` tiles.

Files

  • `src/components/search/use-recent-searches.ts` (new) — localStorage hook with useSyncExternalStore + custom-event same-tab sync.
  • `src/components/search/search-dialog.tsx` — full rewrite.
  • `src/app/globals.css` — four CSS keyframes for the open/close transitions.

Test plan

  • Open dialog (Cmd+K) → see Recent (if any) + Live leaders + Trending.
  • Click a result → dialog animates out, route changes, item appears in Recent next time.
  • Type "rpc" → results group by kind; selected row shows ArrowRight.
  • X on a recent chip removes it; "Clear" wipes all.
  • Mobile (375px): full-bleed sheet, no footer, X to close.
  • Reduced motion: open is instant, no fade/slide.

- Linear-inspired chrome: hairline border, single soft shadow, no
  accent ring, snappy 150ms open animation (fade + slide-down 4px).
- New useRecentSearches hook (localStorage, ocb:search:recent:v1
  namespace, cap 7, custom-event same-tab sync, useSyncExternalStore
  for hydration safety).
- Idle state surfaces 3 sections:
  - Recent chips (horizontal scroll with edge fade, X to remove)
  - Live leaders cards (horizontal snap, fetched from /api/citable,
    shows current #1 provider + p50 value with logo)
  - Trending list (vertical, same data shape as featured)
- Search state: results grouped by kind, each row gets the leader's
  logo (benches) or entity logo (products/chains), or a kind-icon
  fallback for compares/answers/alternatives/pages.
- Mobile: full-bleed sheet, kbd footer hidden, X close button.
- /api/citable fetched once on mount; 300s edge cache means usually
  zero network hit. Renders gracefully without it (logo + title only,
  no p50 / leader).
@Flotapponnier
Flotapponnier merged commit ddc37fb into dev Jun 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant