diff --git a/apps/desktop/src/addons/builtin.ai-assistant/AiChatComponent.tsx b/apps/desktop/src/addons/builtin.ai-assistant/AiChatComponent.tsx index 19952c6f..ef88b5ba 100644 --- a/apps/desktop/src/addons/builtin.ai-assistant/AiChatComponent.tsx +++ b/apps/desktop/src/addons/builtin.ai-assistant/AiChatComponent.tsx @@ -713,7 +713,15 @@ const AiChatComponent: React.FC = () => { )} {/* Chat messages */} -
+
{activeSession?.messages.map((msg, i) => (
{
) : (
- {gitFeedback && ( -
- {gitFeedback} -
- )} + {/* Live regions must stay mounted so screen readers can observe + text changes; conditional mounting would hide the update. */} +
+ {gitFeedback} +
{hasConflicts && ( -
+
{t('git.conflicts.banner')}
diff --git a/apps/desktop/src/api/builtin.l10n.ts b/apps/desktop/src/api/builtin.l10n.ts index faa1b10a..c5f2d3a6 100644 --- a/apps/desktop/src/api/builtin.l10n.ts +++ b/apps/desktop/src/api/builtin.l10n.ts @@ -258,6 +258,7 @@ export function registerBuiltinTranslations() { 'ai.status.badge.ready': 'Ready', 'ai.status.badge.busy': 'Busy', 'ai.disclaimer': 'Trixty AI can make mistakes. Check important info.', + 'ai.chat_log_label': 'AI chat transcript', 'terminal.error_connect': 'Error connecting to terminal: ', 'editor.empty_desc': 'Select a file from the explorer to begin', @@ -635,6 +636,7 @@ export function registerBuiltinTranslations() { 'ai.status.badge.ready': 'Listo', 'ai.status.badge.busy': 'Ocupado', 'ai.disclaimer': 'Trixty AI puede cometer errores. Verifica info importante.', + 'ai.chat_log_label': 'Transcripción del chat de IA', 'terminal.error_connect': 'Error al conectar con la terminal: ', 'editor.empty_desc': 'Selecciona un archivo del explorador para comenzar', diff --git a/apps/desktop/src/components/UpdaterDialog.tsx b/apps/desktop/src/components/UpdaterDialog.tsx index 06061f63..88030dfe 100644 --- a/apps/desktop/src/components/UpdaterDialog.tsx +++ b/apps/desktop/src/components/UpdaterDialog.tsx @@ -112,8 +112,34 @@ const UpdaterDialog: React.FC = () => { } }; + // Build the string AT should announce for the current phase. Progress + // percentage is intentionally omitted because `updater-progress` fires + // on every chunk and would flood screen readers if it lived inside a + // live region. + const getAnnouncement = (): string => { + switch (state.phase) { + case "checking": return t('updater.checking'); + case "up-to-date": return `${getDialogTitle()}. ${t('updater.uptodate')}`; + case "available": return `${getDialogTitle()}. ${t('updater.new_version')} ${state.version}`; + case "downloading": return t('updater.downloading'); + case "ready": return `${getDialogTitle()}. ${t('updater.relaunching')}`; + case "error": return `${getDialogTitle()}. ${state.message}`; + default: return getDialogTitle(); + } + }; + return (
+ {/* Dedicated live region so only the phase text is announced — not + the whole toast with buttons, and not every frame of the + `updater-progress` stream. Role escalates to `alert` on error. */} + + {getAnnouncement()} +
{/* Header */}