website v3
This commit is contained in:
parent
9a0c184515
commit
1f6b5aef3d
@ -4,55 +4,197 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<section class="section" id="np-section" hidden>
|
<div class="music">
|
||||||
<h2 class="label">now playing</h2>
|
<button
|
||||||
<div class="np" id="np">
|
class="music__trigger"
|
||||||
<div class="np__body">
|
type="button"
|
||||||
<img class="np__art np__art--none" id="np-art" alt="" width="64" height="64" decoding="async" />
|
data-music-open
|
||||||
<div class="np__meta">
|
aria-haspopup="dialog"
|
||||||
<div class="np__title" id="np-title">—</div>
|
data-umami-event="music-open"
|
||||||
<div class="np__artist" id="np-artist">—</div>
|
hidden
|
||||||
<div class="np__foot">
|
>
|
||||||
<span class="np__tx" aria-hidden="true">
|
<span class="music__note" aria-hidden="true">♫</span>
|
||||||
<svg viewBox="0 0 24 24" width="11" height="11" fill="currentColor"
|
<span class="music__label" id="music-label">now playing</span>
|
||||||
><path d="M6 5h2v14H6zM20 5v14L9 12z"></path></svg
|
<span class="music__arw" aria-hidden="true">→</span>
|
||||||
>
|
</button>
|
||||||
<svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor"
|
|
||||||
><path d="M6 4l14 8-14 8z"></path></svg
|
<dialog class="music-wall" data-music-dialog aria-label="music">
|
||||||
>
|
<div class="music-wall__bar">
|
||||||
<svg viewBox="0 0 24 24" width="11" height="11" fill="currentColor"
|
<span class="music-wall__title">music</span>
|
||||||
><path d="M16 5h2v14h-2zM4 5l11 7-11 7z"></path></svg
|
<button
|
||||||
>
|
class="music-wall__close"
|
||||||
</span>
|
type="button"
|
||||||
<span class="np__dur" id="np-dur"></span>
|
data-music-close
|
||||||
<span class="np__ago" id="np-ago"></span>
|
aria-label="close"
|
||||||
<a class="np__src" id="np-src" href="#" target="_blank" rel="noopener">
|
autofocus>✕</button>
|
||||||
<svg class="np__logo" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"
|
</div>
|
||||||
><path
|
|
||||||
d="M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.66 0 12 0zm5.521 17.34c-.24.359-.66.48-1.021.24-2.82-1.74-6.36-2.101-10.561-1.141-.418.122-.779-.179-.899-.539-.12-.421.18-.78.54-.9 4.56-1.021 8.52-.6 11.64 1.32.42.18.479.659.301 1.02zm1.44-3.3c-.301.42-.841.6-1.262.3-3.239-1.98-8.159-2.58-11.939-1.38-.479.12-1.02-.12-1.14-.6-.12-.48.12-1.021.6-1.141C9.6 9.9 15 10.561 18.72 12.84c.361.181.54.78.241 1.2zm.12-3.36C15.24 8.4 8.82 8.16 5.16 9.301c-.6.179-1.2-.16-1.38-.72-.18-.601.18-1.2.72-1.381 4.26-1.26 11.28-1.02 15.721 1.621.539.3.719 1.02.419 1.56-.299.421-1.02.599-1.559.3z"
|
<div class="music-wall__body">
|
||||||
></path></svg
|
<div class="music-block" id="np-section" hidden>
|
||||||
><span>spotify</span>
|
<h2 class="label">now playing</h2>
|
||||||
</a>
|
<div class="np" id="np">
|
||||||
|
<div class="np__body">
|
||||||
|
<img class="np__art np__art--none" id="np-art" alt="" width="64" height="64" decoding="async" />
|
||||||
|
<div class="np__meta">
|
||||||
|
<div class="np__title" id="np-title">—</div>
|
||||||
|
<div class="np__artist" id="np-artist">—</div>
|
||||||
|
<div class="np__foot">
|
||||||
|
<span class="np__tx" aria-hidden="true">
|
||||||
|
<svg viewBox="0 0 24 24" width="11" height="11" fill="currentColor"
|
||||||
|
><path d="M6 5h2v14H6zM20 5v14L9 12z"></path></svg
|
||||||
|
>
|
||||||
|
<svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor"
|
||||||
|
><path d="M6 4l14 8-14 8z"></path></svg
|
||||||
|
>
|
||||||
|
<svg viewBox="0 0 24 24" width="11" height="11" fill="currentColor"
|
||||||
|
><path d="M16 5h2v14h-2zM4 5l11 7-11 7z"></path></svg
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="np__dur" id="np-dur"></span>
|
||||||
|
<span class="np__ago" id="np-ago"></span>
|
||||||
|
<a class="np__src" id="np-src" href="#" target="_blank" rel="noopener">
|
||||||
|
<svg class="np__logo" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"
|
||||||
|
><path
|
||||||
|
d="M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.66 0 12 0zm5.521 17.34c-.24.359-.66.48-1.021.24-2.82-1.74-6.36-2.101-10.561-1.141-.418.122-.779-.179-.899-.539-.12-.421.18-.78.54-.9 4.56-1.021 8.52-.6 11.64 1.32.42.18.479.659.301 1.02zm1.44-3.3c-.301.42-.841.6-1.262.3-3.239-1.98-8.159-2.58-11.939-1.38-.479.12-1.02-.12-1.14-.6-.12-.48.12-1.021.6-1.141C9.6 9.9 15 10.561 18.72 12.84c.361.181.54.78.241 1.2zm.12-3.36C15.24 8.4 8.82 8.16 5.16 9.301c-.6.179-1.2-.16-1.38-.72-.18-.601.18-1.2.72-1.381 4.26-1.26 11.28-1.02 15.721 1.621.539.3.719 1.02.419 1.56-.299.421-1.02.599-1.559.3z"
|
||||||
|
></path></svg
|
||||||
|
><span>spotify</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="np__prog" id="np-prog" hidden><div class="np__prog-fill" id="np-prog-fill"></div></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="np__prog" id="np-prog" hidden><div class="np__prog-fill" id="np-prog-fill"></div></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="section top" id="top-section" hidden>
|
<div class="music-block top" id="top-section" hidden>
|
||||||
<h2 class="label">top tracks <span class="label__sub">last 4 weeks</span></h2>
|
<h2 class="label">top tracks <span class="label__sub">last 4 weeks</span></h2>
|
||||||
<div class="mosaic" id="mosaic"></div>
|
<div class="mosaic" id="mosaic"></div>
|
||||||
<div class="mosaic__caps" id="mosaic-caps"></div>
|
<div class="mosaic__caps" id="mosaic-caps"></div>
|
||||||
</section>
|
</div>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
||||||
|
</div>
|
||||||
|
|
||||||
<style is:global>
|
<style is:global>
|
||||||
|
|
||||||
|
|
||||||
|
.music {
|
||||||
|
margin-top: var(--gap);
|
||||||
|
}
|
||||||
|
.music__trigger {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.55rem;
|
||||||
|
padding: 0.35rem 0;
|
||||||
|
background: none;
|
||||||
|
border: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
font-family: var(--mono);
|
||||||
|
font-size: 0.78rem;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
color: var(--muted);
|
||||||
|
transition: color 0.18s ease;
|
||||||
|
}
|
||||||
|
.music__trigger:hover {
|
||||||
|
color: var(--accent-2);
|
||||||
|
}
|
||||||
|
.music__trigger:focus-visible {
|
||||||
|
outline: 2px solid var(--accent);
|
||||||
|
outline-offset: 4px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
.music__note {
|
||||||
|
color: var(--accent);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
.music__trigger--live .music__note {
|
||||||
|
animation: music-pulse 1.6s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
@keyframes music-pulse {
|
||||||
|
50% {
|
||||||
|
opacity: 0.35;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.music__label {
|
||||||
|
max-width: 22ch;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.music__arw {
|
||||||
|
color: var(--faint);
|
||||||
|
transition: transform 0.22s cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
|
}
|
||||||
|
.music__trigger:hover .music__arw {
|
||||||
|
transform: translateX(0.25em);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.music-wall {
|
||||||
|
margin: auto;
|
||||||
|
width: min(24rem, calc(100vw - 1.5rem));
|
||||||
|
max-height: min(82vh, 40rem);
|
||||||
|
padding: 0;
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-radius: 8px;
|
||||||
|
background: var(--paper-2);
|
||||||
|
color: var(--ink);
|
||||||
|
box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.75);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.music-wall[open] {
|
||||||
|
animation: music-in 0.28s cubic-bezier(0.17, 0.89, 0.32, 1.28);
|
||||||
|
}
|
||||||
|
@keyframes music-in {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(8px) scale(0.96);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.music-wall::backdrop {
|
||||||
|
background: rgba(6, 5, 4, 0.68);
|
||||||
|
backdrop-filter: blur(3px);
|
||||||
|
}
|
||||||
|
.music-wall__bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0.6rem 0.85rem;
|
||||||
|
border-bottom: 1px solid var(--line);
|
||||||
|
}
|
||||||
|
.music-wall__title {
|
||||||
|
font-family: var(--mono);
|
||||||
|
font-size: 0.72rem;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
color: var(--faint);
|
||||||
|
}
|
||||||
|
.music-wall__close {
|
||||||
|
background: none;
|
||||||
|
border: 0;
|
||||||
|
color: var(--muted);
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
line-height: 1;
|
||||||
|
padding: 0.3rem;
|
||||||
|
}
|
||||||
|
.music-wall__close:hover {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
.music-wall__body {
|
||||||
|
padding: 1rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: calc(min(82vh, 40rem) - 2.6rem);
|
||||||
|
}
|
||||||
|
.music-block + .music-block {
|
||||||
|
margin-top: 1.4rem;
|
||||||
|
}
|
||||||
|
.music-block .label {
|
||||||
|
margin-bottom: 0.7rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.np {
|
.np {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 22rem;
|
|
||||||
border: 1px solid var(--faint);
|
border: 1px solid var(--faint);
|
||||||
background: #151412;
|
background: #151412;
|
||||||
}
|
}
|
||||||
@ -161,7 +303,6 @@
|
|||||||
gap: 3px;
|
gap: 3px;
|
||||||
aspect-ratio: 4 / 3;
|
aspect-ratio: 4 / 3;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 268px;
|
|
||||||
}
|
}
|
||||||
.mosaic__cell {
|
.mosaic__cell {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -205,7 +346,7 @@
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 0.14s ease;
|
transition: opacity 0.14s ease;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
white-space: nowrap;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
.mosaic__rank {
|
.mosaic__rank {
|
||||||
color: var(--faint);
|
color: var(--faint);
|
||||||
@ -257,16 +398,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 560px) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
.np {
|
.music__trigger--live .music__note {
|
||||||
max-width: none;
|
animation: none;
|
||||||
}
|
|
||||||
.mosaic__cap {
|
|
||||||
white-space: normal;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import "../scripts/music.ts";
|
import "../scripts/music.ts";
|
||||||
|
|
||||||
|
const dialog = document.querySelector<HTMLDialogElement>("[data-music-dialog]");
|
||||||
|
const open = document.querySelector<HTMLButtonElement>("[data-music-open]");
|
||||||
|
const close = document.querySelector<HTMLButtonElement>("[data-music-close]");
|
||||||
|
|
||||||
|
open?.addEventListener("click", () => dialog?.showModal());
|
||||||
|
close?.addEventListener("click", () => dialog?.close());
|
||||||
|
dialog?.addEventListener("click", (e) => {
|
||||||
|
if (e.target === dialog) dialog.close();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -12,8 +12,6 @@ import { site, elsewhere } from "../data/site";
|
|||||||
<p class="bio">{site.bio}</p>
|
<p class="bio">{site.bio}</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<Music />
|
|
||||||
|
|
||||||
<section class="section">
|
<section class="section">
|
||||||
<h2 class="label">elsewhere</h2>
|
<h2 class="label">elsewhere</h2>
|
||||||
<nav class="pagenav" aria-label="more">
|
<nav class="pagenav" aria-label="more">
|
||||||
@ -35,4 +33,5 @@ import { site, elsewhere } from "../data/site";
|
|||||||
|
|
||||||
<Webrings />
|
<Webrings />
|
||||||
<Buttons />
|
<Buttons />
|
||||||
|
<Music />
|
||||||
</Base>
|
</Base>
|
||||||
|
|||||||
@ -142,6 +142,22 @@ async function load(): Promise<void> {
|
|||||||
if (!data || !data.configured) return;
|
if (!data || !data.configured) return;
|
||||||
if (data.nowPlaying) renderNowPlaying(data.nowPlaying as NP);
|
if (data.nowPlaying) renderNowPlaying(data.nowPlaying as NP);
|
||||||
if (Array.isArray(data.top)) renderTop(data.top as Track[]);
|
if (Array.isArray(data.top)) renderTop(data.top as Track[]);
|
||||||
|
|
||||||
|
|
||||||
|
const trigger = document.querySelector<HTMLButtonElement>(".music__trigger");
|
||||||
|
if (trigger && (data.nowPlaying || (Array.isArray(data.top) && data.top.length))) {
|
||||||
|
trigger.hidden = false;
|
||||||
|
const label = $("music-label");
|
||||||
|
const np = data.nowPlaying as NP | null;
|
||||||
|
if (label && np) {
|
||||||
|
if (np.isPlaying) {
|
||||||
|
trigger.classList.add("music__trigger--live");
|
||||||
|
label.textContent = np.title;
|
||||||
|
} else if (np.playedAt) {
|
||||||
|
label.textContent = "last played";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
load();
|
load();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user