diff --git a/components/email/__tests__/thread-list-item-source-folder.test.tsx b/components/email/__tests__/thread-list-item-source-folder.test.tsx index debaad59e..cea7f7705 100644 --- a/components/email/__tests__/thread-list-item-source-folder.test.tsx +++ b/components/email/__tests__/thread-list-item-source-folder.test.tsx @@ -2,6 +2,7 @@ import { Profiler } from 'react'; import { act, render, screen } from '@testing-library/react'; import { describe, it, expect, vi, beforeEach } from 'vitest'; import { ThreadListItem } from '../thread-list-item'; +import { TagDisplayContext, type TagDisplay } from '@/hooks/use-tag-display'; import { useSettingsStore, DEFAULT_KEYWORDS } from '@/stores/settings-store'; import { useEmailStore } from '@/stores/email-store'; import { useUIStore } from '@/stores/ui-store'; @@ -142,3 +143,45 @@ describe('ThreadListItem folder chip in search results (#1172)', () => { }); }); }); + +describe('ThreadListItem sender line in a narrow list', () => { + const display: TagDisplay = { variant: 'badge', placement: 'sender', tight: true }; + const tagged = (keywords: Record) => [makeEmail({ keywords: { $seen: true, ...keywords } })]; + const renderIn = (value: TagDisplay, emails: Email[]) => { + const [thread] = groupEmailsByThread(emails); + return render( + + + , + ); + }; + + beforeEach(() => { + useUIStore.setState({ isMobile: true, isTablet: false, isDesktop: false }); + useSettingsStore.setState({ emailKeywords: [...DEFAULT_KEYWORDS], showPreview: false, mailLayout: 'split', interfaceLayout: 'default', showColorNames: false }); + useEmailStore.setState({ selectedEmailKeys: new Set(), selectedMailbox: 'inbox', isUnifiedView: false, selectedKeyword: null, searchQuery: '', searchFilters: { ...DEFAULT_SEARCH_FILTERS }, searchMailboxId: 'archive' }); + }); + + const dots = (c: HTMLElement) => c.querySelectorAll('[data-tag-dot]').length; + + it('names a single tag', () => { + const { container } = renderIn(display, tagged({ '$label:red': true })); + expect(dots(container)).toBe(0); + }); + + it('turns several tags into dots so the name keeps its room', () => { + const { container } = renderIn(display, tagged({ '$label:red': true, '$label:blue': true })); + expect(dots(container)).toBe(2); + }); + + it('turns a tag into a dot next to the folder chip', () => { + useEmailStore.setState({ searchQuery: 'invoice', searchMailboxId: '' }); + const { container } = renderIn(display, tagged({ '$label:red': true })); + expect(dots(container)).toBe(1); + }); + + it('keeps the names while the list has room', () => { + const { container } = renderIn({ ...display, tight: false }, tagged({ '$label:red': true, '$label:blue': true })); + expect(dots(container)).toBe(0); + }); +}); diff --git a/components/email/thread-list-item.tsx b/components/email/thread-list-item.tsx index 366647703..7c761c530 100644 --- a/components/email/thread-list-item.tsx +++ b/components/email/thread-list-item.tsx @@ -310,10 +310,10 @@ function describeAccount(label: string | undefined, account: AccountEntry | unde * aggregate "All …" views (All Mail / unified / cross-account) where rows come * from different folders. `email.sourceFolder` is stamped at fetch time. */ -function SourceFolderTag({ name }: { name: string }) { +function SourceFolderTag({ name, tight }: { name: string; tight?: boolean }) { return ( @@ -451,7 +451,7 @@ const SingleEmailItem = React.forwardRef( const formatAddress = useOwnDomainAddress(); const tagScope = useEmailTagScope(email); const { sortTagIds, tagColor } = useKeywordFormat(tagScope); - const { variant: tagVariant, placement: tagPlacement } = useTagDisplay(); + const { variant: tagVariant, placement: tagPlacement, tight: senderLineTight } = useTagDisplay(); const tintListRowsByTag = useSettingsStore((state) => state.tintListRowsByTag); const tintListRowsByAccount = useSettingsStore((state) => state.tintListRowsByAccount); // The tint replaces the dot, and the dot can be switched off on its own (#912). @@ -845,7 +845,7 @@ const SingleEmailItem = React.forwardRef( )} {showPaperclip && } - {showSourceFolder && } + {showSourceFolder && } {scheduledSendLabel ? ( ( {tagPlacement === 'sender' && tagIds.length > 0 && ( {tagIds.map((id) => ( - + 1) ? 'dot' : tagVariant} scope={tagScope} /> ))} )} @@ -923,7 +923,7 @@ const SingleEmailItem = React.forwardRef(
- {showSourceFolder && } + {showSourceFolder && } {scheduledSendLabel ? ( state.tintListRowsByTag); const tintListRowsByAccount = useSettingsStore((state) => state.tintListRowsByAccount); // The tint replaces the dot, and the dot can be switched off on its own (#912). @@ -1616,7 +1616,7 @@ export const ThreadListItem = React.forwardRef )} {hasAttachment && } - {showSourceFolder && } + {showSourceFolder && } {scheduledSendLabel ? ( {tagPlacement === 'sender' && tagIds.map((id) => ( - + 1) ? 'dot' : tagVariant} scope={tagScope} /> ))}
@@ -1702,7 +1702,7 @@ export const ThreadListItem = React.forwardRef
- {showSourceFolder && } + {showSourceFolder && } {scheduledSendLabel ? ( ): TagDi return { variant: width >= TAG_NAME_MIN_WIDTH ? "badge" : "dot", placement: width >= TAG_BESIDE_SUBJECT_MIN_WIDTH ? "subject" : "sender", + tight: width < SENDER_LINE_TIGHT_WIDTH, }; }, [width]); }