+
{t(`scope_${kind}`)}
+
+ {hits.length}
+
{status.status === 'loading' && }
{hits.slice(0, MAX_ROWS_PER_KIND).map((hit) => (
diff --git a/components/global-search/palette-result-row.tsx b/components/global-search/palette-result-row.tsx
index d85b2b61d..04267a484 100644
--- a/components/global-search/palette-result-row.tsx
+++ b/components/global-search/palette-result-row.tsx
@@ -1,19 +1,43 @@
"use client";
-import { BookUser, CalendarDays, FileText, Folder, Mail, Repeat } from "lucide-react";
+import { CalendarDays, FileText, Folder, Repeat } from "lucide-react";
import { useTranslations } from "next-intl";
+import { Avatar } from "@/components/ui/avatar";
import { parseSearchSnippet, type SnippetSegment } from "@/lib/search-snippet";
import type { GlobalSearchHit } from "@/lib/global-search/types";
+import { getContactDisplayName, getContactPhotoUri, getContactPrimaryEmail } from "@/stores/contact-store";
import { cn } from "@/lib/utils";
-function HitIcon({ hit }: { hit: GlobalSearchHit }) {
- const className = "w-4 h-4 shrink-0 text-muted-foreground";
- switch (hit.kind) {
- case 'mail': return
;
- case 'contacts': return
;
- case 'calendar': return
;
- case 'files': return hit.isFolder ?
:
;
+/**
+ * Leading visual, mirroring the mail list's identity language: real avatars
+ * for people (sender / contact), kind-tinted icon chips for events and files.
+ */
+function LeadingVisual({ hit }: { hit: GlobalSearchHit }) {
+ if (hit.kind === 'mail') {
+ const from = hit.email.from?.[0];
+ return
;
}
+ if (hit.kind === 'contacts') {
+ return (
+
+ );
+ }
+ const [Icon, tint] = hit.kind === 'calendar'
+ ? [CalendarDays, "bg-violet-500/15 text-violet-600 dark:text-violet-400"]
+ : hit.isFolder
+ ? [Folder, "bg-amber-500/15 text-amber-600 dark:text-amber-400"]
+ : [FileText, "bg-amber-500/15 text-amber-600 dark:text-amber-400"];
+ return (
+
+
+
+ );
}
function Snippet({ value }: { value: string }) {
@@ -41,8 +65,9 @@ export interface PaletteResultRowProps {
}
/**
- * One palette hit: icon, title, account · context subtitle, date; the server
- * snippet with its `
`ed terms when mail search returned one.
+ * One search hit: avatar/icon, title with the date right-aligned, account ·
+ * context subtitle, and the server snippet with its ``ed terms when
+ * mail search returned one. Used by both the palette and the search tab.
*/
export function PaletteResultRow({ hit, onOpen, className }: PaletteResultRowProps) {
const t = useTranslations('global_search');
@@ -57,29 +82,31 @@ export function PaletteResultRow({ hit, onOpen, className }: PaletteResultRowPro
onClick={() => onOpen(hit)}
data-hit-kind={hit.kind}
className={cn(
- "w-full flex items-start gap-2.5 px-3 py-2 text-left rounded-md",
- "hover:bg-muted focus:bg-muted focus:outline-none",
+ "w-full flex items-start gap-3 px-3 py-2 text-left rounded-md transition-colors duration-150",
+ "hover:bg-muted/50 focus:bg-muted focus:outline-none",
className,
)}
>
-
+
-
-
- {hit.kind === 'mail' && hit.snippet?.subject ? : title}
+
+
+
+ {hit.kind === 'mail' && hit.snippet?.subject ? : title}
+
+ {hit.kind === 'calendar' && hit.isRecurring && (
+
+ )}
- {hit.kind === 'calendar' && hit.isRecurring && (
-
+ {hit.date && (
+ {formatHitDate(hit.date)}
)}
- {subtitle}
+ {subtitle}
{snippet && (
-
+
)}
- {hit.date && (
- {formatHitDate(hit.date)}
- )}
);
}
diff --git a/components/global-search/search-preview.tsx b/components/global-search/search-preview.tsx
index 50fae0f02..9f0ba1169 100644
--- a/components/global-search/search-preview.tsx
+++ b/components/global-search/search-preview.tsx
@@ -1,12 +1,13 @@
"use client";
-import { BookUser, CalendarDays, ExternalLink, FileText, Folder, Repeat } from "lucide-react";
+import { AlignLeft, Building2, CalendarDays, Clock, ExternalLink, FileText, Folder, HardDrive, Mail, MapPin, Phone, Repeat, Users } from "lucide-react";
import { useTranslations } from "next-intl";
+import { Avatar } from "@/components/ui/avatar";
import { ProEmailView } from "@/components/pro/pro-email-tab-body";
import type { CalendarHit, ContactHit, FileHit, GlobalSearchHit } from "@/lib/global-search/types";
-import { getContactDisplayName } from "@/stores/contact-store";
+import { getContactDisplayName, getContactPhotoUri, getContactPrimaryEmail } from "@/stores/contact-store";
import { useAuthStore } from "@/stores/auth-store";
-import { formatFileSize } from "@/lib/utils";
+import { cn, formatFileSize } from "@/lib/utils";
function formatDateTime(iso: string | null): string {
if (!iso) return '';
@@ -20,7 +21,7 @@ function OpenButton({ hit, onOpen, label }: { hit: GlobalSearchHit; onOpen: (hit