cleanup+a11y: VOD select checkbox — proper aria-label + CSS-class styling
The bulk-select checkbox on each VOD card was carrying a ~140 char
inline-style block (absolute positioning, dimensions, accent-color,
z-index, cursor) — duplicated across every rendered VOD — plus a
truly bizarre title-attribute fallback that hacked the
bulkSelectedCount locale string by stripping placeholder digits:
title=`${UI_TEXT.vods.bulkSelectedCount
.replace("{count}", "0")
.replace(/[0-9]/g, "")
.trim() || "Select"}`
That worked by accident — the placeholder happens to be "{count}
ausgewahlt" / "{count} selected" so stripping digits gave a usable
fragment — but it was fragile and not really an accessible label.
Three fixes:
- Extracted the inline styles to a .vod-select-checkbox CSS rule.
The custom checkbox styling from 4.6.26 means accent-color was
redundant anyway, so dropping it is a no-op visually.
- Added a proper locale key vods.selectAriaLabel ("Select VOD for
bulk action" / "VOD fuer Bulk-Aktion auswaehlen") for the
aria-label attribute.
- Dropped the title-attribute hack entirely. aria-label now provides
the AT-readable name; sighted users get the visual checkbox
which is self-explanatory.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e56bac2c2b
commit
69b83c9d22
@ -363,6 +363,7 @@ const UI_TEXT_DE = {
|
|||||||
updateProgressAria: 'Update-Download-Fortschritt'
|
updateProgressAria: 'Update-Download-Fortschritt'
|
||||||
},
|
},
|
||||||
vods: {
|
vods: {
|
||||||
|
selectAriaLabel: 'VOD fuer Bulk-Aktion auswaehlen',
|
||||||
noneTitle: 'Keine VODs',
|
noneTitle: 'Keine VODs',
|
||||||
noneText: 'Wahle einen Streamer aus der Liste.',
|
noneText: 'Wahle einen Streamer aus der Liste.',
|
||||||
loading: 'Lade VODs...',
|
loading: 'Lade VODs...',
|
||||||
|
|||||||
@ -363,6 +363,7 @@ const UI_TEXT_EN = {
|
|||||||
updateProgressAria: 'Update download progress'
|
updateProgressAria: 'Update download progress'
|
||||||
},
|
},
|
||||||
vods: {
|
vods: {
|
||||||
|
selectAriaLabel: 'Select VOD for bulk action',
|
||||||
noneTitle: 'No VODs',
|
noneTitle: 'No VODs',
|
||||||
noneText: 'Select a streamer from the list.',
|
noneText: 'Select a streamer from the list.',
|
||||||
loading: 'Loading VODs...',
|
loading: 'Loading VODs...',
|
||||||
|
|||||||
@ -257,7 +257,7 @@ function buildVodCardHtml(vod: VOD, streamer: string, downloadedIds?: Set<string
|
|||||||
data-vod-date="${safeDateAttr}"
|
data-vod-date="${safeDateAttr}"
|
||||||
data-vod-streamer="${safeStreamerAttr}"
|
data-vod-streamer="${safeStreamerAttr}"
|
||||||
data-vod-duration="${safeDurationAttr}">
|
data-vod-duration="${safeDurationAttr}">
|
||||||
<input type="checkbox" class="vod-select-checkbox" data-vod-url="${safeUrlAttr}" ${isChecked ? 'checked' : ''} title="${escapeHtml(UI_TEXT.vods.bulkSelectedCount.replace('{count}', '0').replace(/[0-9]/g, '').trim() || 'Select')}" style="position:absolute; top:8px; left:8px; width:18px; height:18px; accent-color:#9146FF; cursor:pointer; z-index:2;">
|
<input type="checkbox" class="vod-select-checkbox" data-vod-url="${safeUrlAttr}" ${isChecked ? 'checked' : ''} aria-label="${escapeHtml(UI_TEXT.vods.selectAriaLabel)}">
|
||||||
${downloadedBadge}
|
${downloadedBadge}
|
||||||
<div class="vod-thumb-wrap">
|
<div class="vod-thumb-wrap">
|
||||||
<img class="vod-thumbnail" loading="lazy" decoding="async" src="${thumb}" alt="" title="${escapeHtml(UI_TEXT.vods.openOnTwitch)}" onerror="this.src='data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 320 180%22><rect fill=%22%23333%22 width=%22320%22 height=%22180%22/></svg>'">
|
<img class="vod-thumbnail" loading="lazy" decoding="async" src="${thumb}" alt="" title="${escapeHtml(UI_TEXT.vods.openOnTwitch)}" onerror="this.src='data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 320 180%22><rect fill=%22%23333%22 width=%22320%22 height=%22180%22/></svg>'">
|
||||||
|
|||||||
@ -1318,6 +1318,19 @@ select option {
|
|||||||
box-shadow: 0 0 0 3px rgba(145, 70, 255, 0.35);
|
box-shadow: 0 0 0 3px rgba(145, 70, 255, 0.35);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The bulk-select checkbox overlaid on each VOD thumbnail top-left.
|
||||||
|
Positioned absolutely so it sits over the artwork without affecting
|
||||||
|
the cards flex/info layout. */
|
||||||
|
.vod-select-checkbox {
|
||||||
|
position: absolute;
|
||||||
|
top: 8px;
|
||||||
|
left: 8px;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
.vod-card.selected {
|
.vod-card.selected {
|
||||||
box-shadow: 0 0 0 2px #9146FF, 0 8px 25px rgba(145, 70, 255, 0.25);
|
box-shadow: 0 0 0 2px #9146FF, 0 8px 25px rgba(145, 70, 255, 0.25);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user