diff --git a/app/globals.css b/app/globals.css
index 4386b06e..59b6d2db 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -3,6 +3,8 @@
@custom-variant dark (&:where(.dark, .dark *));
:root {
+ font-size: var(--font-size-base);
+
--color-border: #e2e8f0;
--color-input: #e2e8f0;
--color-ring: #94a3b8;
@@ -79,7 +81,6 @@ body {
system-ui,
-apple-system,
sans-serif;
- font-size: var(--font-size-base);
font-feature-settings:
"rlig" 1,
"calt" 1;
diff --git a/components/email/email-list-item.tsx b/components/email/email-list-item.tsx
index eadf3f2a..d7ce04a1 100644
--- a/components/email/email-list-item.tsx
+++ b/components/email/email-list-item.tsx
@@ -24,6 +24,7 @@ export function EmailListItem({ email, selected, onClick, onContextMenu }: Email
const t = useTranslations('email_viewer');
const { selectedEmailIds, toggleEmailSelection, selectRangeEmails, selectedMailbox, clearSelection } = useEmailStore();
const showPreview = useSettingsStore((state) => state.showPreview);
+ const density = useSettingsStore((state) => state.density);
const emailKeywords = useSettingsStore((state) => state.emailKeywords);
const { identities } = useAuthStore();
const isChecked = selectedEmailIds.has(email.id);
@@ -116,12 +117,14 @@ export function EmailListItem({ email, selected, onClick, onContextMenu }: Email
)}
{/* Avatar */}
-
state.showPreview);
const estimateSize = useCallback(() => {
- const base = { compact: 60, regular: 84, comfortable: 104 }[density];
- return showPreview ? base + 36 : base;
+ const base = { 'extra-compact': 32, compact: 60, regular: 84, comfortable: 104 }[density];
+ return (showPreview && density !== 'extra-compact') ? base + 36 : base;
}, [density, showPreview]);
const virtualizer = useVirtualizer({
diff --git a/components/email/thread-conversation-view.tsx b/components/email/thread-conversation-view.tsx
index 3ea1867b..11248e0a 100644
--- a/components/email/thread-conversation-view.tsx
+++ b/components/email/thread-conversation-view.tsx
@@ -221,6 +221,7 @@ function EmailCard({
}: EmailCardProps) {
const t = useTranslations();
const resolvedTheme = useThemeStore((state) => state.resolvedTheme);
+ const density = useSettingsStore((state) => state.density);
const sender = email.from?.[0];
const isUnread = !email.keywords?.$seen;
const isStarred = email.keywords?.$flagged;
@@ -428,12 +429,14 @@ function EmailCard({
)}
style={{ gap: 'var(--density-item-gap)', padding: 'var(--density-card-p)' }}
>
-
{email.preview || "No preview available"}
diff --git a/components/email/thread-email-item.tsx b/components/email/thread-email-item.tsx index cce9e20e..0355eb6f 100644 --- a/components/email/thread-email-item.tsx +++ b/components/email/thread-email-item.tsx @@ -7,6 +7,7 @@ import { Avatar } from "@/components/ui/avatar"; import { Paperclip, Star, Circle, CheckSquare, Square } from "lucide-react"; import { useEmailDrag } from "@/hooks/use-email-drag"; import { useEmailStore } from "@/stores/email-store"; +import { useSettingsStore } from "@/stores/settings-store"; interface ThreadEmailItemProps { email: Email; @@ -27,6 +28,7 @@ export function ThreadEmailItem({ const isStarred = email.keywords?.$flagged; const sender = email.from?.[0]; const { selectedMailbox, selectedEmailIds, toggleEmailSelection, selectRangeEmails, clearSelection } = useEmailStore(); + const density = useSettingsStore((state) => state.density); const isChecked = selectedEmailIds.has(email.id); const { dragHandlers, isDragging } = useEmailDrag({ @@ -104,12 +106,14 @@ export function ThreadEmailItem({ )} {/* Small Avatar */} - state.showPreview);
+ const density = useSettingsStore((state) => state.density);
const isMobile = useUIStore((state) => state.isMobile);
const { latestEmail, participantNames, hasUnread, hasStarred, hasAttachment, emailCount } = thread;
@@ -377,12 +381,14 @@ export const ThreadListItem = React.forwardRef = {
+ 'extra-compact': { py: 'py-0.5', gap: 'gap-1.5', showAvatar: false, showPreview: false },
+ compact: { py: 'py-1', gap: 'gap-2', showAvatar: true, showPreview: false },
+ regular: { py: 'py-2.5', gap: 'gap-3', showAvatar: true, showPreview: true },
+ comfortable: { py: 'py-4', gap: 'gap-4', showAvatar: true, showPreview: true },
+};
+
+function DensityPreview({ density }: { density: Density }) {
+ const cfg = DENSITY_PREVIEW[density];
+ const rows = [
+ { unread: true, sender: 'Alice Johnson', subject: 'Project update — Q1 roadmap', preview: 'Here are the latest numbers from…' },
+ { unread: false, sender: 'Bob Smith', subject: 'Re: Meeting notes', preview: 'Thanks, will review and get back...' },
+ { unread: true, sender: 'Carol Lee', subject: 'Invoice #4092', preview: 'Please find attached the invoice…' },
+ ];
+
+ return (
+