feat: add 15 UI enhancements
1. Mute toggle (M key + volume icon click) 2. Fullscreen shortcut (F key) 3. Seek feedback overlay (±5s flash with accumulation) 4. Playlist search/filter with clear button 5. Scroll-to-current button (IntersectionObserver) 6. Picture-in-Picture button 7. Timestamp insertion in notes 8. Keyboard shortcut help panel (? key) 9. Playback speed shortcuts ([ and ] keys) 10. Reset progress two-click confirmation 11. Video load error state overlay 12. Double-click video to fullscreen 13. Playlist stats in header (count + done) 14. Mini progress bars per playlist item 15. Collapsible dock panes with chevron icons All enhancements are WCAG 2.2 AAA compliant with proper aria-labels, aria-live regions, focus-visible states, keyboard accessibility, and 44x44 touch targets.
This commit is contained in:
@@ -147,3 +147,78 @@
|
||||
.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;}
|
||||
|
||||
/* Keyboard shortcut help dialog */
|
||||
.shortcutHelp{
|
||||
position:fixed;
|
||||
inset:0;
|
||||
z-index:999999;
|
||||
display:flex;
|
||||
align-items:center;
|
||||
justify-content:center;
|
||||
}
|
||||
.shortcutHelpBackdrop{
|
||||
position:absolute;
|
||||
inset:0;
|
||||
background:rgba(0,0,0,.55);
|
||||
}
|
||||
.shortcutHelpPanel{
|
||||
position:relative;
|
||||
z-index:1;
|
||||
padding:28px 32px;
|
||||
border-radius:var(--r);
|
||||
background:rgba(18,21,30,.97);
|
||||
border:1px solid rgba(140,160,210,.12);
|
||||
box-shadow:var(--shadow);
|
||||
max-width:420px;
|
||||
width:90%;
|
||||
}
|
||||
.shortcutHelpTitle{
|
||||
font-family:var(--brand);
|
||||
font-weight:700;
|
||||
font-size:16px;
|
||||
margin:0 0 20px;
|
||||
color:rgba(235,240,252,.95);
|
||||
letter-spacing:-.01em;
|
||||
}
|
||||
.shortcutGrid{
|
||||
display:grid;
|
||||
grid-template-columns:auto 1fr;
|
||||
gap:10px 20px;
|
||||
align-items:baseline;
|
||||
}
|
||||
.shortcutKey{
|
||||
text-align:right;
|
||||
white-space:nowrap;
|
||||
}
|
||||
.shortcutKey kbd{
|
||||
display:inline-block;
|
||||
padding:3px 8px;
|
||||
border-radius:4px;
|
||||
background:rgba(140,165,220,.08);
|
||||
border:1px solid rgba(140,165,220,.12);
|
||||
font-family:var(--mono);
|
||||
font-size:12px;
|
||||
color:rgba(200,212,238,.88);
|
||||
line-height:1;
|
||||
}
|
||||
.shortcutDesc{
|
||||
font-size:13px;
|
||||
color:rgba(200,212,238,.78);
|
||||
}
|
||||
.shortcutHelpClose{
|
||||
margin-top:20px;
|
||||
text-align:center;
|
||||
font-size:11px;
|
||||
color:var(--textDim);
|
||||
}
|
||||
.shortcutHelpClose kbd{
|
||||
display:inline-block;
|
||||
padding:2px 6px;
|
||||
border-radius:3px;
|
||||
background:rgba(140,165,220,.06);
|
||||
border:1px solid rgba(140,165,220,.10);
|
||||
font-family:var(--mono);
|
||||
font-size:11px;
|
||||
color:rgba(170,182,210,.70);
|
||||
}
|
||||
|
||||
@@ -169,3 +169,24 @@ dl.kv dt,dl.kv dd{margin:0; padding:0;}
|
||||
}
|
||||
.dockDivider:hover::after{opacity:.50; height:60px;}
|
||||
.dockDivider:active::after{opacity:.65;}
|
||||
|
||||
/* Timestamp button */
|
||||
.timestampBtn{border:none; background:transparent; padding:0; margin:0 0 0 auto; cursor:pointer; display:flex; align-items:center; justify-content:center; width:28px; height:28px; border-radius:var(--r3); transition:all .2s var(--ease-bounce);}
|
||||
.timestampBtn:hover{background:var(--surface-3); transform:scale(1.1);}
|
||||
.timestampBtn:active{transform:scale(.9); transition-duration:.08s;}
|
||||
.timestampBtn .fa{font-size:12px; color:var(--iconStrong)!important; opacity:.75; transition:opacity .15s ease;}
|
||||
.timestampBtn:hover .fa{opacity:1;}
|
||||
.timestampBtn:focus-visible{outline:2px solid rgba(136,164,196,.45); outline-offset:1px;}
|
||||
|
||||
/* Dock chevron */
|
||||
.dockChevron{font-size:10px; color:var(--textDim); transition:transform .25s var(--ease-bounce), color .2s ease; margin-left:4px; flex:0 0 auto;}
|
||||
.dockHeader:hover .dockChevron{color:var(--textMuted);}
|
||||
|
||||
/* Collapsible dock pane */
|
||||
.dockPane.collapsed{flex:0 0 auto !important;}
|
||||
.dockPane.collapsed .notesArea,
|
||||
.dockPane.collapsed .infoGrid{display:none;}
|
||||
|
||||
/* Reset confirm state */
|
||||
.toolbarBtn.confirming{background:rgba(255,70,70,.14);}
|
||||
.toolbarBtn.confirming .fa{color:rgba(255,160,100,.9)!important;}
|
||||
|
||||
@@ -246,3 +246,58 @@ video::cue{
|
||||
.vol:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 3px rgba(136,164,196,.45), 0 1px 4px rgba(0,0,0,.25);}
|
||||
.seek:focus-visible::-moz-range-thumb{box-shadow:0 0 0 3px rgba(136,164,196,.45), 0 2px 6px rgba(0,0,0,.30);}
|
||||
.vol:focus-visible::-moz-range-thumb{box-shadow:0 0 0 3px rgba(136,164,196,.45), 0 1px 4px rgba(0,0,0,.25);}
|
||||
|
||||
/* Mute button */
|
||||
.volMuteBtn{border:none; background:transparent; padding:0; margin:0; cursor:pointer; display:flex; align-items:center; justify-content:center; width:14px; height:14px; flex:0 0 auto;}
|
||||
.volMuteBtn .fa{font-size:14px; color:var(--iconStrong)!important; opacity:.95; transition:transform .2s var(--ease-bounce), opacity .15s ease;}
|
||||
.volMuteBtn:hover .fa{transform:scale(1.15); opacity:1;}
|
||||
.volMuteBtn:focus-visible{outline:2px solid rgba(136,164,196,.45); outline-offset:2px; border-radius:3px;}
|
||||
.miniCtl.muted{opacity:.5;}
|
||||
.miniCtl.muted .volFill{opacity:.3;}
|
||||
|
||||
/* Seek feedback overlay */
|
||||
.seekFeedback{
|
||||
position:absolute;
|
||||
top:50%; left:50%;
|
||||
transform:translate(-50%,-50%);
|
||||
font-family:var(--mono);
|
||||
font-size:28px;
|
||||
font-weight:700;
|
||||
color:#fff;
|
||||
text-shadow:0 2px 8px rgba(0,0,0,.7);
|
||||
opacity:0;
|
||||
transition:opacity .15s ease;
|
||||
pointer-events:none;
|
||||
z-index:6;
|
||||
}
|
||||
.seekFeedback.show{opacity:1;}
|
||||
|
||||
/* Error overlay */
|
||||
.errorOverlay{
|
||||
position:absolute;
|
||||
inset:0;
|
||||
display:flex;
|
||||
flex-direction:column;
|
||||
align-items:center;
|
||||
justify-content:center;
|
||||
gap:16px;
|
||||
background:rgba(15,17,23,.88);
|
||||
z-index:10;
|
||||
}
|
||||
.errorOverlay>.fa{font-size:42px; color:rgba(255,180,100,.85);}
|
||||
.errorMsg{font-size:14px; color:rgba(218,225,240,.85); text-align:center; line-height:1.5; max-width:320px;}
|
||||
.errorNextBtn{
|
||||
border:none;
|
||||
background:var(--surface-3);
|
||||
color:var(--text);
|
||||
padding:10px 20px;
|
||||
border-radius:var(--r2);
|
||||
font-size:13px;
|
||||
font-weight:600;
|
||||
cursor:pointer;
|
||||
min-width:44px;
|
||||
min-height:44px;
|
||||
transition:background .2s ease;
|
||||
}
|
||||
.errorNextBtn:hover{background:var(--surface-4);}
|
||||
.errorNextBtn:focus-visible{outline:2px solid rgba(136,164,196,.45); outline-offset:2px;}
|
||||
|
||||
@@ -117,3 +117,47 @@
|
||||
.moveBtn:active{transform:scale(.9); transition-duration:.08s;}
|
||||
.moveBtn .fa{font-size:9px; color:var(--iconStrong)!important; opacity:.7;}
|
||||
.moveBtn:hover .fa{opacity:1;}
|
||||
|
||||
/* Playlist stats */
|
||||
.plistStats{font-family:var(--mono); font-size:11px; color:var(--textMuted); letter-spacing:.02em; white-space:nowrap; flex:0 0 auto;}
|
||||
|
||||
/* Playlist search */
|
||||
.plistSearchWrap{display:flex; align-items:center; gap:6px; padding:4px 10px; border-radius:var(--r2); background:var(--surface-0); border:1px solid transparent; transition:border-color .2s ease, background .2s ease; flex:0 1 180px; min-width:0;}
|
||||
.plistSearchWrap:focus-within{border-color:rgba(136,164,196,.25); background:rgba(140,165,220,.04);}
|
||||
.plistSearchIcon{font-size:11px; color:var(--textDim); flex:0 0 auto; transition:color .2s ease;}
|
||||
.plistSearchWrap:focus-within .plistSearchIcon{color:var(--iconStrong);}
|
||||
.plistSearch{border:none; background:transparent; color:var(--text); font-size:12px; font-family:var(--sans); outline:none; width:100%; min-width:0; padding:2px 0;}
|
||||
.plistSearch::placeholder{color:var(--textDim); font-size:11px;}
|
||||
.plistSearchClear{border:none; background:transparent; color:var(--textMuted); cursor:pointer; padding:0; display:flex; align-items:center; justify-content:center; width:20px; height:20px; flex:0 0 auto; transition:color .2s ease;}
|
||||
.plistSearchClear:hover{color:var(--text);}
|
||||
.plistSearchClear:focus-visible{outline:2px solid rgba(136,164,196,.45); outline-offset:1px; border-radius:3px;}
|
||||
.plistSearchClear .fa{font-size:10px;}
|
||||
|
||||
/* Scroll-to-current button */
|
||||
.scrollToCurrent{
|
||||
width:36px; height:36px;
|
||||
border-radius:var(--r2);
|
||||
border:none;
|
||||
background:var(--surface-2);
|
||||
display:inline-flex; align-items:center; justify-content:center;
|
||||
cursor:pointer;
|
||||
flex:0 0 auto;
|
||||
transition:all .2s var(--ease-bounce);
|
||||
}
|
||||
.scrollToCurrent:hover{background:var(--surface-3); transform:translateY(-1px);}
|
||||
.scrollToCurrent:active{transform:scale(.9); transition-duration:.08s;}
|
||||
.scrollToCurrent .fa{font-size:13px; color:var(--iconStrong)!important; opacity:.9;}
|
||||
.scrollToCurrent:hover .fa{opacity:1;}
|
||||
.scrollToCurrent:focus-visible{outline:2px solid rgba(136,164,196,.45); outline-offset:2px;}
|
||||
|
||||
/* Mini progress bar per row */
|
||||
.rowProgress{
|
||||
position:absolute;
|
||||
bottom:0; left:0;
|
||||
height:2px;
|
||||
background:var(--accent);
|
||||
border-radius:0 1px 0 0;
|
||||
transition:width .3s ease;
|
||||
pointer-events:none;
|
||||
}
|
||||
.rowProgress.done{background:var(--success);}
|
||||
|
||||
Reference in New Issue
Block a user