diff --git a/frontend/src/lib/timeline/LetterCard.svelte b/frontend/src/lib/timeline/LetterCard.svelte index 4f44a6b4..593156fc 100644 --- a/frontend/src/lib/timeline/LetterCard.svelte +++ b/frontend/src/lib/timeline/LetterCard.svelte @@ -2,6 +2,7 @@ import * as m from '$lib/paraglide/messages.js'; import { timelineDateLabel } from './dateLabel'; import GlyphLabel from './GlyphLabel.svelte'; +import TagChip from './TagChip.svelte'; import type { components } from '$lib/generated/api'; type TimelineEntryDTO = components['schemas']['TimelineEntryDTO']; @@ -46,4 +47,9 @@ const receiver = $derived( · {dateLabel} {/if} + {#if entry.rootTagName} + + + {/if} diff --git a/frontend/src/lib/timeline/LetterCard.svelte.spec.ts b/frontend/src/lib/timeline/LetterCard.svelte.spec.ts index f9c928bc..b60c0f5f 100644 --- a/frontend/src/lib/timeline/LetterCard.svelte.spec.ts +++ b/frontend/src/lib/timeline/LetterCard.svelte.spec.ts @@ -1,7 +1,9 @@ import { describe, it, expect, afterEach } from 'vitest'; import { cleanup, render } from 'vitest-browser-svelte'; +import { tick } from 'svelte'; import * as m from '$lib/paraglide/messages.js'; import LetterCard from './LetterCard.svelte'; +import YearLetterStrip from './YearLetterStrip.svelte'; import { timelineDateLabel } from './dateLabel'; import { makeEntry } from './test-factories'; @@ -86,4 +88,42 @@ describe('LetterCard', () => { expect(document.body.textContent).toContain(evil); expect(document.querySelector('a script')).toBeNull(); }); + + it('renders one root-tag chip beneath the meta line when rootTagName is present (REQ-008)', () => { + render(LetterCard, { entry: makeEntry({ rootTagName: 'Familie', rootTagColor: 'sage' }) }); + const chips = document.querySelectorAll('[data-testid="tag-chip"]'); + expect(chips).toHaveLength(1); + expect(chips[0].textContent).toContain('Familie'); + }); + + it('renders no chip when the letter has no root tag (REQ-005/006)', () => { + render(LetterCard, { entry: makeEntry({ rootTagName: undefined, rootTagColor: undefined }) }); + expect(document.querySelector('[data-testid="tag-chip"]')).toBeNull(); + }); + + it('keeps a long tag name from overflowing the card at 320px, full name in the title (REQ-008a)', () => { + document.body.style.width = '320px'; + render(LetterCard, { + entry: makeEntry({ + rootTagName: 'Briefe von der Front und aus der Heimat', + rootTagColor: 'sienna' + }) + }); + const link = document.querySelector('a') as HTMLAnchorElement; + expect(link.scrollWidth).toBeLessThanOrEqual(link.clientWidth); + const chip = document.querySelector('[data-testid="tag-chip"]') as HTMLElement; + expect(chip.getAttribute('title')).toBe('Briefe von der Front und aus der Heimat'); + document.body.style.width = ''; + }); + + it('renders the chip inside an expanded YearLetterStrip too (REQ-012)', async () => { + render(YearLetterStrip, { + letters: [makeEntry({ rootTagName: 'Familie', rootTagColor: 'sage', documentId: 'doc-1' })], + year: 1909 + }); + (document.querySelector('[data-testid="strip-expand"]') as HTMLButtonElement).click(); + await tick(); + const chip = document.querySelector('[data-testid="tag-chip"]'); + expect(chip?.textContent).toContain('Familie'); + }); });