fix(quick-260921-jt4): drei Statussymbole in calendar-settings-panel tragen role="img" (D-03)
Die drei <span> mit aria-label ("Sync error"/"Connection OK"/
"Connection error") hatten die Rolle generic, die keine ARIA-Merkmale
traegt — die Beschriftung wurde stillschweigend verworfen. role="img"
ergaenzt (geprueft sauber, keine useSemanticElements-Neuausloesung).
Die Beschriftung ist hier der einzige Text des Symbols (svg bereits
aria-hidden) — Ursache behoben, nicht das Attribut gestrichen.
Erfolgsfall nutzt den vorhandenen Schluessel calendar.connectionSuccess
woertlich; fuer die beiden Fehlerfaelle neue kurze Schluessel
syncErrorLabel/connectionFailedLabel (der vorhandene connectionError
ist ein ganzer Hinweissatz, als Symbolbeschriftung zu lang). Die drei
fest verdrahteten englischen Texte damit aus der deutschen Oberflaeche.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TPPB4ApQxzSU1rwV2Ffj9J
This commit is contained in:
@@ -13,6 +13,9 @@ vi.mock('next-intl', () => ({
|
||||
'calendar.deleteDialogLabel': 'Löschen bestätigen',
|
||||
'calendar.saveError': 'Fehler beim Speichern',
|
||||
'calendar.saveSuccess': 'Gespeichert',
|
||||
'calendar.connectionSuccess': 'Verbindung erfolgreich',
|
||||
'calendar.syncErrorLabel': 'Synchronisierungsfehler',
|
||||
'calendar.connectionFailedLabel': 'Verbindung fehlgeschlagen',
|
||||
},
|
||||
settings: {
|
||||
sourceDeleteCta: 'Quelle löschen',
|
||||
@@ -129,3 +132,15 @@ describe('CalendarSettingsPanel — delete confirmation dialog (D-01, T-JT4-04)'
|
||||
expect(screen.getByRole('alertdialog')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('CalendarSettingsPanel — Statussymbole tragen role="img" (D-03)', () => {
|
||||
it('der Sync-Fehler-Indikator ist per Rolle+Name ansprechbar, statt sein aria-label an einem rollenlosen <span> zu verschwenden', async () => {
|
||||
vi.mocked(fetchSources).mockResolvedValue([
|
||||
{ ...baseSource, lastSyncError: 'Verbindung abgelehnt' },
|
||||
]);
|
||||
render(<CalendarSettingsPanel />);
|
||||
await screen.findByText('Firmenkalender');
|
||||
|
||||
expect(screen.getByRole('img', { name: 'Synchronisierungsfehler' })).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -154,12 +154,17 @@ export function CalendarSettingsPanel() {
|
||||
{TYPE_LABELS[source.type] || source.type}
|
||||
</span>
|
||||
|
||||
{/* Connection status indicator */}
|
||||
{/* Connection status indicator. role="img" (D-03): die
|
||||
Beschriftung ist der EINZIGE Text dieser Symbole (das
|
||||
<svg> darin ist bereits aria-hidden) — ohne Rolle ist ein
|
||||
<span> "generic" und die Vorlesehilfe verwirft
|
||||
aria-label stillschweigend. */}
|
||||
{source.lastSyncError ? (
|
||||
<span
|
||||
title={source.lastSyncError}
|
||||
className="text-orange-500"
|
||||
aria-label="Sync error"
|
||||
role="img"
|
||||
aria-label={t('calendar.syncErrorLabel')}
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
@@ -179,7 +184,11 @@ export function CalendarSettingsPanel() {
|
||||
</svg>
|
||||
</span>
|
||||
) : testResults[source.id] === 'success' ? (
|
||||
<span className="text-green-500" aria-label="Connection OK">
|
||||
<span
|
||||
className="text-green-500"
|
||||
role="img"
|
||||
aria-label={t('calendar.connectionSuccess')}
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@@ -196,7 +205,11 @@ export function CalendarSettingsPanel() {
|
||||
</svg>
|
||||
</span>
|
||||
) : testResults[source.id] === 'error' ? (
|
||||
<span className="text-orange-500" aria-label="Connection error">
|
||||
<span
|
||||
className="text-orange-500"
|
||||
role="img"
|
||||
aria-label={t('calendar.connectionFailedLabel')}
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
||||
Reference in New Issue
Block a user