mirror of
https://github.com/bulwarkmail/native.git
synced 2026-11-01 00:07:01 +00:00
fix: name the month button by its month and the participant remove button by the person
This commit is contained in:
+4
-2
@@ -93,7 +93,8 @@
|
||||
},
|
||||
"occurrence_not_found_again": "Die Änderung wurde nicht gespeichert: Der Termin konnte auf dem Server nicht wiedergefunden werden. Versuchen Sie es erneut.",
|
||||
"participants": {
|
||||
"limit_warning": "Mehr als {max, plural, one {# Teilnehmer} other {# Teilnehmer}}, den Organisator mitgezählt: Der Server lehnt das Speichern dieses Termins möglicherweise ab. Ihr Administrator kann das Limit erhöhen."
|
||||
"limit_warning": "Mehr als {max, plural, one {# Teilnehmer} other {# Teilnehmer}}, den Organisator mitgezählt: Der Server lehnt das Speichern dieses Termins möglicherweise ab. Ihr Administrator kann das Limit erhöhen.",
|
||||
"remove_named": "{name} entfernen"
|
||||
},
|
||||
"recurrence": {
|
||||
"editor_occurrences_count": "{count, plural, one {Termin} other {Terminen}}",
|
||||
@@ -148,7 +149,8 @@
|
||||
},
|
||||
"detail": {
|
||||
"delete_confirm": "Dieses Ereignis löschen?"
|
||||
}
|
||||
},
|
||||
"change_month_named": "{month}, Monat wechseln"
|
||||
},
|
||||
"common": {
|
||||
"add": "Hinzufügen",
|
||||
|
||||
+3
-1
@@ -13,6 +13,7 @@
|
||||
"alerts": {
|
||||
"minutes_after": "{count, plural, one {# minute after} other {# minutes after}}"
|
||||
},
|
||||
"change_month_named": "{month}, change month",
|
||||
"colors": {
|
||||
"indigo": "Indigo",
|
||||
"teal": "Teal"
|
||||
@@ -116,7 +117,8 @@
|
||||
"occurrence_not_found_again": "The change was not saved: the occurrence could not be found again on the server. Please try again.",
|
||||
"participants": {
|
||||
"group_members": "{count, plural, one {# member} other {# members}}",
|
||||
"limit_warning": "More than {max, plural, one {# participant} other {# participants}}, including the organizer: the server may refuse to save this event. An administrator can raise the limit."
|
||||
"limit_warning": "More than {max, plural, one {# participant} other {# participants}}, including the organizer: the server may refuse to save this event. An administrator can raise the limit.",
|
||||
"remove_named": "Remove {name}"
|
||||
},
|
||||
"recurrence": {
|
||||
"editor_occurrences_count": "{count, plural, one {occurrence} other {occurrences}}",
|
||||
|
||||
@@ -14,6 +14,7 @@ import { useContactsStore, type RecipientSuggestion } from '../../stores/contact
|
||||
import { useLocaleStore } from '../../stores/locale-store';
|
||||
import type { Attendee } from '../../lib/calendar-participants';
|
||||
import { participantSuggestions, participantsFromSuggestion } from '../../lib/calendar-participant-suggestions';
|
||||
import { participantRemoveAccessibilityLabel } from '../../lib/calendar-a11y';
|
||||
|
||||
interface ParticipantInputProps {
|
||||
attendees: Attendee[];
|
||||
@@ -92,7 +93,7 @@ export function ParticipantInput({ attendees, onAdd, onRemove }: ParticipantInpu
|
||||
onPress={() => onRemove(a.email)}
|
||||
hitSlop={6}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={t('calendar.participants.remove', 'Remove')}
|
||||
accessibilityLabel={participantRemoveAccessibilityLabel(a, t)}
|
||||
>
|
||||
<X size={12} color={c.textMuted} />
|
||||
</Pressable>
|
||||
|
||||
@@ -7,7 +7,12 @@ vi.hoisted(() => {
|
||||
import { enUS } from 'date-fns/locale';
|
||||
import type { CalendarEvent } from '../../api/types';
|
||||
import { formatMessage } from '../../i18n/format';
|
||||
import { dayCellAccessibilityLabel, eventAccessibilityLabel } from '../calendar-a11y';
|
||||
import {
|
||||
dayCellAccessibilityLabel,
|
||||
eventAccessibilityLabel,
|
||||
monthButtonAccessibilityLabel,
|
||||
participantRemoveAccessibilityLabel,
|
||||
} from '../calendar-a11y';
|
||||
import { useSettingsStore } from '../../stores/settings-store';
|
||||
|
||||
const t = (_key: string, fallback?: string, params?: Record<string, string | number>) =>
|
||||
@@ -46,3 +51,24 @@ describe('eventAccessibilityLabel', () => {
|
||||
.toMatch(/^\(No title\), Monday, Nov(ember)? 2, 2026, 9:00 AM – 9:15 AM, Cancelled$/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('header and chip buttons', () => {
|
||||
it('names the month button by the month it shows, not "Click to change month"', () => {
|
||||
expect(monthButtonAccessibilityLabel('October 2026', t)).toBe('October 2026, change month');
|
||||
});
|
||||
|
||||
it('names the cross on a participant chip by the person it removes', () => {
|
||||
expect(participantRemoveAccessibilityLabel({ name: 'Ana Lima', email: 'ana@example.com' }, t)).toBe('Remove Ana Lima');
|
||||
expect(participantRemoveAccessibilityLabel({ name: '', email: 'ana@example.com' }, t)).toBe('Remove ana@example.com');
|
||||
});
|
||||
|
||||
it('is what the calendar header and the participant chips use', async () => {
|
||||
const fs = await import('node:fs');
|
||||
const path = await import('node:path');
|
||||
const screen = fs.readFileSync(path.resolve(__dirname, '../../screens/CalendarScreen.tsx'), 'utf8');
|
||||
const chips = fs.readFileSync(path.resolve(__dirname, '../../components/calendar/ParticipantInput.tsx'), 'utf8');
|
||||
expect(screen).toMatch(/accessibilityLabel=\{monthButtonAccessibilityLabel\(/);
|
||||
expect(screen).not.toMatch(/mini_calendar_change/);
|
||||
expect(chips).toMatch(/accessibilityLabel=\{participantRemoveAccessibilityLabel\(a, t\)\}/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,6 +11,20 @@ type Translate = (key: string, fallback?: string, params?: Record<string, string
|
||||
// 19e0acde9): a day cell by its full date and how many events it has, an
|
||||
// event by its title, date, time, calendar and state.
|
||||
|
||||
/**
|
||||
* "October 2026, change month" for the header button that opens the month
|
||||
* panel: the month shown first, then what the button does. Not the
|
||||
* webmail's "Click to change month" (calendar.mini_calendar_change).
|
||||
*/
|
||||
export function monthButtonAccessibilityLabel(title: string, t: Translate): string {
|
||||
return t('calendar.change_month_named', '{month}, change month', { month: title });
|
||||
}
|
||||
|
||||
/** "Remove Ana" for the cross on an invited participant's chip (webmail recipient_remove_named). */
|
||||
export function participantRemoveAccessibilityLabel(attendee: { name?: string; email: string }, t: Translate): string {
|
||||
return t('calendar.participants.remove_named', 'Remove {name}', { name: attendee.name?.trim() || attendee.email });
|
||||
}
|
||||
|
||||
/** "Monday, November 2, 2026, 3 events" for a month day cell. */
|
||||
export function dayCellAccessibilityLabel(day: Date, eventCount: number, t: Translate, locale: Locale): string {
|
||||
const date = formatCalendarDate(day, locale.code, 'longWeekdayMonthDayYear');
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
} from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { useFocusEffect } from '@react-navigation/native';
|
||||
import { monthButtonAccessibilityLabel } from '../lib/calendar-a11y';
|
||||
import { TASK_CHIP_ID_PREFIX, multiDayCount } from '../lib/calendar-time-grid';
|
||||
import {
|
||||
Calendar as CalendarIcon,
|
||||
@@ -1037,7 +1038,7 @@ export default function CalendarScreen() {
|
||||
style={styles.titleBtn}
|
||||
hitSlop={6}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={t('calendar.mini_calendar_change', 'Change month')}
|
||||
accessibilityLabel={monthButtonAccessibilityLabel(headerTitle(titleDate, locale), t)}
|
||||
accessibilityState={{ expanded: monthPanelOpen }}
|
||||
>
|
||||
<Text style={styles.headerTitle} numberOfLines={1}>
|
||||
|
||||
Reference in New Issue
Block a user