This commit is contained in:
2026-07-17 19:15:11 +08:00 Unverified
parent 6899f11b5f
commit 333e92df80
2 changed files with 37 additions and 10 deletions
+31 -8
View File
@@ -1,6 +1,6 @@
<aside class="hitokoto-card" aria-label="一言" data-hitokoto-card> <aside class="hitokoto-card is-collapsed" aria-label="一言" data-hitokoto-card>
<div class="hitokoto-card__head"> <div class="hitokoto-card__head">
<button class="hitokoto-card__toggle" type="button" aria-label="展开一言" aria-expanded="true" title="一言" data-hitokoto-toggle> <button class="hitokoto-card__toggle" type="button" aria-label="展开一言" aria-expanded="false" title="一言" data-hitokoto-toggle>
<i class="fa-solid fa-quote-left" aria-hidden="true"></i> <i class="fa-solid fa-quote-left" aria-hidden="true"></i>
<span>一言</span> <span>一言</span>
</button> </button>
@@ -38,6 +38,7 @@
const endpoint = 'https://yiyan.biss.click/api?encode=json'; const endpoint = 'https://yiyan.biss.click/api?encode=json';
const cacheKey = 'hitokoto-card-cache'; const cacheKey = 'hitokoto-card-cache';
const preferenceKey = 'hitokoto-card-expanded';
const cacheMaxAge = 6 * 60 * 60 * 1000; const cacheMaxAge = 6 * 60 * 60 * 1000;
const fallback = { const fallback = {
sentence: '生活明朗,万物可爱。', sentence: '生活明朗,万物可爱。',
@@ -46,11 +47,32 @@
}; };
const isHomePage = ['/', '/index.html'].includes(window.location.pathname); const isHomePage = ['/', '/index.html'].includes(window.location.pathname);
const mobileMedia = window.matchMedia('(max-width: 720px)');
function setExpanded(expanded) { function readExpandedPreference() {
try {
const preference = localStorage.getItem(preferenceKey);
if (preference === 'true') return true;
if (preference === 'false') return false;
} catch {
// localStorage can be unavailable in strict privacy modes.
}
return null;
}
function writeExpandedPreference(expanded) {
try {
localStorage.setItem(preferenceKey, String(expanded));
} catch {
// localStorage can be unavailable in strict privacy modes.
}
}
function setExpanded(expanded, { persist = false } = {}) {
card.classList.toggle('is-collapsed', !expanded); card.classList.toggle('is-collapsed', !expanded);
toggle.setAttribute('aria-expanded', String(expanded)); toggle.setAttribute('aria-expanded', String(expanded));
toggle.setAttribute('aria-label', expanded ? '收起一言' : '展开一言'); toggle.setAttribute('aria-label', expanded ? '收起一言' : '展开一言');
if (persist) writeExpandedPreference(expanded);
} }
function readCache() { function readCache() {
@@ -117,27 +139,28 @@
} }
} }
setExpanded(isHomePage); const expandedPreference = readExpandedPreference();
setExpanded(expandedPreference ?? (isHomePage && !mobileMedia.matches));
toggle.addEventListener('click', () => { toggle.addEventListener('click', () => {
setExpanded(card.classList.contains('is-collapsed')); setExpanded(card.classList.contains('is-collapsed'), { persist: true });
}); });
refresh?.addEventListener('click', (event) => { refresh?.addEventListener('click', (event) => {
event.stopPropagation(); event.stopPropagation();
setExpanded(true); setExpanded(true, { persist: true });
fetchHitokoto({ force: true }); fetchHitokoto({ force: true });
}); });
collapse?.addEventListener('click', (event) => { collapse?.addEventListener('click', (event) => {
event.stopPropagation(); event.stopPropagation();
setExpanded(false); setExpanded(false, { persist: true });
}); });
card.addEventListener('click', (event) => { card.addEventListener('click', (event) => {
if (!card.classList.contains('is-collapsed')) return; if (!card.classList.contains('is-collapsed')) return;
if (event.target instanceof Element && event.target.closest('a, button')) return; if (event.target instanceof Element && event.target.closest('a, button')) return;
setExpanded(true); setExpanded(true, { persist: true });
}); });
fetchHitokoto(); fetchHitokoto();
+6 -2
View File
@@ -151,19 +151,23 @@
0 22px 64px rgba(44, 55, 63, 0.24); 0 22px 64px rgba(44, 55, 63, 0.24);
backdrop-filter: blur(22px) saturate(170%); backdrop-filter: blur(22px) saturate(170%);
-webkit-backdrop-filter: blur(22px) saturate(170%); -webkit-backdrop-filter: blur(22px) saturate(170%);
visibility: hidden;
opacity: 0; opacity: 0;
pointer-events: none; pointer-events: none;
transform: translateX(calc(100% + 24px)) scale(0.98); transform: translateY(-8px) scale(0.98);
transform-origin: top right; transform-origin: top right;
transition: transition:
visibility 0s linear 0.24s,
opacity 0.18s ease, opacity 0.18s ease,
transform 0.24s cubic-bezier(0.2, 0.8, 0.2, 1); transform 0.24s cubic-bezier(0.2, 0.8, 0.2, 1);
} }
.nav.is-open .nav-menu { .nav.is-open .nav-menu {
visibility: visible;
opacity: 1; opacity: 1;
pointer-events: auto; pointer-events: auto;
transform: translateX(0) scale(1); transform: translateY(0) scale(1);
transition-delay: 0s;
} }
.nav-links { .nav-links {