feat(briefwechsel): ThumbnailRow aria-label leads with Gesendet/Empfangen
Without this prefix, a color-blind user or screen-reader user has no indication of correspondence direction — the colored left border is information but not announced, and the arrow glyphs were removed in the earlier layout pass. Prepending "Gesendet:" or "Empfangen:" to the aria-label gives assistive-tech users the direction first so the row identity is unambiguous even without color perception. Refs #305 Fixes @leonievoss WCAG 1.4.1 concern from PR review Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -50,8 +50,9 @@ const relativeYearLabel = $derived(
|
|||||||
? relativeYearsDe(new Date(doc.documentDate + 'T12:00:00'), now ?? new Date())
|
? relativeYearsDe(new Date(doc.documentDate + 'T12:00:00'), now ?? new Date())
|
||||||
: ''
|
: ''
|
||||||
);
|
);
|
||||||
|
const directionLabel = $derived(isOut ? 'Gesendet' : 'Empfangen');
|
||||||
const ariaLabel = $derived(
|
const ariaLabel = $derived(
|
||||||
`${title}${doc.documentDate ? `, ${formatDate(doc.documentDate)}` : ''}`
|
`${directionLabel}: ${title}${doc.documentDate ? `, ${formatDate(doc.documentDate)}` : ''}`
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ describe('ThumbnailRow', () => {
|
|||||||
expect(link.className).toContain('border-l-accent');
|
expect(link.className).toContain('border-l-accent');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('exposes a descriptive aria-label combining title and date', () => {
|
it('exposes a descriptive aria-label combining direction, title, and date', () => {
|
||||||
render(ThumbnailRow, {
|
render(ThumbnailRow, {
|
||||||
doc: baseDoc,
|
doc: baseDoc,
|
||||||
isOut: true,
|
isOut: true,
|
||||||
@@ -137,10 +137,23 @@ describe('ThumbnailRow', () => {
|
|||||||
|
|
||||||
const link = document.querySelector('a[href="/documents/d1"]') as HTMLElement;
|
const link = document.querySelector('a[href="/documents/d1"]') as HTMLElement;
|
||||||
const label = link.getAttribute('aria-label') ?? '';
|
const label = link.getAttribute('aria-label') ?? '';
|
||||||
|
expect(label).toMatch(/^Gesendet:/);
|
||||||
expect(label).toContain('Liebe Anna');
|
expect(label).toContain('Liebe Anna');
|
||||||
expect(label).toMatch(/1950/);
|
expect(label).toMatch(/1950/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('aria-label begins with "Empfangen:" for incoming letters', () => {
|
||||||
|
render(ThumbnailRow, {
|
||||||
|
doc: baseDoc,
|
||||||
|
isOut: false,
|
||||||
|
showOtherParty: false,
|
||||||
|
now: new Date('2026-06-01T00:00:00Z')
|
||||||
|
});
|
||||||
|
|
||||||
|
const link = document.querySelector('a[href="/documents/d1"]') as HTMLElement;
|
||||||
|
expect(link.getAttribute('aria-label') ?? '').toMatch(/^Empfangen:/);
|
||||||
|
});
|
||||||
|
|
||||||
it('does not inject raw HTML when summary contains markup (XSS regression)', () => {
|
it('does not inject raw HTML when summary contains markup (XSS regression)', () => {
|
||||||
render(ThumbnailRow, {
|
render(ThumbnailRow, {
|
||||||
doc: {
|
doc: {
|
||||||
|
|||||||
Reference in New Issue
Block a user