a11y: cut + merge progress bars role=progressbar + aria-valuenow
Following 4.6.64 for the queue progress bars, the cut + merge progress containers in their respective tabs had the same gap: a plain <div class="progress-bar"> wrapping a <div class="progress- bar-fill"> with no semantic role. JS poked the bar's style.width on every percent update; AT had no way to read out the running value. Promoted both .progress-bar wrappers to role="progressbar" with aria-valuemin / max / now, plus aria-label sourced from new locale strings (cutProgressAria / mergeProgressAria) so EN/DE both work. The progress event handlers in renderer.ts now also stamp aria-valuenow on each tick, so AT live regions pick up the percentage as the cut / merge advances. setAttribute is cheap relative to the FFmpeg progress event rate (~1/s), no perf concern. renderer-texts.applyText sets the localized aria-label on both gauges at boot + language switch — text contents already get re-applied through the same path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6213134a27
commit
fa440951d2
@ -372,7 +372,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="progress-container" id="cutProgress">
|
<div class="progress-container" id="cutProgress">
|
||||||
<div class="progress-bar">
|
<div class="progress-bar" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" aria-label="Cut progress" id="cutProgressGauge">
|
||||||
<div class="progress-bar-fill" id="cutProgressBar"></div>
|
<div class="progress-bar-fill" id="cutProgressBar"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="progress-text" id="cutProgressText">0%</div>
|
<div class="progress-text" id="cutProgressText">0%</div>
|
||||||
@ -404,7 +404,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="progress-container" id="mergeProgress">
|
<div class="progress-container" id="mergeProgress">
|
||||||
<div class="progress-bar">
|
<div class="progress-bar" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" aria-label="Merge progress" id="mergeProgressGauge">
|
||||||
<div class="progress-bar-fill" id="mergeProgressBar"></div>
|
<div class="progress-bar-fill" id="mergeProgressBar"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="progress-text" id="mergeProgressText">0%</div>
|
<div class="progress-text" id="mergeProgressText">0%</div>
|
||||||
|
|||||||
@ -357,7 +357,9 @@ const UI_TEXT_DE = {
|
|||||||
liveNowTooltip: 'Aktuell live auf Twitch',
|
liveNowTooltip: 'Aktuell live auf Twitch',
|
||||||
modalCloseAria: 'Dialog schliessen',
|
modalCloseAria: 'Dialog schliessen',
|
||||||
sidebarEmpty: 'Noch keine Streamer. Fuege oben rechts einen hinzu.',
|
sidebarEmpty: 'Noch keine Streamer. Fuege oben rechts einen hinzu.',
|
||||||
removeAria: 'Entfernen'
|
removeAria: 'Entfernen',
|
||||||
|
cutProgressAria: 'Schnitt-Fortschritt',
|
||||||
|
mergeProgressAria: 'Merge-Fortschritt'
|
||||||
},
|
},
|
||||||
vods: {
|
vods: {
|
||||||
noneTitle: 'Keine VODs',
|
noneTitle: 'Keine VODs',
|
||||||
|
|||||||
@ -357,7 +357,9 @@ const UI_TEXT_EN = {
|
|||||||
liveNowTooltip: 'Currently live on Twitch',
|
liveNowTooltip: 'Currently live on Twitch',
|
||||||
modalCloseAria: 'Close dialog',
|
modalCloseAria: 'Close dialog',
|
||||||
sidebarEmpty: 'No streamers yet. Add one via the input at the top right.',
|
sidebarEmpty: 'No streamers yet. Add one via the input at the top right.',
|
||||||
removeAria: 'Remove'
|
removeAria: 'Remove',
|
||||||
|
cutProgressAria: 'Cut progress',
|
||||||
|
mergeProgressAria: 'Merge progress'
|
||||||
},
|
},
|
||||||
vods: {
|
vods: {
|
||||||
noneTitle: 'No VODs',
|
noneTitle: 'No VODs',
|
||||||
|
|||||||
@ -253,6 +253,8 @@ function applyLanguageToStaticUI(): void {
|
|||||||
// Localize the modal close-button aria-label. The buttons share a
|
// Localize the modal close-button aria-label. The buttons share a
|
||||||
// .modal-close-localizable class so one call updates all five.
|
// .modal-close-localizable class so one call updates all five.
|
||||||
setAriaLabelAll('.modal-close-localizable', UI_TEXT.streamers.modalCloseAria);
|
setAriaLabelAll('.modal-close-localizable', UI_TEXT.streamers.modalCloseAria);
|
||||||
|
document.getElementById('cutProgressGauge')?.setAttribute('aria-label', UI_TEXT.streamers.cutProgressAria);
|
||||||
|
document.getElementById('mergeProgressGauge')?.setAttribute('aria-label', UI_TEXT.streamers.mergeProgressAria);
|
||||||
setText('backupCardTitle', UI_TEXT.static.backupCardTitle);
|
setText('backupCardTitle', UI_TEXT.static.backupCardTitle);
|
||||||
setText('backupCardIntro', UI_TEXT.static.backupCardIntro);
|
setText('backupCardIntro', UI_TEXT.static.backupCardIntro);
|
||||||
setText('btnExportConfig', UI_TEXT.static.exportConfig);
|
setText('btnExportConfig', UI_TEXT.static.exportConfig);
|
||||||
|
|||||||
@ -168,13 +168,17 @@ async function init(): Promise<void> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
window.api.onCutProgress((percent: number) => {
|
window.api.onCutProgress((percent: number) => {
|
||||||
|
const rounded = Math.round(percent);
|
||||||
byId('cutProgressBar').style.width = percent + '%';
|
byId('cutProgressBar').style.width = percent + '%';
|
||||||
byId('cutProgressText').textContent = Math.round(percent) + '%';
|
byId('cutProgressText').textContent = rounded + '%';
|
||||||
|
byId('cutProgressGauge').setAttribute('aria-valuenow', String(rounded));
|
||||||
});
|
});
|
||||||
|
|
||||||
window.api.onMergeProgress((percent: number) => {
|
window.api.onMergeProgress((percent: number) => {
|
||||||
|
const rounded = Math.round(percent);
|
||||||
byId('mergeProgressBar').style.width = percent + '%';
|
byId('mergeProgressBar').style.width = percent + '%';
|
||||||
byId('mergeProgressText').textContent = Math.round(percent) + '%';
|
byId('mergeProgressText').textContent = rounded + '%';
|
||||||
|
byId('mergeProgressGauge').setAttribute('aria-valuenow', String(rounded));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update stats bar — paused while the window is hidden so we don't
|
// Update stats bar — paused while the window is hidden so we don't
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user