From 5282a273973532219f80032b31b783e1b77cb7dc Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Sun, 26 Jul 2026 23:35:48 +0300 Subject: [PATCH] chore(motion): name and document stagger/badge duration constants Introduce kQueryaStaggerStep and document allowed non-token durations alongside kUpdateBadgePulsePeriod in motion guardrails. Closes #365 Co-authored-by: Cursor --- docs/motion-and-high-refresh.md | 9 ++++++++- lib/core/motion/querya_stagger.dart | 6 +++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/docs/motion-and-high-refresh.md b/docs/motion-and-high-refresh.md index 53f41973..409ef9e4 100644 --- a/docs/motion-and-high-refresh.md +++ b/docs/motion-and-high-refresh.md @@ -142,11 +142,18 @@ Suggested order: A1 → A2 → A3 in parallel with A4; then A5; A6 closes the mi When reviewing PRs that touch animation: 1. Reject bare `Duration(milliseconds: …)` / ad-hoc `Curves.*` in product UI unless - wired through `QueryaMotion` (or documented physics constants in `QueryaSpring`). + wired through `QueryaMotion` (or documented physics / choreography constants). 2. Require Full / Reduced / Off + OS `disableAnimations` coverage for new transitions. 3. Split / resize: no spring or lag mid-drag; settle only on release / focus chrome. 4. Never stagger or fade virtualized result rows while scrolling. +**Allowed named non-token durations** (named + documented — not magic literals at call sites): + +| Constant | Value | Where | +|----------|-------|--------| +| `kQueryaStaggerStep` | 30 ms | `QueryaStagger` first-paint choreography | +| `kUpdateBadgePulsePeriod` | 1400 ms | Update title-bar chip pulse (chrome; see #363) | + Checklist for 120 Hz verification: [perf-baseline.md](perf-baseline.md) § Fluid shell. ## 8. References diff --git a/lib/core/motion/querya_stagger.dart b/lib/core/motion/querya_stagger.dart index 7b698b47..654ceda7 100644 --- a/lib/core/motion/querya_stagger.dart +++ b/lib/core/motion/querya_stagger.dart @@ -3,6 +3,10 @@ import 'package:flutter/material.dart'; import 'querya_motion.dart'; import 'querya_motion_context.dart'; +/// Default per-child delay for [QueryaStagger] (physics/choreography constant, +/// not a surface morph token — see docs/motion-and-high-refresh.md). +const Duration kQueryaStaggerStep = Duration(milliseconds: 30); + /// Staggered fade-in for a fixed list — **first paint only**, capped at [maxStaggered]. /// /// Do not wrap virtualized / scrolling grids; use for history lists, recent @@ -12,7 +16,7 @@ class QueryaStagger extends StatefulWidget { super.key, required this.children, this.maxStaggered = 8, - this.step = const Duration(milliseconds: 30), + this.step = kQueryaStaggerStep, }); final List children;