feat(search): global conversation search in the topbar with deep-link nav

Topbar search box → debounced crm.search → dropdown of hits (chat/mail, highlighted
snippet). Clicking a hit switches to the right tab and focuses the exact thread:
mail → Inbox, chat → Messenger (via the SDK's new focusThreadId, 0.1.6). Snippet HTML
is escaped except the <em> highlight. Demo mode searches an in-memory set.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-23 14:07:26 +05:30
parent c874a726ef
commit 904d003d32
13 changed files with 1242 additions and 105 deletions
+10 -3
View File
@@ -24,6 +24,13 @@ import "../../app/dashboard/dashboard.css";
export function Dashboard() {
const [theme, setTheme] = useState<"dark" | "light">("dark");
const [active, setActive] = useState("dashboard");
// Deep link from global search: which conversation to focus once we switch tabs.
const [deepLink, setDeepLink] = useState<{ surface: "messenger" | "inbox"; threadId: string } | null>(null);
function navigateToConversation(surface: "messenger" | "inbox", threadId: string) {
setActive(surface);
setDeepLink({ surface, threadId });
}
useEffect(() => {
// Sync the persisted theme from localStorage (an external system) on mount.
@@ -42,15 +49,15 @@ export function Dashboard() {
<div className="dash-root" data-theme={theme}>
<Sidebar active={active} onSelect={setActive} />
<div className="dash-main">
<Topbar theme={theme} onToggle={toggle} title={title} subtitle={subtitle} />
<Topbar theme={theme} onToggle={toggle} title={title} subtitle={subtitle} onNavigate={navigateToConversation} />
<div className="dash-content">
<ToastProvider>
{active === "profile" ? <Profile />
: active === "support" ? <Support />
: active === "rules" ? <Rules />
: active === "ai" ? <AiAssistant />
: active === "messenger" ? <MessengerSdk />
: active === "inbox" ? <InboxSdk />
: active === "messenger" ? <MessengerSdk focusThreadId={deepLink?.surface === "messenger" ? deepLink.threadId : null} />
: active === "inbox" ? <InboxSdk focusThreadId={deepLink?.surface === "inbox" ? deepLink.threadId : null} />
: active === "settings" ? <Settings />
: active === "gallery" ? <SmartGallery theme={theme} />
: active === "team" ? <TeamManagement />