feat: fix reduce motion controls
This commit is contained in:
parent
3f74df0b3a
commit
38efffa9b9
3 changed files with 26 additions and 70 deletions
|
|
@ -1,8 +1,6 @@
|
|||
const STORAGE_KEY = "background-motion-preference";
|
||||
const MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
||||
const STILL_STEPS = 5;
|
||||
|
||||
type MotionPreference = "auto" | "off" | "on";
|
||||
type BackgroundMode = "animated" | "still" | "failed";
|
||||
|
||||
interface BackgroundActions {
|
||||
|
|
@ -11,23 +9,7 @@ interface BackgroundActions {
|
|||
renderStill: (steps: number) => void;
|
||||
}
|
||||
|
||||
function readPreference(): MotionPreference {
|
||||
const stored = window.localStorage.getItem(STORAGE_KEY);
|
||||
return stored === "off" || stored === "on" || stored === "auto"
|
||||
? stored
|
||||
: "auto";
|
||||
}
|
||||
|
||||
function writePreference(preference: MotionPreference) {
|
||||
window.localStorage.setItem(STORAGE_KEY, preference);
|
||||
}
|
||||
|
||||
function getMode(
|
||||
preference: MotionPreference,
|
||||
reducedMotion: boolean,
|
||||
): BackgroundMode {
|
||||
if (preference === "on") return "animated";
|
||||
if (preference === "off") return "still";
|
||||
function getMode(reducedMotion: boolean): BackgroundMode {
|
||||
return reducedMotion ? "still" : "animated";
|
||||
}
|
||||
|
||||
|
|
@ -39,46 +21,22 @@ function applyCanvasState(mode: BackgroundMode) {
|
|||
}
|
||||
}
|
||||
|
||||
function updateControls(
|
||||
preference: MotionPreference,
|
||||
mode: BackgroundMode,
|
||||
reducedMotion: boolean,
|
||||
) {
|
||||
const button = document.getElementById(
|
||||
"background-toggle",
|
||||
) as HTMLButtonElement | null;
|
||||
const status = document.getElementById("background-status");
|
||||
if (!button || !status) return;
|
||||
|
||||
button.textContent = `motion ${preference}`;
|
||||
|
||||
if (mode === "failed") {
|
||||
status.textContent = "background unavailable";
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode === "still") {
|
||||
status.textContent =
|
||||
preference === "auto" && reducedMotion
|
||||
? "still frame"
|
||||
: "background still";
|
||||
return;
|
||||
}
|
||||
|
||||
status.textContent = "background live";
|
||||
}
|
||||
|
||||
export function initBackgroundControls(actions: BackgroundActions) {
|
||||
const media = window.matchMedia(MOTION_QUERY);
|
||||
let preference = readPreference();
|
||||
let mode: BackgroundMode = getMode(preference, media.matches);
|
||||
let mode: BackgroundMode = getMode(media.matches);
|
||||
let failed = false;
|
||||
|
||||
const applyMode = () => {
|
||||
mode = getMode(preference, media.matches);
|
||||
const applyMode = (restartAnimation = false) => {
|
||||
if (failed) return;
|
||||
|
||||
mode = getMode(media.matches);
|
||||
applyCanvasState(mode);
|
||||
updateControls(preference, mode, media.matches);
|
||||
|
||||
if (mode === "animated") {
|
||||
if (restartAnimation) {
|
||||
actions.stop();
|
||||
}
|
||||
|
||||
actions.start();
|
||||
return;
|
||||
}
|
||||
|
|
@ -87,29 +45,34 @@ export function initBackgroundControls(actions: BackgroundActions) {
|
|||
actions.renderStill(STILL_STEPS);
|
||||
};
|
||||
|
||||
const button = document.getElementById(
|
||||
"background-toggle",
|
||||
) as HTMLButtonElement | null;
|
||||
const restartAnimation = () => {
|
||||
if (document.visibilityState === "hidden" || media.matches) {
|
||||
return;
|
||||
}
|
||||
|
||||
button?.addEventListener("click", () => {
|
||||
preference =
|
||||
preference === "auto" ? "off" : preference === "off" ? "on" : "auto";
|
||||
writePreference(preference);
|
||||
applyMode();
|
||||
});
|
||||
applyMode(true);
|
||||
};
|
||||
|
||||
media.addEventListener("change", () => {
|
||||
applyMode();
|
||||
});
|
||||
|
||||
document.addEventListener("visibilitychange", () => {
|
||||
restartAnimation();
|
||||
});
|
||||
|
||||
window.addEventListener("pageshow", () => {
|
||||
restartAnimation();
|
||||
});
|
||||
|
||||
return {
|
||||
applyInitialMode() {
|
||||
applyMode();
|
||||
},
|
||||
setFailed() {
|
||||
failed = true;
|
||||
mode = "failed";
|
||||
applyCanvasState(mode);
|
||||
updateControls(preference, mode, media.matches);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,9 +38,6 @@ export function renderFooter() {
|
|||
<span aria-hidden="true">|</span>
|
||||
<a href="/ssh.txt" data-native-link>ssh</a>
|
||||
<span aria-hidden="true">|</span>
|
||||
<button type="button" id="background-toggle" class="qa-inline-action">motion auto</button>
|
||||
<span id="background-status" class="qa-meta" aria-live="polite"></span>
|
||||
<span aria-hidden="true">|</span>
|
||||
<a href="${mirror.href}">${mirror.label}</a>
|
||||
</div>
|
||||
</div>`;
|
||||
|
|
|
|||
|
|
@ -352,10 +352,6 @@ a[aria-current="page"] {
|
|||
color: var(--dark-gray);
|
||||
}
|
||||
|
||||
#background-status {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue