fix(ui): align gauge animation with validation
This commit is contained in:
@@ -116,6 +116,10 @@ describe("Gauge", () => {
|
||||
const indicator = gauge.querySelector('[data-slot="indicator"]');
|
||||
const value = gauge.querySelector('[data-slot="value"]');
|
||||
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(16);
|
||||
});
|
||||
|
||||
expect(gauge).toHaveAttribute("data-animating", "");
|
||||
expect(indicator).toHaveAttribute("stroke-dasharray", "0 100");
|
||||
expect(value).toHaveTextContent("0%");
|
||||
|
||||
@@ -374,6 +374,7 @@ export const Gauge = forwardRef<HTMLDivElement, GaugeProps>(function Gauge(
|
||||
useEffect(() => {
|
||||
const targetPercentage = percentage ?? 0;
|
||||
const targetValue = computedAriaValueNow ?? null;
|
||||
let frame = 0;
|
||||
|
||||
if (
|
||||
disableMotion ||
|
||||
@@ -383,17 +384,21 @@ export const Gauge = forwardRef<HTMLDivElement, GaugeProps>(function Gauge(
|
||||
previousPercentageRef.current === targetPercentage &&
|
||||
previousValueRef.current === targetValue)
|
||||
) {
|
||||
setDisplayPercentage(targetPercentage);
|
||||
setDisplayValue(targetValue);
|
||||
setIsAnimating(false);
|
||||
previousPercentageRef.current = targetPercentage;
|
||||
previousValueRef.current = targetValue;
|
||||
frame = window.requestAnimationFrame(() => {
|
||||
setDisplayPercentage(targetPercentage);
|
||||
setDisplayValue(targetValue);
|
||||
setIsAnimating(false);
|
||||
previousPercentageRef.current = targetPercentage;
|
||||
previousValueRef.current = targetValue;
|
||||
|
||||
if (targetValue != null) {
|
||||
hasAnimatedRef.current = true;
|
||||
}
|
||||
if (targetValue != null) {
|
||||
hasAnimatedRef.current = true;
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
return () => {
|
||||
window.cancelAnimationFrame(frame);
|
||||
};
|
||||
}
|
||||
|
||||
const fromPercentage = hasAnimatedRef.current ? previousPercentageRef.current : 0;
|
||||
@@ -401,13 +406,8 @@ export const Gauge = forwardRef<HTMLDivElement, GaugeProps>(function Gauge(
|
||||
? previousValueRef.current ?? resolvedMin
|
||||
: resolvedMin;
|
||||
const duration = hasAnimatedRef.current ? UPDATE_SWEEP_DURATION : INITIAL_SWEEP_DURATION;
|
||||
let frame = 0;
|
||||
let startTime: number | null = null;
|
||||
|
||||
setDisplayPercentage(fromPercentage);
|
||||
setDisplayValue(fromValue);
|
||||
setIsAnimating(true);
|
||||
|
||||
const tick = (timestamp: number) => {
|
||||
if (startTime == null) {
|
||||
startTime = timestamp;
|
||||
@@ -416,6 +416,7 @@ export const Gauge = forwardRef<HTMLDivElement, GaugeProps>(function Gauge(
|
||||
const progress = Math.min((timestamp - startTime) / duration, 1);
|
||||
const easedProgress = easeOutCubic(progress);
|
||||
|
||||
setIsAnimating(progress < 1);
|
||||
setDisplayPercentage(fromPercentage + (targetPercentage - fromPercentage) * easedProgress);
|
||||
setDisplayValue(fromValue + (targetValue - fromValue) * easedProgress);
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ describe("Progress", () => {
|
||||
const { rerender } = render(<Progress aria-label="Reduced sync status" value={null} />);
|
||||
|
||||
let progressbar = screen.getByRole("progressbar", { name: "Reduced sync status" });
|
||||
let indicator = progressbar.querySelector('[data-slot="indicator"]');
|
||||
const indicator = progressbar.querySelector('[data-slot="indicator"]');
|
||||
|
||||
expect(progressbar).toHaveAttribute("data-reduced-motion", "");
|
||||
expect(indicator).toHaveAttribute("data-reduced-motion", "");
|
||||
|
||||
Reference in New Issue
Block a user