add keyboard navigation visual feedback (fix #5)

add pause/play hotkey using spacebar
fix small visual bug with loading video
This commit is contained in:
torcado 2023-10-20 17:42:50 -04:00
parent 2dbd39df98
commit 20f463e36f

View file

@ -83,6 +83,21 @@
font-family: 'Segoe UI Symbol', sans-serif; font-family: 'Segoe UI Symbol', sans-serif;
} }
a[href]:not([tabindex='-1']):focus-visible,
area[href]:not([tabindex='-1']):focus-visible,
input:not([disabled]):not([tabindex='-1']):focus-visible,
select:not([disabled]):not([tabindex='-1']):focus-visible,
textarea:not([disabled]):not([tabindex='-1']):focus-visible,
button:not([disabled]):not([tabindex='-1']):focus-visible,
iframe:not([tabindex='-1']):focus-visible,
[tabindex]:not([tabindex='-1']):focus-visible,
[contentEditable=true]:not([tabindex='-1']):focus-visible
{
outline: 2px solid rgb(83, 186, 255);
outline-offset: 2px;
border-radius: 2px;
}
/*** title ***/ /*** title ***/
#titleContainer { #titleContainer {
@ -548,7 +563,7 @@
align-items: center; align-items: center;
} }
.track button { .track .playButton {
margin-right: 12px; margin-right: 12px;
width: 26px; width: 26px;
height: 26px; height: 26px;
@ -562,7 +577,12 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.track button:not(.loading, .error, .locked):after { /* .track .playButton:focus-visible {
outline: 2px solid rgb(83, 186, 255);
outline-offset: 2px;
} */
.track .playButton:not(.loading, .error, .locked):after {
content: ''; content: '';
display: block; display: block;
width: 0px; width: 0px;
@ -575,7 +595,7 @@
position: relative; position: relative;
left: 1px; left: 1px;
} }
.track button:not(.loading, .error, .locked).pause:after { .track .playButton:not(.loading, .error, .locked).pause:after {
content: ''; content: '';
border: 0; border: 0;
border-left: 4px solid var(--secondaryColor); border-left: 4px solid var(--secondaryColor);
@ -587,7 +607,7 @@
left: 0; left: 0;
} }
.track button.loading.loading:after { .track .playButton.loading.loading:after {
content: "\1f506"; content: "\1f506";
color: var(--secondaryColor); color: var(--secondaryColor);
font-family: 'icons' !important; font-family: 'icons' !important;
@ -600,15 +620,15 @@
font-size: 20px; font-size: 20px;
animation: pulse 1.0s infinite; animation: pulse 1.0s infinite;
} }
.track button.error { .track .playButton.error {
opacity: 0.5; opacity: 0.5;
cursor: default; cursor: default;
} }
.track button.locked { .track .playButton.locked {
cursor: default; cursor: default;
} }
.track button.locked:after { .track .playButton.locked:after {
content: "\1f512"; content: "\1f512";
color: var(--secondaryColor); color: var(--secondaryColor);
font-family: 'icons' !important; font-family: 'icons' !important;
@ -621,7 +641,7 @@
font-size: 20px; font-size: 20px;
} }
.track.looped button:before { .track.looped .playButton:before {
content: attr(loopcount); content: attr(loopcount);
display: block; display: block;
width: 15px; width: 15px;
@ -638,7 +658,7 @@
font-size: 10px; font-size: 10px;
text-align: center; text-align: center;
} }
.track.active.looped button:before { .track.active.looped .playButton:before {
border-color: var(--secondaryColor);; border-color: var(--secondaryColor);;
} }
@ -668,6 +688,7 @@
.track .toggleInfo { .track .toggleInfo {
margin-left: 8px; margin-left: 8px;
margin-right: 4px; margin-right: 4px;
border-radius: 2px;
cursor: pointer; cursor: pointer;
color: var(--primaryAltTextColor); color: var(--primaryAltTextColor);
} }
@ -681,6 +702,7 @@
} }
.track .infoContainer:not(.active) { .track .infoContainer:not(.active) {
height: 0px !important; height: 0px !important;
overflow: hidden;
} }
.track .info { .track .info {
@ -787,6 +809,7 @@
</body> </body>
<script> <script>
let mediaDir = 'media/'; let mediaDir = 'media/';
let mainContainerEl = document.getElementById('mainContainer');
let playerEl = document.getElementById('player'); let playerEl = document.getElementById('player');
let tracksEl = document.getElementById('tracks'); let tracksEl = document.getElementById('tracks');
let descriptionEl = document.getElementById('description'); let descriptionEl = document.getElementById('description');
@ -851,16 +874,16 @@
if(theme.previewStripeColor2) rootEl.style.setProperty('--previewStripeColor2', theme.previewStripeColor2); if(theme.previewStripeColor2) rootEl.style.setProperty('--previewStripeColor2', theme.previewStripeColor2);
if(theme.linkColor) rootEl.style.setProperty('--linkColor', theme.linkColor); if(theme.linkColor) rootEl.style.setProperty('--linkColor', theme.linkColor);
if(theme.layoutStyle){ if(theme.layoutStyle){
document.getElementById('mainContainer').classList.remove('vertical', 'horizontal'); mainContainerEl.classList.remove('vertical', 'horizontal');
document.getElementById('mainContainer').classList.add(theme.layoutStyle); mainContainerEl.classList.add(theme.layoutStyle);
} }
if(theme.infoStyle){ if(theme.infoStyle){
document.getElementById('mainContainer').classList.remove('info-none', 'info-overlaid', 'info-below', 'info-overlaid-toggle'); mainContainerEl.classList.remove('info-none', 'info-overlaid', 'info-below', 'info-overlaid-toggle');
document.getElementById('mainContainer').classList.add('info-' + theme.infoStyle); mainContainerEl.classList.add('info-' + theme.infoStyle);
} }
if(theme.titleStyle){ if(theme.titleStyle){
document.getElementById('mainContainer').classList.remove('title-none', 'title-span'); mainContainerEl.classList.remove('title-none', 'title-span');
document.getElementById('mainContainer').classList.add('title-' + theme.titleStyle); mainContainerEl.classList.add('title-' + theme.titleStyle);
} }
if(theme.contentWidth) document.getElementById('contentContainer').style.maxWidth = theme.contentWidth + 'px'; if(theme.contentWidth) document.getElementById('contentContainer').style.maxWidth = theme.contentWidth + 'px';
if(theme.nativePlayer){ if(theme.nativePlayer){
@ -989,17 +1012,17 @@
tracksEl.insertAdjacentHTML('beforeend', tracksEl.insertAdjacentHTML('beforeend',
`<div class="track ${entry.locked ? 'locked' : ''}" ${entry.locked ? 'title="This file is available in the full download"' : ''}> `<div class="track ${entry.locked ? 'locked' : ''}" ${entry.locked ? 'title="This file is available in the full download"' : ''}>
<div class="main"> <div class="main">
<button class="${entry.locked ? 'locked' : 'loading'}"></button> <button class="playButton ${entry.locked ? 'locked' : 'loading'}"></button>
<div class="details"> <div class="details">
<div class="number">${i+1}. </div> <div class="number">${i+1}. </div>
<div class="title">${entry.title}</div> <div class="title">${entry.title}</div>
<div class="duration"></div> <div class="duration"></div>
<div class="spacer"></div> <div class="spacer"></div>
${entry.info ? `<div class="toggleInfo icon-info"></div>` : ''} ${entry.info ? `<button class="toggleInfo icon-info"></button>` : ''}
</div> </div>
</div> </div>
${entry.info ? ` ${entry.info ? `
<div class="infoContainer"> <div class="infoContainer" inert>
<div class="info"> <div class="info">
${entry.info} ${entry.info}
</div> </div>
@ -1020,6 +1043,11 @@
trackEl.querySelector('.toggleInfo').addEventListener('click', (e) => { trackEl.querySelector('.toggleInfo').addEventListener('click', (e) => {
infoContainerEl.style.height = trackEl.querySelector('.info').clientHeight + 'px'; infoContainerEl.style.height = trackEl.querySelector('.info').clientHeight + 'px';
entry.infoToggled = infoContainerEl.classList.toggle('active'); entry.infoToggled = infoContainerEl.classList.toggle('active');
if(entry.info && entry.infoToggled){
infoContainerEl.removeAttribute("inert");
} else {
infoContainerEl.setAttribute("inert", "");
}
if(config.theme.infoStyle === 'overlaid-toggle'){ if(config.theme.infoStyle === 'overlaid-toggle'){
if(entry.info && entry.infoToggled){ if(entry.info && entry.infoToggled){
mediaInfoEl.innerHTML = entry.info; mediaInfoEl.innerHTML = entry.info;
@ -1313,6 +1341,13 @@
} }
} }
document.addEventListener('keydown', e => {
if(e.key === " " && e.target === document.body){
playEntry(currentEntry);
e.preventDefault();
}
})
let scrubberDragged = false; let scrubberDragged = false;
scrubberTrackContainerEl.addEventListener('pointerdown', e => { scrubberTrackContainerEl.addEventListener('pointerdown', e => {
scrubberDragged = true; scrubberDragged = true;
@ -1600,6 +1635,7 @@
if(entry.type === 'video'){ if(entry.type === 'video'){
mediaVideoEl.src = entry.file; mediaVideoEl.src = entry.file;
mediaVideoEl.classList.add('active'); mediaVideoEl.classList.add('active');
mediaImageEl.style.visibility = 'hidden';
playerEl.classList.add('video'); playerEl.classList.add('video');
if(config.theme.nativePlayer){ if(config.theme.nativePlayer){