feat: match the search tab chrome to the mail page sidebar #641

This commit is contained in:
Linus Rath
2026-09-01 21:30:16 +02:00
parent 1d8e4b9d8a
commit a9cd4ced60
29 changed files with 88 additions and 44 deletions
+30 -13
View File
@@ -18,19 +18,38 @@ export interface SearchFacetsProps {
onFlatChange: (flat: boolean) => void;
}
/** Section title, styled like the mail sidebar's section rows. */
function FacetSection({ title, first, children }: { title: string; first?: boolean; children: React.ReactNode }) {
return (
<section>
<div className={cn("px-3 pb-1", first ? "pt-3" : "pt-5")}>
<span className="text-xs font-semibold text-muted-foreground truncate">{title}</span>
</div>
{children}
</section>
);
}
/** One facet row, styled like a mail sidebar folder row (start-border selection marker). */
function FacetButton({ active, label, count, onClick }: { active: boolean; label: string; count?: string; onClick: () => void }) {
return (
<button
type="button"
onClick={onClick}
aria-pressed={active}
style={{ paddingBlock: 'var(--density-sidebar-py)' }}
className={cn(
"w-full flex items-center justify-between gap-2 px-2 py-1 rounded-md text-sm text-left cursor-pointer",
active ? "bg-primary/10 text-primary font-medium" : "text-muted-foreground hover:bg-muted hover:text-foreground",
"w-full flex items-center gap-2 ps-3 pe-2 text-sm text-left transition-colors duration-150 cursor-pointer",
"max-lg:min-h-[44px] border-s-2",
active
? "bg-accent text-accent-foreground font-semibold border-primary"
: "hover:bg-muted/50 text-foreground border-transparent",
)}
>
<span className="truncate">{label}</span>
{count !== undefined && <span className="shrink-0 text-xs tabular-nums">{count}</span>}
<span className="flex-1 truncate">{label}</span>
{count !== undefined && (
<span className={cn("shrink-0 text-xs tabular-nums", active ? "font-semibold text-accent-foreground" : "text-muted-foreground")}>{count}</span>
)}
</button>
);
}
@@ -45,9 +64,8 @@ export function SearchFacets({
const total = SEARCH_KINDS.reduce((sum, kind) => sum + kindCounts[kind], 0);
const anyMore = SEARCH_KINDS.some((kind) => kindHasMore[kind]);
return (
<div className="flex flex-col gap-4 p-3 overflow-y-auto">
<section>
<h3 className="px-2 pb-1 text-xs font-medium text-muted-foreground uppercase tracking-wide">{t('scope_label')}</h3>
<div className="flex flex-col pb-3 overflow-y-auto">
<FacetSection title={t('scope_label')} first>
<FacetButton
active={scope === 'all'}
label={t('scope_all')}
@@ -63,11 +81,10 @@ export function SearchFacets({
onClick={() => onScopeChange(kind)}
/>
))}
</section>
</FacetSection>
{accounts.length > 1 && (
<section>
<h3 className="px-2 pb-1 text-xs font-medium text-muted-foreground uppercase tracking-wide">{t('account_label')}</h3>
<FacetSection title={t('account_label')}>
<FacetButton active={accountId === null} label={t('all_accounts')} onClick={() => onAccountChange(null)} />
{accounts.map((account) => (
<FacetButton
@@ -78,13 +95,13 @@ export function SearchFacets({
onClick={() => onAccountChange(account.localAccountId)}
/>
))}
</section>
</FacetSection>
)}
<section>
<FacetSection title={t('view_label')}>
<FacetButton active={!flat} label={t('grouped')} onClick={() => onFlatChange(false)} />
<FacetButton active={flat} label={t('flat_by_date')} onClick={() => onFlatChange(true)} />
</section>
</FacetSection>
</div>
);
}
+4 -4
View File
@@ -90,8 +90,8 @@ export function SearchTabBody({ tabId, data }: SearchTabBodyProps) {
const handleOpen = (hit: GlobalSearchHit) => { void openHit(hit, { proShell: true }); };
return (
<div className="flex h-full min-h-0 w-full">
<aside className="w-48 shrink-0 border-r border-border overflow-y-auto">
<div className="flex h-full min-h-0 w-full bg-background">
<aside className="w-56 shrink-0 bg-secondary border-e border-border overflow-y-auto">
<SearchFacets
scope={data.scope}
onScopeChange={setScope}
@@ -105,8 +105,8 @@ export function SearchTabBody({ tabId, data }: SearchTabBodyProps) {
/>
</aside>
<section className="flex-1 min-w-0 flex flex-col border-r border-border">
<div className="flex items-center gap-2 px-3 py-2 border-b border-border">
<section className="flex-1 lg:flex-none lg:w-96 min-w-0 flex flex-col border-e border-border">
<div className="flex h-10 flex-shrink-0 items-center gap-2 border-b border-border px-3">
<Search className="w-4 h-4 shrink-0 text-muted-foreground" />
<input
type="text"
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "مجمّع",
"load_more": "تحميل المزيد",
"preview_empty": "اختر نتيجة لمعاينتها",
"open_full": "فتح"
"open_full": "فتح",
"view_label": "العرض"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Agrupat",
"load_more": "Carrega'n més",
"preview_empty": "Seleccioneu un resultat per previsualitzar-lo",
"open_full": "Obre"
"open_full": "Obre",
"view_label": "Vista"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Seskupené",
"load_more": "Načíst další",
"preview_empty": "Vyberte výsledek pro náhled",
"open_full": "Otevřít"
"open_full": "Otevřít",
"view_label": "Zobrazení"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Grupperet",
"load_more": "Indlæs flere",
"preview_empty": "Vælg et resultat for at se det",
"open_full": "Åbn"
"open_full": "Åbn",
"view_label": "Visning"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Gruppiert",
"load_more": "Mehr laden",
"preview_empty": "Ergebnis auswählen, um es anzuzeigen",
"open_full": "Öffnen"
"open_full": "Öffnen",
"view_label": "Ansicht"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Grouped",
"load_more": "Load more",
"preview_empty": "Select a result to preview it",
"open_full": "Open"
"open_full": "Open",
"view_label": "View"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Agrupado",
"load_more": "Cargar más",
"preview_empty": "Selecciona un resultado para previsualizarlo",
"open_full": "Abrir"
"open_full": "Abrir",
"view_label": "Vista"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "گروه‌بندی‌شده",
"load_more": "بارگذاری بیشتر",
"preview_empty": "برای پیش‌نمایش یک نتیجه انتخاب کنید",
"open_full": "باز کردن"
"open_full": "باز کردن",
"view_label": "نما"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Groupé",
"load_more": "Charger plus",
"preview_empty": "Sélectionnez un résultat pour l'aperçu",
"open_full": "Ouvrir"
"open_full": "Ouvrir",
"view_label": "Affichage"
}
}
+2 -1
View File
@@ -3583,6 +3583,7 @@
"grouped": "מקובץ",
"load_more": "טען עוד",
"preview_empty": "בחרו תוצאה לתצוגה מקדימה",
"open_full": "פתיחה"
"open_full": "פתיחה",
"view_label": "תצוגה"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Csoportosított",
"load_more": "Továbbiak betöltése",
"preview_empty": "Válasszon egy találatot az előnézethez",
"open_full": "Megnyitás"
"open_full": "Megnyitás",
"view_label": "Nézet"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Raggruppato",
"load_more": "Carica altri",
"preview_empty": "Seleziona un risultato per l'anteprima",
"open_full": "Apri"
"open_full": "Apri",
"view_label": "Vista"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "グループ表示",
"load_more": "さらに読み込む",
"preview_empty": "プレビューする結果を選択してください",
"open_full": "開く"
"open_full": "開く",
"view_label": "表示"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "그룹 보기",
"load_more": "더 불러오기",
"preview_empty": "미리 볼 결과를 선택하세요",
"open_full": "열기"
"open_full": "열기",
"view_label": "보기"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Grupēts",
"load_more": "Ielādēt vairāk",
"preview_empty": "Izvēlieties rezultātu, lai to priekšskatītu",
"open_full": "Atvērt"
"open_full": "Atvērt",
"view_label": "Skats"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Бүлэглэсэн",
"load_more": "Цааш ачаалах",
"preview_empty": "Урьдчилан харах үр дүнгээ сонгоно уу",
"open_full": "Нээх"
"open_full": "Нээх",
"view_label": "Харагдац"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Gruppert",
"load_more": "Last inn flere",
"preview_empty": "Velg et resultat for å forhåndsvise det",
"open_full": "Åpne"
"open_full": "Åpne",
"view_label": "Visning"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Gegroepeerd",
"load_more": "Meer laden",
"preview_empty": "Selecteer een resultaat voor een voorbeeld",
"open_full": "Openen"
"open_full": "Openen",
"view_label": "Weergave"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Pogrupowane",
"load_more": "Wczytaj więcej",
"preview_empty": "Wybierz wynik, aby zobaczyć podgląd",
"open_full": "Otwórz"
"open_full": "Otwórz",
"view_label": "Widok"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Agrupado",
"load_more": "Carregar mais",
"preview_empty": "Selecione um resultado para pré-visualizar",
"open_full": "Abrir"
"open_full": "Abrir",
"view_label": "Vista"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Grupat",
"load_more": "Încarcă mai multe",
"preview_empty": "Selectează un rezultat pentru previzualizare",
"open_full": "Deschide"
"open_full": "Deschide",
"view_label": "Vizualizare"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "По группам",
"load_more": "Загрузить ещё",
"preview_empty": "Выберите результат для предпросмотра",
"open_full": "Открыть"
"open_full": "Открыть",
"view_label": "Вид"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Zoskupené",
"load_more": "Načítať ďalšie",
"preview_empty": "Vyberte výsledok pre náhľad",
"open_full": "Otvoriť"
"open_full": "Otvoriť",
"view_label": "Zobrazenie"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "Gruplandırılmış",
"load_more": "Daha fazla yükle",
"preview_empty": "Önizlemek için bir sonuç seçin",
"open_full": "Aç"
"open_full": "Aç",
"view_label": "Görünüm"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "За групами",
"load_more": "Завантажити ще",
"preview_empty": "Виберіть результат для перегляду",
"open_full": "Відкрити"
"open_full": "Відкрити",
"view_label": "Вигляд"
}
}
+2 -1
View File
@@ -3577,6 +3577,7 @@
"grouped": "分組",
"load_more": "載入更多",
"preview_empty": "選擇結果以預覽",
"open_full": "開啟"
"open_full": "開啟",
"view_label": "檢視"
}
}
+2 -1
View File
@@ -3582,6 +3582,7 @@
"grouped": "分组",
"load_more": "加载更多",
"preview_empty": "选择一个结果以预览",
"open_full": "打开"
"open_full": "打开",
"view_label": "视图"
}
}