clean up TOTM popup. properly remember closes

This commit is contained in:
2026-05-29 11:29:50 +09:30
parent a23eda1162
commit f5034ca0bc
3 changed files with 84 additions and 64 deletions
+59 -45
View File
@@ -3753,41 +3753,6 @@ div.day-empty {
pointer-events: none; pointer-events: none;
animation: themeOfTheMonthCardOut 0.18s ease-in forwards; animation: themeOfTheMonthCardOut 0.18s ease-in forwards;
} }
.themeOfTheMonthCardDisable {
position: absolute !important;
top: 6px !important;
right: 6px !important;
z-index: 3 !important;
box-sizing: border-box !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
width: 18px !important;
height: 18px !important;
min-width: 0 !important;
min-height: 0 !important;
max-width: 18px !important;
max-height: 18px !important;
margin: 0 !important;
padding: 0 !important;
border: 1px solid rgba(255, 255, 255, 0.22) !important;
border-radius: 9px !important;
background: rgba(0, 0, 0, 0.42) !important;
color: white !important;
cursor: pointer !important;
font-family: inherit !important;
font-size: 12px !important;
font-weight: 600 !important;
line-height: 1 !important;
text-align: center !important;
opacity: 0.75;
transition: opacity 0.15s ease, transform 0.15s ease, background 0.15s ease;
}
.themeOfTheMonthCardDisable:hover {
opacity: 1;
transform: scale(1.08);
background: rgba(0, 0, 0, 0.6) !important;
}
.themeOfTheMonthCardConfirm { .themeOfTheMonthCardConfirm {
position: absolute; position: absolute;
inset: 0; inset: 0;
@@ -3897,11 +3862,34 @@ div.day-empty {
.themeOfTheMonthCardActions { .themeOfTheMonthCardActions {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: flex-end; align-items: center;
gap: 8px; justify-content: space-between;
gap: 10px;
}
.themeOfTheMonthCardActionsStart {
display: flex;
flex-wrap: wrap;
align-items: center;
}
.themeOfTheMonthCardActionsEnd {
display: inline-flex;
flex-wrap: nowrap;
align-items: stretch;
margin-left: auto;
padding: 3px;
gap: 0;
overflow: hidden;
border-radius: 9999px;
background: color-mix(
in srgb,
var(--background-secondary, var(--text-primary)) 28%,
var(--background-primary)
);
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text-primary) 8%, transparent);
} }
.themeOfTheMonthCardPrimary, .themeOfTheMonthCardPrimary,
.themeOfTheMonthCardSecondary { .themeOfTheMonthCardSecondary,
.themeOfTheMonthCardDontShow {
appearance: none; appearance: none;
border: none; border: none;
cursor: pointer; cursor: pointer;
@@ -3909,23 +3897,49 @@ div.day-empty {
padding: 0.58rem 0.9rem; padding: 0.58rem 0.9rem;
font-size: 0.86rem; font-size: 0.86rem;
font-weight: 700; font-weight: 700;
transition: transform 0.15s ease, filter 0.15s ease, background 0.15s ease; transition: background 0.15s ease, color 0.15s ease;
} }
.themeOfTheMonthCardPrimary { .themeOfTheMonthCardPrimary {
background: var(--better-pri, #6366f1); background: var(--better-pri, #6366f1);
color: white; color: white;
} }
.themeOfTheMonthCardSecondary { #theme-of-the-month-card .themeOfTheMonthCardActionsEnd .themeOfTheMonthCardSecondary,
background: color-mix(in srgb, var(--text-primary) 10%, transparent); #theme-of-the-month-card .themeOfTheMonthCardActionsEnd .themeOfTheMonthCardDontShow {
padding: 0.5rem 0.8rem;
font-size: 0.8rem;
font-weight: 600;
border: none !important;
border-radius: 9999px !important;
background: transparent !important;
box-shadow: none !important;
filter: none !important;
transform: none !important;
}
#theme-of-the-month-card .themeOfTheMonthCardActionsEnd .themeOfTheMonthCardSecondary {
color: var(--text-primary); color: var(--text-primary);
} }
.themeOfTheMonthCardPrimary:hover, #theme-of-the-month-card .themeOfTheMonthCardActionsEnd .themeOfTheMonthCardDontShow {
.themeOfTheMonthCardSecondary:hover { color: color-mix(in srgb, var(--text-primary) 58%, transparent);
}
#theme-of-the-month-card .themeOfTheMonthCardActionsEnd .themeOfTheMonthCardSecondary:hover,
#theme-of-the-month-card .themeOfTheMonthCardActionsEnd .themeOfTheMonthCardSecondary:focus-visible,
#theme-of-the-month-card .themeOfTheMonthCardActionsEnd .themeOfTheMonthCardDontShow:hover,
#theme-of-the-month-card .themeOfTheMonthCardActionsEnd .themeOfTheMonthCardDontShow:focus-visible {
background: color-mix(in srgb, var(--text-primary) 10%, transparent) !important;
border-radius: 9999px !important;
filter: none !important;
transform: none !important;
}
#theme-of-the-month-card .themeOfTheMonthCardActionsEnd .themeOfTheMonthCardSecondary:active,
#theme-of-the-month-card .themeOfTheMonthCardActionsEnd .themeOfTheMonthCardDontShow:active {
background: color-mix(in srgb, var(--text-primary) 14%, transparent) !important;
border-radius: 9999px !important;
}
.themeOfTheMonthCardPrimary:hover {
filter: brightness(1.08); filter: brightness(1.08);
transform: translateY(-1px); transform: translateY(-1px);
} }
.themeOfTheMonthCardPrimary:active, .themeOfTheMonthCardPrimary:active {
.themeOfTheMonthCardSecondary:active {
transform: translateY(0); transform: translateY(0);
} }
@keyframes themeOfTheMonthCardIn { @keyframes themeOfTheMonthCardIn {
@@ -134,7 +134,6 @@ export async function OpenThemeOfTheMonthPopup(
const card = stringToHTML(/* html */ ` const card = stringToHTML(/* html */ `
<aside id="theme-of-the-month-card" class="themeOfTheMonthCard" role="dialog" aria-label="Theme of the Month"> <aside id="theme-of-the-month-card" class="themeOfTheMonthCard" role="dialog" aria-label="Theme of the Month">
<button type="button" class="themeOfTheMonthCardDisable" aria-label="Don't show Theme of the Month again" title="Don't show again">×</button>
${ ${
heroUrl heroUrl
? `<img class="themeOfTheMonthCardImage" src="${escapeHTML(heroUrl)}" alt="${escapeHTML(entry.title)}" />` ? `<img class="themeOfTheMonthCardImage" src="${escapeHTML(heroUrl)}" alt="${escapeHTML(entry.title)}" />`
@@ -145,18 +144,23 @@ export async function OpenThemeOfTheMonthPopup(
<h2>${escapeHTML(entry.title)}</h2> <h2>${escapeHTML(entry.title)}</h2>
<p class="themeOfTheMonthCardDescription">${description}</p> <p class="themeOfTheMonthCardDescription">${description}</p>
<div class="themeOfTheMonthCardActions"> <div class="themeOfTheMonthCardActions">
<div class="themeOfTheMonthCardActionsStart">
${ ${
linkedThemeId linkedThemeId
? `<button type="button" class="themeOfTheMonthCardPrimary">Open Store</button>` ? `<button type="button" class="themeOfTheMonthCardPrimary">Open Store</button>`
: "" : ""
} }
</div>
<div class="themeOfTheMonthCardActionsEnd">
<button type="button" class="themeOfTheMonthCardSecondary">Close</button> <button type="button" class="themeOfTheMonthCardSecondary">Close</button>
<button type="button" class="themeOfTheMonthCardDontShow">Don't show again</button>
</div>
</div> </div>
</div> </div>
<div class="themeOfTheMonthCardConfirm" hidden> <div class="themeOfTheMonthCardConfirm" hidden>
<div class="themeOfTheMonthCardConfirmInner"> <div class="themeOfTheMonthCardConfirmInner">
<h3>Don't show again?</h3> <h3>Don't show again?</h3>
<p>You won't see this month's announcement again until next month. Re-enable monthly popups in BetterSEQTA+ settings.</p> <p>Theme of the Month popups will be turned off. You can turn them back on in BetterSEQTA+ settings.</p>
<div class="themeOfTheMonthCardConfirmActions"> <div class="themeOfTheMonthCardConfirmActions">
<button type="button" class="themeOfTheMonthCardConfirmCancel">Cancel</button> <button type="button" class="themeOfTheMonthCardConfirmCancel">Cancel</button>
<button type="button" class="themeOfTheMonthCardConfirmAccept">Don't show again</button> <button type="button" class="themeOfTheMonthCardConfirmAccept">Don't show again</button>
@@ -168,7 +172,7 @@ export async function OpenThemeOfTheMonthPopup(
const autoCloseTimeout = window.setTimeout(() => { const autoCloseTimeout = window.setTimeout(() => {
closeThemeOfTheMonthCard(card, onDismissed); closeThemeOfTheMonthCard(card, onDismissed);
}, 12000); }, 30_000);
const dismiss = () => { const dismiss = () => {
window.clearTimeout(autoCloseTimeout); window.clearTimeout(autoCloseTimeout);
@@ -180,22 +184,24 @@ export async function OpenThemeOfTheMonthPopup(
const confirmEl = card.querySelector<HTMLElement>(".themeOfTheMonthCardConfirm"); const confirmEl = card.querySelector<HTMLElement>(".themeOfTheMonthCardConfirm");
card.querySelector(".themeOfTheMonthCardSecondary")?.addEventListener("click", () => { card.querySelector(".themeOfTheMonthCardSecondary")?.addEventListener("click", () => {
settingsState.themeOfTheMonthDismissedMonth = entry.month;
dismiss(); dismiss();
}); });
card.querySelector(".themeOfTheMonthCardPrimary")?.addEventListener("click", () => { card.querySelector(".themeOfTheMonthCardPrimary")?.addEventListener("click", () => {
settingsState.themeOfTheMonthDismissedMonth = entry.month;
dismiss(); dismiss();
openThemeStoreWithHighlight(linkedThemeId!); openThemeStoreWithHighlight(linkedThemeId!);
}); });
card.querySelector(".themeOfTheMonthCardDisable")?.addEventListener("click", () => { const openDontShowConfirm = () => {
window.clearTimeout(autoCloseTimeout); window.clearTimeout(autoCloseTimeout);
if (confirmEl) { if (!confirmEl) return;
confirmEl.hidden = false; confirmEl.hidden = false;
// allow CSS transition by toggling on next frame
requestAnimationFrame(() => confirmEl.classList.add("themeOfTheMonthCardConfirmVisible")); requestAnimationFrame(() => confirmEl.classList.add("themeOfTheMonthCardConfirmVisible"));
} };
});
card.querySelector(".themeOfTheMonthCardDontShow")?.addEventListener("click", openDontShowConfirm);
card.querySelector(".themeOfTheMonthCardConfirmCancel")?.addEventListener("click", () => { card.querySelector(".themeOfTheMonthCardConfirmCancel")?.addEventListener("click", () => {
if (!confirmEl) return; if (!confirmEl) return;
@@ -206,7 +212,7 @@ export async function OpenThemeOfTheMonthPopup(
}); });
card.querySelector(".themeOfTheMonthCardConfirmAccept")?.addEventListener("click", () => { card.querySelector(".themeOfTheMonthCardConfirmAccept")?.addEventListener("click", () => {
settingsState.themeOfTheMonthDismissedMonth = entry.month; settingsState.themeOfTheMonthDisabled = true;
dismiss(); dismiss();
}); });
+2 -2
View File
@@ -37,8 +37,8 @@ export interface SettingsState {
/** One-time announcement: BS Cloud automatic settings sync (last in startup popup queue). */ /** One-time announcement: BS Cloud automatic settings sync (last in startup popup queue). */
bsCloudAutoSyncAnnouncementShown?: boolean; bsCloudAutoSyncAnnouncementShown?: boolean;
/** /**
* Calendar month (`YYYY-MM`) for which the user dismissed the Theme of the Month * Calendar month (`YYYY-MM`) for which the user closed the Theme of the Month popup.
* popup via "Don't show again" (not a normal Close). * Cleared automatically when a new month's entry is fetched (different `month`).
*/ */
themeOfTheMonthDismissedMonth?: string; themeOfTheMonthDismissedMonth?: string;
/** @deprecated Migrated away; no longer read. */ /** @deprecated Migrated away; no longer read. */