Add hamburger menu to house Song List and Waveform Styles
This commit is contained in:
1 parent
565585c95b
commit
5e98b9fca6
3 files changed
+118
-59
No files matched your search
+33
-24
@@ -160,22 +160,11 @@ audio[controls] { width: 100%; outline: 0; }
|
||||
.waveform { width: 100%; display: block; border-radius: 8px; }
|
||||
.waveform[hidden] { display: none; } /* [hidden] must beat display:block */
|
||||
|
||||
.waveform-picker { position: absolute; top: 6px; right: 6px; z-index: 2; }
|
||||
.waveform-picker summary {
|
||||
list-style: none; padding: 4px 12px;
|
||||
background: rgba(0, 0, 0, 0.55); color: #fff;
|
||||
font-variant: small-caps; font-size: 0.8rem;
|
||||
border: 1px solid rgba(255, 255, 255, 0.35); border-radius: 999px;
|
||||
cursor: pointer; backdrop-filter: blur(4px);
|
||||
transition: background .15s ease;
|
||||
}
|
||||
.waveform-picker summary::-webkit-details-marker { display: none; }
|
||||
.waveform-picker summary:hover, .waveform-picker summary:focus { background: rgba(0, 0, 0, 0.8); outline: 0; }
|
||||
.waveform-picker[open] summary { background: var(--accent); color: var(--accent-text); border-color: var(--accent); }
|
||||
|
||||
.waveform-picker[open] {
|
||||
.waveform-picker {
|
||||
position: fixed; top: 64px; right: 16px; z-index: 30;
|
||||
display: flex; flex-direction: column; align-items: flex-end; gap: 6px;
|
||||
}
|
||||
.waveform-picker[hidden] { display: none; }
|
||||
.waveform-picker fieldset {
|
||||
margin: 0; padding: 8px 10px;
|
||||
background: rgba(0, 0, 0, 0.85); color: #fff;
|
||||
@@ -266,15 +255,35 @@ audio[controls] { width: 100%; outline: 0; }
|
||||
width: 0; height: 0; display: none;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------- history panel */
|
||||
.history-toggle {
|
||||
position: fixed; top: 16px; right: 16px; z-index: 30;
|
||||
padding: 8px 14px;
|
||||
/* ----------------------------------------------------------------- menu */
|
||||
.menu-wrap { position: fixed; top: 16px; right: 16px; z-index: 30; }
|
||||
.menu-toggle {
|
||||
width: 40px; height: 40px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
background: var(--accent); color: var(--accent-text);
|
||||
font-variant: small-caps; border: none; border-radius: 8px; cursor: pointer;
|
||||
font-size: 1.1rem; line-height: 1;
|
||||
border: none; border-radius: 8px; cursor: pointer;
|
||||
}
|
||||
.history-toggle:hover, .history-toggle:focus { background: var(--accent-hover); outline: 0; }
|
||||
.menu-toggle:hover, .menu-toggle:focus { background: var(--accent-hover); outline: 0; }
|
||||
|
||||
.menu-list {
|
||||
position: absolute; top: calc(100% + 6px); right: 0; z-index: 30;
|
||||
min-width: 170px; margin: 0; padding: 6px;
|
||||
list-style: none;
|
||||
background: rgba(0, 0, 0, 0.85); color: #fff;
|
||||
border: 1px solid rgba(255, 255, 255, 0.35); border-radius: 10px;
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
.menu-list[hidden] { display: none; }
|
||||
.menu-item {
|
||||
display: block; width: 100%; text-align: left;
|
||||
padding: 8px 10px; margin: 0;
|
||||
background: none; border: none; border-radius: 6px;
|
||||
color: inherit; font: inherit; font-size: 0.85rem; cursor: pointer;
|
||||
}
|
||||
.menu-item:hover, .menu-item:focus-visible { background: rgba(255, 255, 255, 0.15); outline: 0; }
|
||||
|
||||
/* ----------------------------------------------------- history panel */
|
||||
.history {
|
||||
position: fixed; top: 0; right: 0; height: 100%;
|
||||
width: min(90vw, 420px); padding: 64px 16px 16px;
|
||||
@@ -308,11 +317,11 @@ audio[controls] { width: 100%; outline: 0; }
|
||||
.history { width: min(96vw, 420px); }
|
||||
|
||||
/* -webkit-touch-callout is a no-op everywhere except iOS WebKit, so this
|
||||
@supports check targets iOS phones without any JS/UA sniffing. Picker is
|
||||
hidden there, so give the art a fake ambient glow (no audio analysis)
|
||||
in its place. */
|
||||
@supports check targets iOS phones without any JS/UA sniffing. The menu
|
||||
item is hidden there, so give the art a fake ambient glow (no audio
|
||||
analysis) in its place. */
|
||||
@supports (-webkit-touch-callout: none) {
|
||||
.waveform-picker { display: none; }
|
||||
#menu-waveform { display: none; }
|
||||
.album-art { animation: art-glow-pulse 3.2s ease-in-out infinite; }
|
||||
}
|
||||
}
|
||||
|
||||
+44
-7
@@ -39,14 +39,17 @@
|
||||
lyricsLines: $('lyrics-lines'),
|
||||
lyricsSync: $('lyrics-sync'),
|
||||
lyricsOffset: $('lyrics-offset'),
|
||||
historyToggle:$('history-toggle'),
|
||||
historyBody: $('history-body'),
|
||||
history: $('history'),
|
||||
listeners: $('listeners'),
|
||||
canvas: $('tint-canvas'),
|
||||
waveform: $('waveform'),
|
||||
artRing: $('art-ring'),
|
||||
wavePicker: $('waveform-picker')
|
||||
wavePicker: $('waveform-picker'),
|
||||
menuToggle: $('menu-toggle'),
|
||||
menuList: $('menu-list'),
|
||||
menuHistory: $('menu-history'),
|
||||
menuWaveform: $('menu-waveform')
|
||||
};
|
||||
|
||||
var ICON = {
|
||||
@@ -768,13 +771,47 @@
|
||||
while (el.historyBody.children.length > 100) el.historyBody.removeChild(el.historyBody.lastChild);
|
||||
}
|
||||
|
||||
if (el.historyToggle && el.history) {
|
||||
el.historyToggle.addEventListener('click', function () {
|
||||
var open = el.history.classList.toggle('open');
|
||||
el.historyToggle.classList.toggle('open', open);
|
||||
el.historyToggle.textContent = open ? 'Close' : 'Song list';
|
||||
/* --------------------------------------------------------- menu / popovers */
|
||||
function closeMenu() {
|
||||
if (!el.menuList) return;
|
||||
el.menuList.hidden = true;
|
||||
if (el.menuToggle) el.menuToggle.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
|
||||
if (el.menuToggle && el.menuList) {
|
||||
el.menuToggle.addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
var open = el.menuList.hidden;
|
||||
el.menuList.hidden = !open;
|
||||
el.menuToggle.setAttribute('aria-expanded', open ? 'true' : 'false');
|
||||
});
|
||||
}
|
||||
if (el.menuHistory && el.history) {
|
||||
el.menuHistory.addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
el.history.classList.toggle('open');
|
||||
closeMenu();
|
||||
});
|
||||
}
|
||||
if (el.menuWaveform && el.wavePicker) {
|
||||
el.menuWaveform.addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
el.wavePicker.hidden = !el.wavePicker.hidden;
|
||||
closeMenu();
|
||||
});
|
||||
}
|
||||
// Clicking anywhere outside the menu / history pane / waveform picker
|
||||
// closes whichever of them is open (the triggers above stop propagation
|
||||
// so this only fires for genuine outside clicks).
|
||||
document.addEventListener('click', function (e) {
|
||||
closeMenu();
|
||||
if (el.history && el.history.classList.contains('open') && !el.history.contains(e.target)) {
|
||||
el.history.classList.remove('open');
|
||||
}
|
||||
if (el.wavePicker && !el.wavePicker.hidden && !el.wavePicker.contains(e.target)) {
|
||||
el.wavePicker.hidden = true;
|
||||
}
|
||||
});
|
||||
|
||||
/* ----------------------------------------------------------- listeners */
|
||||
function updateListeners(data) {
|
||||
|
||||
@@ -58,33 +58,6 @@ $showArtRing = $waveActive && in_array('circular', $waveTypes, true) && $rich;
|
||||
<?php if ($waveActive): ?>
|
||||
<div class="waveform-wrap">
|
||||
<canvas id="waveform" class="waveform" style="height:<?= (int) cfg('waveform.height') ?>px" hidden aria-hidden="true"></canvas>
|
||||
<?php if ($showWavePicker): ?>
|
||||
<details class="waveform-picker" id="waveform-picker">
|
||||
<summary>Style</summary>
|
||||
<fieldset>
|
||||
<legend>Below art</legend>
|
||||
<?php
|
||||
$stripLabels = ['none' => 'None', 'bars' => 'Bars', 'line' => 'Line', 'vu' => 'VU',
|
||||
'spectrum' => 'Spectrum', 'spectrum-mirror' => 'Spectrum (mirror)', 'blob' => 'Blob'];
|
||||
foreach ($stripLabels as $val => $label):
|
||||
if ($val !== 'none' && !in_array($val, $waveTypes, true)) continue;
|
||||
?>
|
||||
<label><input type="radio" name="wave-strip" value="<?= e($val) ?>"/> <?= e($label) ?></label>
|
||||
<?php endforeach; ?>
|
||||
</fieldset>
|
||||
<?php if ($showArtRing || in_array('glow', $waveTypes, true)): ?>
|
||||
<fieldset>
|
||||
<legend>On art</legend>
|
||||
<?php if ($showArtRing): ?>
|
||||
<label><input type="checkbox" id="wave-circular"/> Ring</label>
|
||||
<?php endif; ?>
|
||||
<?php if (in_array('glow', $waveTypes, true)): ?>
|
||||
<label><input type="checkbox" id="wave-glow"/> Glow</label>
|
||||
<?php endif; ?>
|
||||
</fieldset>
|
||||
<?php endif; ?>
|
||||
</details>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -112,8 +85,48 @@ $showArtRing = $waveActive && in_array('circular', $waveTypes, true) && $rich;
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<?php if ($showHistory || $showWavePicker): ?>
|
||||
<div class="menu-wrap" id="menu-wrap">
|
||||
<button id="menu-toggle" class="menu-toggle" type="button" aria-haspopup="true" aria-expanded="false" aria-label="Menu">☰</button>
|
||||
<ul id="menu-list" class="menu-list" hidden>
|
||||
<?php if ($showHistory): ?>
|
||||
<li><button type="button" id="menu-history" class="menu-item">Song List</button></li>
|
||||
<?php endif; ?>
|
||||
<?php if ($showWavePicker): ?>
|
||||
<li><button type="button" id="menu-waveform" class="menu-item">Waveform Styles</button></li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($showWavePicker): ?>
|
||||
<div class="waveform-picker" id="waveform-picker" hidden>
|
||||
<fieldset>
|
||||
<legend>Below art</legend>
|
||||
<?php
|
||||
$stripLabels = ['none' => 'None', 'bars' => 'Bars', 'line' => 'Line', 'vu' => 'VU',
|
||||
'spectrum' => 'Spectrum', 'spectrum-mirror' => 'Spectrum (mirror)', 'blob' => 'Blob'];
|
||||
foreach ($stripLabels as $val => $label):
|
||||
if ($val !== 'none' && !in_array($val, $waveTypes, true)) continue;
|
||||
?>
|
||||
<label><input type="radio" name="wave-strip" value="<?= e($val) ?>"/> <?= e($label) ?></label>
|
||||
<?php endforeach; ?>
|
||||
</fieldset>
|
||||
<?php if ($showArtRing || in_array('glow', $waveTypes, true)): ?>
|
||||
<fieldset>
|
||||
<legend>On art</legend>
|
||||
<?php if ($showArtRing): ?>
|
||||
<label><input type="checkbox" id="wave-circular"/> Ring</label>
|
||||
<?php endif; ?>
|
||||
<?php if (in_array('glow', $waveTypes, true)): ?>
|
||||
<label><input type="checkbox" id="wave-glow"/> Glow</label>
|
||||
<?php endif; ?>
|
||||
</fieldset>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($showHistory): ?>
|
||||
<button id="history-toggle" class="history-toggle" type="button">Song list</button>
|
||||
<aside id="history" class="history">
|
||||
<table class="history-table">
|
||||
<thead><tr><th>Time</th><th>Artist</th><th>Title</th></tr></thead>
|
||||
|
||||
Reference in new issue
Block a user