feat: add extra-compact density option and fix font size scaling
- Add 'extra-compact' density level that hides avatars and preview text, showing only sender and subject for maximum information density - Add visual density preview in appearance settings showing a 3-row email list mockup that reflects each density option - Fix global font size setting only changing line height by moving font-size from body to :root so rem-based Tailwind classes scale - Apply extra-compact behavior to email list items, thread list items, thread email items, and thread conversation view (EmailCard) - Update email list virtualizer size estimates for extra-compact - Add extra-compact translations for all 8 locales
This commit is contained in:
+2
-1
@@ -3,6 +3,8 @@
|
|||||||
@custom-variant dark (&:where(.dark, .dark *));
|
@custom-variant dark (&:where(.dark, .dark *));
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
|
font-size: var(--font-size-base);
|
||||||
|
|
||||||
--color-border: #e2e8f0;
|
--color-border: #e2e8f0;
|
||||||
--color-input: #e2e8f0;
|
--color-input: #e2e8f0;
|
||||||
--color-ring: #94a3b8;
|
--color-ring: #94a3b8;
|
||||||
@@ -79,7 +81,6 @@ body {
|
|||||||
system-ui,
|
system-ui,
|
||||||
-apple-system,
|
-apple-system,
|
||||||
sans-serif;
|
sans-serif;
|
||||||
font-size: var(--font-size-base);
|
|
||||||
font-feature-settings:
|
font-feature-settings:
|
||||||
"rlig" 1,
|
"rlig" 1,
|
||||||
"calt" 1;
|
"calt" 1;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export function EmailListItem({ email, selected, onClick, onContextMenu }: Email
|
|||||||
const t = useTranslations('email_viewer');
|
const t = useTranslations('email_viewer');
|
||||||
const { selectedEmailIds, toggleEmailSelection, selectRangeEmails, selectedMailbox, clearSelection } = useEmailStore();
|
const { selectedEmailIds, toggleEmailSelection, selectRangeEmails, selectedMailbox, clearSelection } = useEmailStore();
|
||||||
const showPreview = useSettingsStore((state) => state.showPreview);
|
const showPreview = useSettingsStore((state) => state.showPreview);
|
||||||
|
const density = useSettingsStore((state) => state.density);
|
||||||
const emailKeywords = useSettingsStore((state) => state.emailKeywords);
|
const emailKeywords = useSettingsStore((state) => state.emailKeywords);
|
||||||
const { identities } = useAuthStore();
|
const { identities } = useAuthStore();
|
||||||
const isChecked = selectedEmailIds.has(email.id);
|
const isChecked = selectedEmailIds.has(email.id);
|
||||||
@@ -116,12 +117,14 @@ export function EmailListItem({ email, selected, onClick, onContextMenu }: Email
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Avatar */}
|
{/* Avatar */}
|
||||||
<Avatar
|
{density !== 'extra-compact' && (
|
||||||
name={sender?.name}
|
<Avatar
|
||||||
email={sender?.email}
|
name={sender?.name}
|
||||||
size="md"
|
email={sender?.email}
|
||||||
className="flex-shrink-0 shadow-sm"
|
size="md"
|
||||||
/>
|
className="flex-shrink-0 shadow-sm"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
@@ -183,7 +186,7 @@ export function EmailListItem({ email, selected, onClick, onContextMenu }: Email
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Third Line: Preview (controlled by showPreview setting) */}
|
{/* Third Line: Preview (controlled by showPreview setting) */}
|
||||||
{showPreview && (
|
{showPreview && density !== 'extra-compact' && (
|
||||||
<p className={cn(
|
<p className={cn(
|
||||||
"text-sm leading-relaxed line-clamp-2",
|
"text-sm leading-relaxed line-clamp-2",
|
||||||
isUnread
|
isUnread
|
||||||
|
|||||||
@@ -100,8 +100,8 @@ export function EmailList({
|
|||||||
const showPreview = useSettingsStore((state) => state.showPreview);
|
const showPreview = useSettingsStore((state) => state.showPreview);
|
||||||
|
|
||||||
const estimateSize = useCallback(() => {
|
const estimateSize = useCallback(() => {
|
||||||
const base = { compact: 60, regular: 84, comfortable: 104 }[density];
|
const base = { 'extra-compact': 32, compact: 60, regular: 84, comfortable: 104 }[density];
|
||||||
return showPreview ? base + 36 : base;
|
return (showPreview && density !== 'extra-compact') ? base + 36 : base;
|
||||||
}, [density, showPreview]);
|
}, [density, showPreview]);
|
||||||
|
|
||||||
const virtualizer = useVirtualizer({
|
const virtualizer = useVirtualizer({
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ function EmailCard({
|
|||||||
}: EmailCardProps) {
|
}: EmailCardProps) {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const resolvedTheme = useThemeStore((state) => state.resolvedTheme);
|
const resolvedTheme = useThemeStore((state) => state.resolvedTheme);
|
||||||
|
const density = useSettingsStore((state) => state.density);
|
||||||
const sender = email.from?.[0];
|
const sender = email.from?.[0];
|
||||||
const isUnread = !email.keywords?.$seen;
|
const isUnread = !email.keywords?.$seen;
|
||||||
const isStarred = email.keywords?.$flagged;
|
const isStarred = email.keywords?.$flagged;
|
||||||
@@ -428,12 +429,14 @@ function EmailCard({
|
|||||||
)}
|
)}
|
||||||
style={{ gap: 'var(--density-item-gap)', padding: 'var(--density-card-p)' }}
|
style={{ gap: 'var(--density-item-gap)', padding: 'var(--density-card-p)' }}
|
||||||
>
|
>
|
||||||
<Avatar
|
{density !== 'extra-compact' && (
|
||||||
name={sender?.name}
|
<Avatar
|
||||||
email={sender?.email}
|
name={sender?.name}
|
||||||
size="md"
|
email={sender?.email}
|
||||||
className="flex-shrink-0"
|
size="md"
|
||||||
/>
|
className="flex-shrink-0"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<div className="flex items-center gap-2 mb-0.5">
|
<div className="flex items-center gap-2 mb-0.5">
|
||||||
<span className={cn(
|
<span className={cn(
|
||||||
@@ -452,7 +455,7 @@ function EmailCard({
|
|||||||
<div className="text-sm text-muted-foreground">
|
<div className="text-sm text-muted-foreground">
|
||||||
{formatDate(email.receivedAt)}
|
{formatDate(email.receivedAt)}
|
||||||
</div>
|
</div>
|
||||||
{!isExpanded && (
|
{!isExpanded && density !== 'extra-compact' && (
|
||||||
<p className="text-sm text-muted-foreground mt-1 line-clamp-2">
|
<p className="text-sm text-muted-foreground mt-1 line-clamp-2">
|
||||||
{email.preview || "No preview available"}
|
{email.preview || "No preview available"}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { Avatar } from "@/components/ui/avatar";
|
|||||||
import { Paperclip, Star, Circle, CheckSquare, Square } from "lucide-react";
|
import { Paperclip, Star, Circle, CheckSquare, Square } from "lucide-react";
|
||||||
import { useEmailDrag } from "@/hooks/use-email-drag";
|
import { useEmailDrag } from "@/hooks/use-email-drag";
|
||||||
import { useEmailStore } from "@/stores/email-store";
|
import { useEmailStore } from "@/stores/email-store";
|
||||||
|
import { useSettingsStore } from "@/stores/settings-store";
|
||||||
|
|
||||||
interface ThreadEmailItemProps {
|
interface ThreadEmailItemProps {
|
||||||
email: Email;
|
email: Email;
|
||||||
@@ -27,6 +28,7 @@ export function ThreadEmailItem({
|
|||||||
const isStarred = email.keywords?.$flagged;
|
const isStarred = email.keywords?.$flagged;
|
||||||
const sender = email.from?.[0];
|
const sender = email.from?.[0];
|
||||||
const { selectedMailbox, selectedEmailIds, toggleEmailSelection, selectRangeEmails, clearSelection } = useEmailStore();
|
const { selectedMailbox, selectedEmailIds, toggleEmailSelection, selectRangeEmails, clearSelection } = useEmailStore();
|
||||||
|
const density = useSettingsStore((state) => state.density);
|
||||||
const isChecked = selectedEmailIds.has(email.id);
|
const isChecked = selectedEmailIds.has(email.id);
|
||||||
|
|
||||||
const { dragHandlers, isDragging } = useEmailDrag({
|
const { dragHandlers, isDragging } = useEmailDrag({
|
||||||
@@ -104,12 +106,14 @@ export function ThreadEmailItem({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Small Avatar */}
|
{/* Small Avatar */}
|
||||||
<Avatar
|
{density !== 'extra-compact' && (
|
||||||
name={sender?.name}
|
<Avatar
|
||||||
email={sender?.email}
|
name={sender?.name}
|
||||||
size="sm"
|
email={sender?.email}
|
||||||
className="flex-shrink-0"
|
size="sm"
|
||||||
/>
|
className="flex-shrink-0"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ const SingleEmailItem = React.forwardRef<HTMLDivElement, SingleEmailItemProps>(
|
|||||||
const sender = email.from?.[0];
|
const sender = email.from?.[0];
|
||||||
const { selectedMailbox, selectedEmailIds, toggleEmailSelection, selectRangeEmails, clearSelection } = useEmailStore();
|
const { selectedMailbox, selectedEmailIds, toggleEmailSelection, selectRangeEmails, clearSelection } = useEmailStore();
|
||||||
const emailKeywords = useSettingsStore((state) => state.emailKeywords);
|
const emailKeywords = useSettingsStore((state) => state.emailKeywords);
|
||||||
|
const density = useSettingsStore((state) => state.density);
|
||||||
const isChecked = selectedEmailIds.has(email.id);
|
const isChecked = selectedEmailIds.has(email.id);
|
||||||
|
|
||||||
// Resolve color and keyword definition from keyword definitions if not passed directly
|
// Resolve color and keyword definition from keyword definitions if not passed directly
|
||||||
@@ -128,12 +129,14 @@ const SingleEmailItem = React.forwardRef<HTMLDivElement, SingleEmailItemProps>(
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Avatar
|
{density !== 'extra-compact' && (
|
||||||
name={sender?.name}
|
<Avatar
|
||||||
email={sender?.email}
|
name={sender?.name}
|
||||||
size="md"
|
email={sender?.email}
|
||||||
className="flex-shrink-0 shadow-sm"
|
size="md"
|
||||||
/>
|
className="flex-shrink-0 shadow-sm"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<div className="flex items-center justify-between gap-2 mb-1">
|
<div className="flex items-center justify-between gap-2 mb-1">
|
||||||
@@ -185,7 +188,7 @@ const SingleEmailItem = React.forwardRef<HTMLDivElement, SingleEmailItemProps>(
|
|||||||
{email.subject || "(no subject)"}
|
{email.subject || "(no subject)"}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{showPreview && (
|
{showPreview && density !== 'extra-compact' && (
|
||||||
<p className={cn(
|
<p className={cn(
|
||||||
"text-sm leading-relaxed line-clamp-2",
|
"text-sm leading-relaxed line-clamp-2",
|
||||||
isUnread
|
isUnread
|
||||||
@@ -216,6 +219,7 @@ export const ThreadListItem = React.forwardRef<HTMLDivElement, ThreadListItemPro
|
|||||||
}, ref) {
|
}, ref) {
|
||||||
const t = useTranslations('threads');
|
const t = useTranslations('threads');
|
||||||
const showPreview = useSettingsStore((state) => state.showPreview);
|
const showPreview = useSettingsStore((state) => state.showPreview);
|
||||||
|
const density = useSettingsStore((state) => state.density);
|
||||||
const isMobile = useUIStore((state) => state.isMobile);
|
const isMobile = useUIStore((state) => state.isMobile);
|
||||||
const { latestEmail, participantNames, hasUnread, hasStarred, hasAttachment, emailCount } = thread;
|
const { latestEmail, participantNames, hasUnread, hasStarred, hasAttachment, emailCount } = thread;
|
||||||
|
|
||||||
@@ -377,12 +381,14 @@ export const ThreadListItem = React.forwardRef<HTMLDivElement, ThreadListItemPro
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Avatar
|
{density !== 'extra-compact' && (
|
||||||
name={latestEmail.from?.[0]?.name}
|
<Avatar
|
||||||
email={latestEmail.from?.[0]?.email}
|
name={latestEmail.from?.[0]?.name}
|
||||||
size="md"
|
email={latestEmail.from?.[0]?.email}
|
||||||
className="flex-shrink-0 shadow-sm"
|
size="md"
|
||||||
/>
|
className="flex-shrink-0 shadow-sm"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<div className="flex items-center justify-between gap-2 mb-1">
|
<div className="flex items-center justify-between gap-2 mb-1">
|
||||||
@@ -446,7 +452,7 @@ export const ThreadListItem = React.forwardRef<HTMLDivElement, ThreadListItemPro
|
|||||||
{latestEmail.subject || "(no subject)"}
|
{latestEmail.subject || "(no subject)"}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{showPreview && (
|
{showPreview && density !== 'extra-compact' && (
|
||||||
<p className={cn(
|
<p className={cn(
|
||||||
"text-sm leading-relaxed line-clamp-2",
|
"text-sm leading-relaxed line-clamp-2",
|
||||||
hasUnread
|
hasUnread
|
||||||
|
|||||||
@@ -2,9 +2,62 @@
|
|||||||
|
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
import { useThemeStore } from '@/stores/theme-store';
|
import { useThemeStore } from '@/stores/theme-store';
|
||||||
import { useSettingsStore, type ToolbarPosition } from '@/stores/settings-store';
|
import { useSettingsStore, type ToolbarPosition, type Density } from '@/stores/settings-store';
|
||||||
import { LanguageSwitcher } from '@/components/ui/language-switcher';
|
import { LanguageSwitcher } from '@/components/ui/language-switcher';
|
||||||
import { SettingsSection, SettingItem, RadioGroup, ToggleSwitch } from './settings-section';
|
import { SettingsSection, SettingItem, RadioGroup, ToggleSwitch } from './settings-section';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
|
const DENSITY_PREVIEW: Record<Density, { py: string; gap: string; showAvatar: boolean; showPreview: boolean }> = {
|
||||||
|
'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 (
|
||||||
|
<div className="mt-3 rounded-lg border border-border overflow-hidden bg-background text-xs select-none">
|
||||||
|
{rows.map((row, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className={cn(
|
||||||
|
"flex items-center px-3 border-b border-border last:border-b-0",
|
||||||
|
cfg.py,
|
||||||
|
cfg.gap
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{cfg.showAvatar && (
|
||||||
|
<div className={cn(
|
||||||
|
"flex-shrink-0 rounded-full bg-muted",
|
||||||
|
density === 'comfortable' ? "w-8 h-8" : "w-6 h-6"
|
||||||
|
)} />
|
||||||
|
)}
|
||||||
|
<div className="flex-1 min-w-0">
|
||||||
|
<div className="flex items-center justify-between gap-2">
|
||||||
|
<span className={cn("truncate", row.unread ? "font-semibold text-foreground" : "text-muted-foreground")}>
|
||||||
|
{row.sender}
|
||||||
|
</span>
|
||||||
|
<span className="text-[10px] text-muted-foreground flex-shrink-0 tabular-nums">12:00</span>
|
||||||
|
</div>
|
||||||
|
<div className={cn("truncate", row.unread ? "font-medium text-foreground" : "text-foreground/80")}>
|
||||||
|
{row.subject}
|
||||||
|
</div>
|
||||||
|
{cfg.showPreview && (
|
||||||
|
<div className="truncate text-muted-foreground/70">{row.preview}</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function AppearanceSettings() {
|
export function AppearanceSettings() {
|
||||||
const t = useTranslations('settings.appearance');
|
const t = useTranslations('settings.appearance');
|
||||||
@@ -49,14 +102,16 @@ export function AppearanceSettings() {
|
|||||||
<RadioGroup
|
<RadioGroup
|
||||||
value={density}
|
value={density}
|
||||||
onChange={(value) =>
|
onChange={(value) =>
|
||||||
updateSetting('density', value as 'compact' | 'regular' | 'comfortable')
|
updateSetting('density', value as Density)
|
||||||
}
|
}
|
||||||
options={[
|
options={[
|
||||||
|
{ value: 'extra-compact', label: t('list_density.extra_compact') },
|
||||||
{ value: 'compact', label: t('list_density.compact') },
|
{ value: 'compact', label: t('list_density.compact') },
|
||||||
{ value: 'regular', label: t('list_density.regular') },
|
{ value: 'regular', label: t('list_density.regular') },
|
||||||
{ value: 'comfortable', label: t('list_density.comfortable') },
|
{ value: 'comfortable', label: t('list_density.comfortable') },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
<DensityPreview density={density} />
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
|
|
||||||
{/* Toolbar Position */}
|
{/* Toolbar Position */}
|
||||||
|
|||||||
@@ -512,6 +512,7 @@
|
|||||||
"list_density": {
|
"list_density": {
|
||||||
"label": "Dichte",
|
"label": "Dichte",
|
||||||
"description": "Abstände in der Benutzeroberfläche steuern",
|
"description": "Abstände in der Benutzeroberfläche steuern",
|
||||||
|
"extra_compact": "Sehr kompakt",
|
||||||
"compact": "Kompakt",
|
"compact": "Kompakt",
|
||||||
"regular": "Normal",
|
"regular": "Normal",
|
||||||
"comfortable": "Komfortabel"
|
"comfortable": "Komfortabel"
|
||||||
|
|||||||
@@ -512,6 +512,7 @@
|
|||||||
"list_density": {
|
"list_density": {
|
||||||
"label": "Density",
|
"label": "Density",
|
||||||
"description": "Control spacing and padding across the UI",
|
"description": "Control spacing and padding across the UI",
|
||||||
|
"extra_compact": "Extra Compact",
|
||||||
"compact": "Compact",
|
"compact": "Compact",
|
||||||
"regular": "Regular",
|
"regular": "Regular",
|
||||||
"comfortable": "Comfortable"
|
"comfortable": "Comfortable"
|
||||||
|
|||||||
@@ -512,6 +512,7 @@
|
|||||||
"list_density": {
|
"list_density": {
|
||||||
"label": "Densidad",
|
"label": "Densidad",
|
||||||
"description": "Controle el espaciado en toda la interfaz",
|
"description": "Controle el espaciado en toda la interfaz",
|
||||||
|
"extra_compact": "Extra compacto",
|
||||||
"compact": "Compacto",
|
"compact": "Compacto",
|
||||||
"regular": "Regular",
|
"regular": "Regular",
|
||||||
"comfortable": "Cómodo"
|
"comfortable": "Cómodo"
|
||||||
|
|||||||
@@ -512,6 +512,7 @@
|
|||||||
"list_density": {
|
"list_density": {
|
||||||
"label": "Densité",
|
"label": "Densité",
|
||||||
"description": "Contrôlez l'espacement dans toute l'interface",
|
"description": "Contrôlez l'espacement dans toute l'interface",
|
||||||
|
"extra_compact": "Très compacte",
|
||||||
"compact": "Compacte",
|
"compact": "Compacte",
|
||||||
"regular": "Normale",
|
"regular": "Normale",
|
||||||
"comfortable": "Confortable"
|
"comfortable": "Confortable"
|
||||||
|
|||||||
@@ -512,6 +512,7 @@
|
|||||||
"list_density": {
|
"list_density": {
|
||||||
"label": "Densità",
|
"label": "Densità",
|
||||||
"description": "Controlla la spaziatura in tutta l'interfaccia",
|
"description": "Controlla la spaziatura in tutta l'interfaccia",
|
||||||
|
"extra_compact": "Molto compatto",
|
||||||
"compact": "Compatto",
|
"compact": "Compatto",
|
||||||
"regular": "Normale",
|
"regular": "Normale",
|
||||||
"comfortable": "Comodo"
|
"comfortable": "Comodo"
|
||||||
|
|||||||
@@ -512,6 +512,7 @@
|
|||||||
"list_density": {
|
"list_density": {
|
||||||
"label": "密度",
|
"label": "密度",
|
||||||
"description": "UI全体の間隔を調整",
|
"description": "UI全体の間隔を調整",
|
||||||
|
"extra_compact": "極小",
|
||||||
"compact": "コンパクト",
|
"compact": "コンパクト",
|
||||||
"regular": "標準",
|
"regular": "標準",
|
||||||
"comfortable": "ゆったり"
|
"comfortable": "ゆったり"
|
||||||
|
|||||||
@@ -512,6 +512,7 @@
|
|||||||
"list_density": {
|
"list_density": {
|
||||||
"label": "Dichtheid",
|
"label": "Dichtheid",
|
||||||
"description": "Regeleer de ruimte in de gehele interface",
|
"description": "Regeleer de ruimte in de gehele interface",
|
||||||
|
"extra_compact": "Extra compact",
|
||||||
"compact": "Compact",
|
"compact": "Compact",
|
||||||
"regular": "Normaal",
|
"regular": "Normaal",
|
||||||
"comfortable": "Comfortabel"
|
"comfortable": "Comfortabel"
|
||||||
|
|||||||
@@ -512,6 +512,7 @@
|
|||||||
"list_density": {
|
"list_density": {
|
||||||
"label": "Densidade",
|
"label": "Densidade",
|
||||||
"description": "Controle o espaçamento em toda a interface",
|
"description": "Controle o espaçamento em toda a interface",
|
||||||
|
"extra_compact": "Extra compacto",
|
||||||
"compact": "Compacto",
|
"compact": "Compacto",
|
||||||
"regular": "Regular",
|
"regular": "Regular",
|
||||||
"comfortable": "Confortável"
|
"comfortable": "Confortável"
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ let isLoadingFromServer = false;
|
|||||||
const SYNC_DEBOUNCE_MS = 2000;
|
const SYNC_DEBOUNCE_MS = 2000;
|
||||||
|
|
||||||
export type FontSize = 'small' | 'medium' | 'large';
|
export type FontSize = 'small' | 'medium' | 'large';
|
||||||
export type Density = 'compact' | 'regular' | 'comfortable';
|
export type Density = 'extra-compact' | 'compact' | 'regular' | 'comfortable';
|
||||||
/** @deprecated Use Density instead */
|
/** @deprecated Use Density instead */
|
||||||
export type ListDensity = Density;
|
export type ListDensity = Density;
|
||||||
export type DeleteAction = 'trash' | 'permanent';
|
export type DeleteAction = 'trash' | 'permanent';
|
||||||
@@ -438,6 +438,14 @@ function applyDensity(density: Density) {
|
|||||||
const root = document.documentElement;
|
const root = document.documentElement;
|
||||||
|
|
||||||
const densityValues = {
|
const densityValues = {
|
||||||
|
'extra-compact': {
|
||||||
|
'--list-item-height': 'auto',
|
||||||
|
'--density-item-py': '2px',
|
||||||
|
'--density-item-gap': '6px',
|
||||||
|
'--density-header-py': '4px',
|
||||||
|
'--density-card-p': '8px',
|
||||||
|
'--density-sidebar-py': '0px',
|
||||||
|
},
|
||||||
compact: {
|
compact: {
|
||||||
'--list-item-height': 'auto',
|
'--list-item-height': 'auto',
|
||||||
'--density-item-py': '4px',
|
'--density-item-py': '4px',
|
||||||
|
|||||||
Reference in New Issue
Block a user