Skip to content

Commit 0a0b3db

Browse files
committed
FIXED : - Toast notifications now announced properly by screen readers processing#3382
1 parent 85058b4 commit 0a0b3db

File tree

3 files changed

+41
-20
lines changed

3 files changed

+41
-20
lines changed

client/modules/IDE/actions/project.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -174,15 +174,15 @@ export function saveProject(
174174
dispatch(projectSaveSuccess());
175175
if (!autosave) {
176176
if (state.ide.justOpenedProject && state.preferences.autosave) {
177-
dispatch(showToast(5500));
177+
dispatch(showToast(12000));
178178
dispatch(setToastText('Toast.SketchSaved'));
179179
setTimeout(
180180
() => dispatch(setToastText('Toast.AutosaveEnabled')),
181-
1500
181+
60000
182182
);
183183
dispatch(resetJustOpenedProject());
184184
} else {
185-
dispatch(showToast(1500));
185+
dispatch(showToast(6000));
186186
dispatch(setToastText('Toast.SketchSaved'));
187187
}
188188
}
@@ -224,15 +224,15 @@ export function saveProject(
224224
dispatch(projectSaveSuccess());
225225
if (!autosave) {
226226
if (state.preferences.autosave) {
227-
dispatch(showToast(5500));
227+
dispatch(showToast(12000));
228228
dispatch(setToastText('Toast.SketchSaved'));
229229
setTimeout(
230230
() => dispatch(setToastText('Toast.AutosaveEnabled')),
231-
1500
231+
6000
232232
);
233233
dispatch(resetJustOpenedProject());
234234
} else {
235-
dispatch(showToast(1500));
235+
dispatch(showToast(6000));
236236
dispatch(setToastText('Toast.SketchSaved'));
237237
}
238238
}

client/modules/IDE/actions/toast.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ export function hideToast() {
1010
* Temporary fix until #2206 is merged.
1111
* Supports legacy two-action syntax:
1212
* dispatch(setToastText('Toast.SketchFailedSave'));
13-
* dispatch(showToast(1500));
13+
* dispatch(showToast(6000));
1414
* And also supports proposed single-action syntax with message and optional timeout.
1515
* dispatch(showToast('Toast.SketchFailedSave'));
16-
* dispatch(showToast('Toast.SketchSaved', 5500));
16+
* dispatch(showToast('Toast.SketchSaved', 6000));
1717
*/
18-
export function showToast(textOrTime, timeout = 1500) {
18+
export function showToast(textOrTime, timeout = 6000) {
1919
return (dispatch) => {
2020
let time = timeout;
2121
if (typeof textOrTime === 'string') {
+32-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { useEffect } from 'react';
22
import { useDispatch, useSelector } from 'react-redux';
33
import { useTranslation } from 'react-i18next';
44
import { hideToast } from '../actions/toast';
@@ -9,19 +9,40 @@ export default function Toast() {
99
const { text, isVisible } = useSelector((state) => state.toast);
1010
const dispatch = useDispatch();
1111
const { t } = useTranslation();
12+
13+
useEffect(() => {
14+
if (isVisible) {
15+
const liveRegion = document.getElementById('toast-live-region');
16+
if (liveRegion) {
17+
liveRegion.textContent = t(text); // Update live region globally
18+
}
19+
}
20+
}, [isVisible, text, t]);
21+
1222
if (!isVisible) {
1323
return null;
1424
}
25+
1526
return (
16-
<section className="toast" role="status" aria-live="polite">
17-
<p>{t(text)}</p>
18-
<button
19-
className="toast__close"
20-
onClick={() => dispatch(hideToast())}
21-
aria-label="Close Alert"
22-
>
23-
<ExitIcon focusable="false" aria-hidden="true" />
24-
</button>
25-
</section>
27+
<>
28+
{/* Global ARIA Live Region */}
29+
<div
30+
id="toast-live-region"
31+
aria-live="assertive"
32+
style={{ position: 'absolute', left: '-9999px' }}
33+
/>
34+
35+
{/* Toast UI */}
36+
<section className="toast" role="status">
37+
<p>{t(text)}</p>
38+
<button
39+
className="toast__close"
40+
onClick={() => dispatch(hideToast())}
41+
aria-label="Close Alert"
42+
>
43+
<ExitIcon focusable="false" aria-hidden="true" />
44+
</button>
45+
</section>
46+
</>
2647
);
2748
}

0 commit comments

Comments
 (0)