mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-08-28 17:21:05 +00:00
fix: fix animations on analyitics page when setting disabled (#474)
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
} from "./timeRange";
|
||||
import { computeGradeForecast, aggregateToMonthlyPoints } from "./utils/gradePrediction";
|
||||
import PredictionMonthsSlider from "./PredictionMonthsSlider.svelte";
|
||||
import { settingsState } from "@/seqta/utils/listeners/SettingsState";
|
||||
|
||||
interface Props {
|
||||
data: Assessment[];
|
||||
@@ -166,6 +167,8 @@
|
||||
return monthly.length >= 3;
|
||||
});
|
||||
|
||||
const animationsOn = $derived($settingsState.animations);
|
||||
|
||||
/** Historical + future forecast points so tooltips work across the dashed line. */
|
||||
const chartData = $derived.by((): TrendPoint[] => {
|
||||
if (!showPrediction || !forecast?.points.length) {
|
||||
@@ -243,7 +246,7 @@
|
||||
curve: curveMonotoneX,
|
||||
"fill-opacity": showSubjectTrends ? 0.12 : 0.35,
|
||||
line: { class: "stroke-2" },
|
||||
motion: "tween",
|
||||
motion: animationsOn ? "tween" : false,
|
||||
},
|
||||
xAxis: {
|
||||
ticks: timeRange === "7d" ? 7 : undefined,
|
||||
@@ -267,12 +270,12 @@
|
||||
</defs>
|
||||
|
||||
<ChartClipPath
|
||||
initialWidth={showPrediction ? undefined : 0}
|
||||
motion={showPrediction
|
||||
? undefined
|
||||
: {
|
||||
initialWidth={animationsOn && !showPrediction ? 0 : undefined}
|
||||
motion={animationsOn && !showPrediction
|
||||
? {
|
||||
width: { type: "tween", duration: 900, easing: cubicInOut },
|
||||
}}
|
||||
}
|
||||
: undefined}
|
||||
>
|
||||
{#each series as s, i (s.key)}
|
||||
{@const meta = chartSeries.find((c) => c.key === s.key)}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
} from "./gradeDistribution";
|
||||
|
||||
import { loadDistributionMode, saveDistributionMode } from "./storage";
|
||||
import { settingsState } from "@/seqta/utils/listeners/SettingsState";
|
||||
|
||||
|
||||
|
||||
@@ -312,7 +313,7 @@
|
||||
|
||||
motion: {
|
||||
|
||||
y: { type: "tween", duration: 600, easing: cubicInOut },
|
||||
y: { type: "tween", duration: $settingsState.animations ? 600 : 0, easing: cubicInOut },
|
||||
|
||||
},
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
type TimeRange,
|
||||
} from "./timeRange";
|
||||
import { openAnalyticsPrivacyPopup } from "./openAnalyticsPrivacyPopup";
|
||||
import { settingsState } from "@/seqta/utils/listeners/SettingsState";
|
||||
|
||||
let analyticsData: Assessment[] | null = $state(null);
|
||||
let loading = $state(true);
|
||||
@@ -39,6 +40,8 @@
|
||||
|
||||
let timestampInterval: ReturnType<typeof setInterval> | null = null;
|
||||
let contentReady = $state(false);
|
||||
const fadeDuration = $derived($settingsState.animations ? 200 : 0);
|
||||
const emptyFadeDuration = $derived($settingsState.animations ? 300 : 0);
|
||||
|
||||
const formattedTimestamp = $derived(() => {
|
||||
if (!lastUpdated) return "";
|
||||
@@ -204,7 +207,7 @@
|
||||
|
||||
<div class="bsplus-analytics-root">
|
||||
{#if error}
|
||||
<p class="bsplus-analytics-alert bsplus-analytics-animate" role="alert" transition:fade={{ duration: 200 }}>
|
||||
<p class="bsplus-analytics-alert bsplus-analytics-animate" role="alert" transition:fade={{ duration: fadeDuration }}>
|
||||
{error}
|
||||
</p>
|
||||
{/if}
|
||||
@@ -462,7 +465,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="bsplus-analytics-layout bsplus-analytics-animate" transition:fade={{ duration: 300 }}>
|
||||
<div class="bsplus-analytics-layout bsplus-analytics-animate" transition:fade={{ duration: emptyFadeDuration }}>
|
||||
<aside class="bsplus-analytics-filters" aria-label="Analytics">
|
||||
{@render sidebarTitle()}
|
||||
{@render sidebarActions()}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { onDestroy } from "svelte";
|
||||
import { settingsState } from "@/seqta/utils/listeners/SettingsState";
|
||||
|
||||
let {
|
||||
value = $bindable<[number, number]>([0, 100]),
|
||||
@@ -88,7 +89,7 @@
|
||||
|
||||
value = next;
|
||||
|
||||
if (animate) {
|
||||
if (animate && $settingsState.animations) {
|
||||
animateVisualTo(next);
|
||||
} else {
|
||||
visual = next;
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import {
|
||||
ANALYTICS_MOTION_CLASS,
|
||||
analyticsMotionEnabled,
|
||||
applyAnalyticsMotionClass,
|
||||
} from "./motion";
|
||||
|
||||
describe("analyticsMotionEnabled", () => {
|
||||
it("is on only when the animations setting is true", () => {
|
||||
expect(analyticsMotionEnabled(true)).toBe(true);
|
||||
expect(analyticsMotionEnabled(false)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("applyAnalyticsMotionClass", () => {
|
||||
it("adds the motion class when animations are enabled", () => {
|
||||
const el = { classList: { toggle: jest.fn() } };
|
||||
applyAnalyticsMotionClass(el, true);
|
||||
expect(el.classList.toggle).toHaveBeenCalledWith(ANALYTICS_MOTION_CLASS, true);
|
||||
});
|
||||
|
||||
it("removes the motion class when animations are disabled", () => {
|
||||
const el = { classList: { toggle: jest.fn() } };
|
||||
applyAnalyticsMotionClass(el, false);
|
||||
expect(el.classList.toggle).toHaveBeenCalledWith(ANALYTICS_MOTION_CLASS, false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
export const ANALYTICS_MOTION_CLASS = "bsplus-analytics-motion";
|
||||
|
||||
export function analyticsMotionEnabled(animations: boolean | undefined): boolean {
|
||||
return animations === true;
|
||||
}
|
||||
|
||||
export function applyAnalyticsMotionClass(
|
||||
target: { classList: { toggle: (token: string, force?: boolean) => unknown } },
|
||||
animations: boolean | undefined,
|
||||
): void {
|
||||
target.classList.toggle(ANALYTICS_MOTION_CLASS, analyticsMotionEnabled(animations));
|
||||
}
|
||||
@@ -114,6 +114,25 @@
|
||||
}
|
||||
}
|
||||
|
||||
.bsplus-analytics-mount:not(.bsplus-analytics-motion) .bsplus-analytics-animate {
|
||||
animation: none;
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.bsplus-analytics-mount:not(.bsplus-analytics-motion) .bsplus-analytics-btn,
|
||||
.bsplus-analytics-mount:not(.bsplus-analytics-motion) .bsplus-analytics-card,
|
||||
.bsplus-analytics-mount:not(.bsplus-analytics-motion) .bsplus-analytics-dropdown-trigger,
|
||||
.bsplus-analytics-mount:not(.bsplus-analytics-motion) .bsplus-analytics-select {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.bsplus-analytics-mount:not(.bsplus-analytics-motion) .bsplus-analytics-btn:hover:not(:disabled),
|
||||
.bsplus-analytics-mount:not(.bsplus-analytics-motion) .bsplus-analytics-btn:active:not(:disabled),
|
||||
.bsplus-analytics-mount:not(.bsplus-analytics-motion) .bsplus-analytics-dropdown-trigger:hover {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.bsplus-analytics-delay-1 {
|
||||
animation-delay: 80ms;
|
||||
}
|
||||
|
||||
@@ -5,13 +5,15 @@ import { mount, unmount } from "svelte";
|
||||
import GradeAnalyticsPage from "./GradeAnalyticsPage.svelte";
|
||||
import { buildContrastAccentPalette } from "./utils/accentColor";
|
||||
import { extractSolidColor } from "@/seqta/ui/colors/parseCssColor";
|
||||
import { applyAnalyticsMotionClass } from "./motion";
|
||||
|
||||
type ThemeSettingKey =
|
||||
| "selectedColor"
|
||||
| "DarkMode"
|
||||
| "adaptiveThemeColour"
|
||||
| "adaptiveThemeGradient"
|
||||
| "selectedTheme";
|
||||
| "selectedTheme"
|
||||
| "animations";
|
||||
|
||||
type ThemeListenerRegistration = {
|
||||
key: ThemeSettingKey;
|
||||
@@ -117,7 +119,10 @@ function syncThemeFromPage(target: HTMLElement) {
|
||||
|
||||
function syncThemeToAnalyticsUi() {
|
||||
if (shadowHost) syncThemeFromPage(shadowHost);
|
||||
if (analyticsRoot) syncThemeFromPage(analyticsRoot);
|
||||
if (analyticsRoot) {
|
||||
syncThemeFromPage(analyticsRoot);
|
||||
applyAnalyticsMotionClass(analyticsRoot, settingsState.animations);
|
||||
}
|
||||
}
|
||||
|
||||
function clearThemeListeners() {
|
||||
@@ -136,6 +141,7 @@ function watchThemeChanges() {
|
||||
"adaptiveThemeColour",
|
||||
"adaptiveThemeGradient",
|
||||
"selectedTheme",
|
||||
"animations",
|
||||
];
|
||||
|
||||
const listener = () => syncThemeToAnalyticsUi();
|
||||
|
||||
Reference in New Issue
Block a user