a11y: bring UI to WCAG 2.2 AAA compliance

Semantic HTML: lang attr, landmarks (header/main/region/complementary),
heading hierarchy (h1-h3), dl/dt/dd for info panel.

ARIA: labels on all icon buttons, aria-hidden on decorative icons,
progressbar role with dynamic aria-valuenow, aria-haspopup/expanded
on all menu triggers, role=listbox/option on playlist, aria-selected,
computed aria-labels on playlist rows.

Contrast: raised --textMuted/--textDim/--icon to AAA 7:1 ratios.

Focus: global :focus-visible outline, slider thumb glow, menu item
highlight, switch focus-within, row focus styles.

Target sizes: 44x44 hit areas on zoom/window/remove buttons via
::before pseudo-elements.

Keyboard: playlist arrow nav + Enter/Space activate + Alt+Arrow
reorder with live region announcements + move buttons. Speed menu,
subtitles menu, and recent menu all keyboard-navigable with
Arrow/Enter/Space/Escape. Dividers resizable via Arrow keys.

Dynamic document.title updates on video/folder load.
This commit is contained in:
Your Name
2026-02-19 16:35:19 +02:00
parent 290ef82176
commit 52934d15d6
11 changed files with 956 additions and 662 deletions

View File

@@ -8,7 +8,7 @@
transform-origin:bottom left;
pointer-events:none;
opacity:0;
transition:opacity .25s ease, transform .25s cubic-bezier(.4,0,.2,1);
transition:opacity .25s ease, transform .35s var(--ease-bounce);
}
#toast.show{
opacity:1;
@@ -17,127 +17,84 @@
.toastInner{
pointer-events:none;
display:flex; align-items:center; gap:12px;
padding:12px 14px;
border-radius:7px;
border:1px solid rgba(255,255,255,.14);
background:rgba(18,20,26,.92);
box-shadow:0 26px 70px rgba(0,0,0,.70);
backdrop-filter:blur(16px);
padding:10px 14px;
border-radius:var(--r);
border:1px solid rgba(140,160,210,.10);
background:rgba(18,21,30,.95);
box-shadow:var(--shadow2);
}
.toastIcon{width:18px; height:18px; display:flex; align-items:center; justify-content:center;}
.toastIcon .fa{font-size:14px; color:rgba(230,236,252,.82)!important; opacity:.95;}
.toastIcon .fa{font-size:14px; color:rgba(200,212,238,.78)!important; opacity:.95; transition:transform .3s var(--ease-bounce);}
#toast.show .toastIcon .fa{animation:toastIconIn .4s var(--ease-bounce);}
@keyframes toastIconIn{
0%{transform:scale(0) rotate(-90deg);}
60%{transform:scale(1.2) rotate(5deg);}
100%{transform:scale(1) rotate(0);}
}
.toastMsg{
font-size:12.8px;
font-weight:760;
letter-spacing:.12px;
color:rgba(246,248,255,.92);
font-size:13px;
font-weight:600;
letter-spacing:0;
color:var(--text);
}
/* Toolbar icon buttons */
/* Toolbar icon buttons — borderless */
.toolbarIcon{
width:36px; height:36px;
border-radius:var(--r2);
background:linear-gradient(180deg, rgba(255,255,255,.07), rgba(255,255,255,.025));
border:1px solid rgba(255,255,255,.1);
color:rgba(246,248,255,.88);
background:var(--surface-2);
border:none;
color:rgba(218,225,240,.85);
font-size:14px;
transition:all .2s cubic-bezier(.4,0,.2,1);
position:relative;
overflow:hidden;
box-shadow:
0 2px 4px rgba(0,0,0,.12),
0 4px 12px rgba(0,0,0,.15),
inset 0 1px 0 rgba(255,255,255,.08);
}
.toolbarIcon::before{
content:"";
position:absolute;
inset:0;
background:linear-gradient(180deg, rgba(255,255,255,.1), transparent 50%);
opacity:0;
transition:opacity .2s ease;
transition:all .2s var(--ease-bounce);
}
.toolbarIcon:hover{
background:linear-gradient(180deg, rgba(255,255,255,.12), rgba(255,255,255,.05));
border-color:rgba(255,255,255,.18);
color:rgba(255,255,255,.98);
transform:translateY(-2px);
box-shadow:
0 4px 8px rgba(0,0,0,.15),
0 8px 20px rgba(0,0,0,.2),
inset 0 1px 0 rgba(255,255,255,.12);
background:var(--surface-3);
color:rgba(235,240,252,.95);
transform:translateY(-1px);
}
.toolbarIcon:hover::before{opacity:1;}
.toolbarIcon:active{
transform:translateY(0);
box-shadow:0 2px 6px rgba(0,0,0,.18);
transform:scale(.9) translateY(0);
transition-duration:.08s;
}
/* Fancy tooltip */
/* Tooltip */
.tooltip{
position:fixed;
pointer-events:none;
z-index:99999;
border-radius:var(--r);
padding:16px 20px;
padding:14px 16px;
opacity:0;
transform:translateY(8px) scale(.97);
transition:opacity .25s ease, transform .25s cubic-bezier(.4,0,.2,1), left .12s ease, top .12s ease;
transform:translateY(6px) scale(.96);
transition:opacity .2s ease, transform .25s var(--ease-bounce), left .12s ease, top .12s ease;
max-width:320px;
font-family:var(--sans);
overflow:hidden;
background:rgba(20,24,32,.5);
backdrop-filter:blur(8px) saturate(1.3);
-webkit-backdrop-filter:blur(8px) saturate(1.3);
border:1px solid rgba(255,255,255,.12);
box-shadow:
0 0 0 1px rgba(0,0,0,.3),
0 4px 8px rgba(0,0,0,.15),
0 12px 24px rgba(0,0,0,.25),
0 24px 48px rgba(0,0,0,.2);
background:rgba(18,21,30,.95);
border:1px solid rgba(140,160,210,.10);
box-shadow:var(--shadow2);
}
.tooltip.visible{
opacity:1;
transform:translateY(0) scale(1);
}
.tooltip::before{
content:"";
position:absolute;
top:0; left:0; right:0;
height:1px;
background:linear-gradient(90deg, transparent 5%, rgba(95,175,255,.5) 30%, rgba(75,200,130,.4) 70%, transparent 95%);
border-radius:var(--r) var(--r) 0 0;
}
.tooltip::after{
content:"";
position:absolute;
top:1px; left:1px; right:1px;
height:40%;
background:linear-gradient(180deg, rgba(255,255,255,.05), transparent);
border-radius:var(--r) var(--r) 0 0;
pointer-events:none;
}
.tooltip::before{display:none;}
.tooltip::after{display:none;}
.tooltip-title{
font-family:var(--brand);
font-weight:800;
font-weight:700;
font-size:14px;
margin-bottom:8px;
margin-bottom:6px;
letter-spacing:-.01em;
background:linear-gradient(135deg, #fff 0%, rgba(180,210,255,1) 50%, rgba(150,230,200,1) 100%);
-webkit-background-clip:text;
background-clip:text;
color:transparent;
text-shadow:none;
position:relative;
z-index:1;
color:rgba(235,240,252,.95);
}
.tooltip-desc{
font-family:var(--sans);
font-size:12px;
font-weight:500;
color:rgba(190,200,225,.88);
color:rgba(170,182,210,.82);
line-height:1.55;
letter-spacing:.01em;
letter-spacing:0;
position:relative;
z-index:1;
}
@@ -147,36 +104,46 @@
.subsBox{position:relative;}
.subsMenu{
position:absolute; left:50%; bottom:calc(100% + 10px);
transform:translateX(-50%);
transform:translateX(-50%) scale(.95);
min-width:220px; padding:8px;
border-radius:7px; border:1px solid rgba(255,255,255,.12);
background:rgba(18,20,26,.94);
box-shadow:0 26px 70px rgba(0,0,0,.70);
backdrop-filter:blur(16px);
border-radius:var(--r); border:1px solid rgba(140,160,210,.10);
background:rgba(18,21,30,.95);
box-shadow:var(--shadow);
display:none; z-index:30;
opacity:0;
transition:opacity .15s ease, transform .2s var(--ease-bounce);
}
.subsMenu.show{display:block;}
.subsMenuHeader{padding:6px 12px 4px; font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.08em; color:rgba(150,160,190,.6);}
.subsMenuItem{padding:10px 12px; border-radius:5px; cursor:pointer; user-select:none; font-size:12px; font-weight:600; color:rgba(246,248,255,.92); letter-spacing:.08px; display:flex; align-items:center; gap:10px; transition:background .12s ease;}
.subsMenuItem:hover{background:rgba(255,255,255,.06);}
.subsMenuItem .fa{font-size:13px; color:var(--iconStrong)!important; opacity:.85; width:18px; text-align:center;}
.subsMenuItem.embedded{color:rgba(180,220,255,.95);}
.subsDivider{height:1px; background:rgba(255,255,255,.08); margin:6px 4px;}
.subsEmpty{padding:10px 12px; color:rgba(165,172,196,.7); font-size:11.5px; text-align:center;}
.subsMenu.show{display:block; opacity:1; transform:translateX(-50%) scale(1);}
.subsMenuHeader{padding:6px 12px 4px; font-size:10px; font-weight:600; text-transform:uppercase; letter-spacing:.08em; color:var(--textDim); transition:color .2s ease;}
.subsMenuItem{padding:10px 12px; border-radius:var(--r3); cursor:pointer; user-select:none; font-size:12px; font-weight:600; color:var(--text); letter-spacing:0; display:flex; align-items:center; gap:10px; transition:all .2s var(--ease-bounce);}
.subsMenuItem:hover{background:var(--surfaceHover); padding-left:16px;}
.subsMenuItem:active{transform:scale(.97); transition-duration:.08s;}
.subsMenuItem .fa{font-size:13px; color:var(--iconStrong)!important; opacity:.85; width:18px; text-align:center; transition:transform .2s var(--ease-bounce), opacity .15s ease;}
.subsMenuItem:hover .fa{transform:scale(1.15) rotate(-5deg); opacity:1;}
.subsMenuItem.embedded{color:rgba(150,185,230,.92);}
.subsDivider{height:1px; background:rgba(140,160,210,.06); margin:6px 4px;}
.subsEmpty{padding:10px 12px; color:var(--textDim); font-size:11px; text-align:center;}
.speedMenu{
position:absolute; right:0; bottom:calc(100% + 10px);
min-width:180px; padding:8px;
border-radius:7px; border:1px solid rgba(255,255,255,.12);
background:rgba(18,20,26,.94);
box-shadow:0 26px 70px rgba(0,0,0,.70);
backdrop-filter:blur(16px);
border-radius:var(--r); border:1px solid rgba(140,160,210,.10);
background:rgba(18,21,30,.95);
box-shadow:var(--shadow);
display:none; z-index:30;
transform:translateY(8px) scale(.96); opacity:0;
transition:transform .18s cubic-bezier(.175,.885,.32,1.275), opacity .15s ease;
opacity:0;
transform:scale(.95) translateY(4px);
transition:opacity .15s ease, transform .2s var(--ease-bounce);
}
.speedMenu.show{display:block; transform:translateY(0) scale(1); opacity:1;}
.speedItem{padding:10px 10px; border-radius:6px; cursor:pointer; user-select:none; font-family:var(--mono); font-size:14px; color:rgba(246,248,255,.92); letter-spacing:.10px; display:flex; align-items:center; justify-content:space-between; gap:10px; transition:all .12s ease;}
.speedItem:hover{background:rgba(255,255,255,.06); transform:translateX(3px);}
.speedItem .dot{width:8px; height:8px; border-radius:999px; background:rgba(255,255,255,.08); border:1px solid rgba(255,255,255,.12); flex:0 0 auto; transition:all .15s ease;}
.speedItem.active .dot{background:radial-gradient(circle at 30% 30%, rgba(255,255,255,.92), rgba(100,180,255,.55)); box-shadow:0 0 0 3px rgba(100,180,255,.10); border-color:rgba(100,180,255,.24);}
.speedMenu.show{display:block; opacity:1; transform:scale(1) translateY(0);}
.speedItem{padding:10px 10px; border-radius:var(--r3); cursor:pointer; user-select:none; font-family:var(--mono); font-size:14px; color:var(--text); letter-spacing:.02em; display:flex; align-items:center; justify-content:space-between; gap:10px; transition:all .2s var(--ease-bounce);}
.speedItem:hover{background:var(--surfaceHover); padding-left:14px;}
.speedItem:active{transform:scale(.97); transition-duration:.08s;}
.speedItem .dot{width:8px; height:8px; border-radius:999px; background:rgba(140,165,220,.06); border:none; flex:0 0 auto; transition:all .2s var(--ease-bounce);}
.speedItem:hover .dot{transform:scale(1.3);}
.speedItem.active .dot{background:rgba(136,164,196,.65);}
.speedItem.active:hover .dot{background:rgba(136,164,196,.80); box-shadow:0 0 6px rgba(136,164,196,.25);}
.subsMenuItem:focus-visible{background:var(--surfaceHover); padding-left:16px; outline:none;}
.speedItem:focus-visible{background:var(--surfaceHover); padding-left:14px; outline:none;}
.dropItem:focus-visible{background:var(--surfaceHover); padding-left:16px; outline:none;}