feat: add setting to toggle alphabetical grouping in contacts list

This commit is contained in:
Linus Rath
2026-04-21 23:22:18 +02:00
parent 7d6a3c8c76
commit 76f6149841
4 changed files with 67 additions and 37 deletions
+16 -8
View File
@@ -137,6 +137,7 @@ export function ContactList({
const t = useTranslations("contacts");
const locale = useLocale();
const density = useSettingsStore((state) => state.density);
const groupByLetter = useSettingsStore((state) => state.groupContactsByLetter);
const { contextMenu, openContextMenu, closeContextMenu, menuRef } = useContextMenu<ContactCard>();
const [filtersOpen, setFiltersOpen] = useState(false);
const [filters, setFilters] = useState<ListFilters>(EMPTY_FILTERS);
@@ -528,13 +529,8 @@ export function ContactList({
)}
</div>
) : (
<div>
{groupedSections.map(({ letter, items }) => (
<section key={letter}>
<div className="sticky top-0 z-10 px-4 py-0.5 bg-background/90 backdrop-blur-sm text-[11px] font-medium text-muted-foreground/70 uppercase tracking-wide">
{letter}
</div>
{items.map((contact) => (
(() => {
const renderItem = (contact: ContactCard) => (
<ContactListItem
key={contact.id}
contact={contact}
@@ -561,10 +557,22 @@ export function ContactList({
}}
onContextMenu={(e, c) => openContextMenu(e, c)}
/>
))}
);
return groupByLetter ? (
<div>
{groupedSections.map(({ letter, items }) => (
<section key={letter}>
<div className="sticky top-0 z-10 px-4 py-0.5 bg-background/90 backdrop-blur-sm text-[11px] font-medium text-muted-foreground/70 uppercase tracking-wide">
{letter}
</div>
{items.map(renderItem)}
</section>
))}
</div>
) : (
<div>{sorted.map(renderItem)}</div>
);
})()
)}
</div>
+14 -1
View File
@@ -4,11 +4,12 @@ import { useState, useCallback } from "react";
import { useTranslations } from "next-intl";
import { Upload, Download } from "lucide-react";
import { Button } from "@/components/ui/button";
import { SettingsSection, SettingItem } from "./settings-section";
import { SettingsSection, SettingItem, ToggleSwitch } from "./settings-section";
import { ContactImportDialog } from "@/components/contacts/contact-import-dialog";
import { exportContacts } from "@/components/contacts/contact-export";
import { useContactStore } from "@/stores/contact-store";
import { useAuthStore } from "@/stores/auth-store";
import { useSettingsStore } from "@/stores/settings-store";
import { toast } from "@/stores/toast-store";
export function ContactsSettings() {
@@ -20,6 +21,8 @@ export function ContactsSettings() {
supportsSync,
importContacts,
} = useContactStore();
const groupContactsByLetter = useSettingsStore((s) => s.groupContactsByLetter);
const updateSetting = useSettingsStore((s) => s.updateSetting);
const [showImport, setShowImport] = useState(false);
const individuals = contacts.filter(c => c.kind !== "group");
@@ -55,6 +58,16 @@ export function ContactsSettings() {
title={tSettings("title")}
description={tSettings("description")}
>
<SettingItem
label={tSettings("group_by_letter_label")}
description={tSettings("group_by_letter_description")}
>
<ToggleSwitch
checked={groupContactsByLetter}
onChange={(checked) => updateSetting("groupContactsByLetter", checked)}
/>
</SettingItem>
<SettingItem
label={tSettings("import_label")}
description={tSettings("import_description")}
+2
View File
@@ -1322,6 +1322,8 @@
"contacts": {
"title": "Contacts",
"description": "Import and export your contacts",
"group_by_letter_label": "Group by first letter",
"group_by_letter_description": "Show alphabetical section headers in the contact list",
"import_label": "Import Contacts",
"import_description": "Import contacts from a vCard (.vcf) file",
"export_label": "Export Contacts",
+7
View File
@@ -160,6 +160,9 @@ interface SettingsState {
showBirthdayCalendar: boolean;
birthdayCalendarColor: string;
// Contacts Display
groupContactsByLetter: boolean;
// Email Notifications
emailNotificationsEnabled: boolean;
emailNotificationSound: boolean;
@@ -304,6 +307,9 @@ const DEFAULT_SETTINGS = {
showBirthdayCalendar: false,
birthdayCalendarColor: '#eab308',
// Contacts Display
groupContactsByLetter: true,
// Email Notifications
emailNotificationsEnabled: true,
emailNotificationSound: true,
@@ -459,6 +465,7 @@ export const useSettingsStore = create<SettingsState>()(
showTasksOnCalendar: state.showTasksOnCalendar,
showBirthdayCalendar: state.showBirthdayCalendar,
birthdayCalendarColor: state.birthdayCalendarColor,
groupContactsByLetter: state.groupContactsByLetter,
expandedFilterView: state.expandedFilterView,
showTimeInMonthView: state.showTimeInMonthView,
showWeekNumbers: state.showWeekNumbers,