perf(motion): 第二批入场动效时长收敛至 300ms(4 文件 21 处)

承接 8fb5aae,继续清理 Task #16 的 P0 硬违规(>700ms 明确禁止):

- contact-content-v3 (7) / case-detail-page (6) / product-detail-content-v3 (5) /
  detail-hero (3 处入场)
- 审计:P0 54 → 33,P1 163 持平,P2 28 持平
- 只改 duration,保留原 delay(与首批先例一致);改动行已逐行核验为纯动效行

验证:
- tsc --noEmit 0 error;eslint 4 个改动文件 0 error
- 单测 131 套件 / 1662 通过 / 2 跳过 / EXIT=0(与基线一致)
- 视觉基线零变动:reducedMotion+animations disabled 下终态一致,
  时长改动不改变最终像素;不带 -u 复跑 92 用例 EXIT=0
This commit is contained in:
2026-09-03 18:54:16 +08:00
parent c9df2e40c5
commit 8117dba865
4 changed files with 21 additions and 21 deletions
+3 -3
View File
@@ -101,7 +101,7 @@ export function DetailHero({
y: 0,
filter: 'blur(0px)',
transition: {
duration: 0.9,
duration: 0.3,
ease: [0.22, 1, 0.36, 1] as const,
},
},
@@ -120,7 +120,7 @@ export function DetailHero({
opacity: 1,
y: 0,
transition: {
duration: 0.75,
duration: 0.3,
delay: 0.25,
ease: [0.22, 1, 0.36, 1] as const,
},
@@ -189,7 +189,7 @@ export function DetailHero({
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 1.5, duration: 0.8 }}
transition={{ delay: 1.5, duration: 0.3 }}
className="absolute bottom-8 left-1/2 -translate-x-1/2"
>
<motion.div
+6 -6
View File
@@ -85,7 +85,7 @@ function CaseDetailHero({ data }: CaseDetailHeroProps) {
className="mb-8"
initial={shouldReduceMotion ? {} : { opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.1, ease: EASE }}
transition={{ duration: 0.3, delay: 0.1, ease: EASE }}
>
<div
className="font-sans text-[clamp(56px,12vw,120px)] font-black leading-none tracking-[-2px] mb-2"
@@ -105,7 +105,7 @@ function CaseDetailHero({ data }: CaseDetailHeroProps) {
className="font-sans text-[clamp(28px,5vw,48px)] font-bold leading-[1.15] tracking-[-0.5px] text-[var(--color-text-primary)] mb-6 max-w-3xl"
initial={shouldReduceMotion ? {} : { opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.9, delay: 0.25, ease: EASE }}
transition={{ duration: 0.3, delay: 0.25, ease: EASE }}
>
{data.title}
</motion.h1>
@@ -115,7 +115,7 @@ function CaseDetailHero({ data }: CaseDetailHeroProps) {
style={{ color: 'var(--color-text-secondary)' }}
initial={shouldReduceMotion ? {} : { opacity: 0, y: 24 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.4, ease: EASE }}
transition={{ duration: 0.3, delay: 0.4, ease: EASE }}
>
{data.subtitle}
</motion.p>
@@ -125,7 +125,7 @@ function CaseDetailHero({ data }: CaseDetailHeroProps) {
className="grid grid-cols-3 gap-6 sm:gap-10 max-w-lg mb-10"
initial={shouldReduceMotion ? {} : { opacity: 0, y: 24 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.55, ease: EASE }}
transition={{ duration: 0.3, delay: 0.55, ease: EASE }}
>
{data.metrics.slice(1, 4).map((m, i) => (
<div key={i}>
@@ -147,7 +147,7 @@ function CaseDetailHero({ data }: CaseDetailHeroProps) {
className="flex flex-wrap gap-x-6 gap-y-3 text-sm mb-10 border-y border-border-primary py-4"
initial={shouldReduceMotion ? {} : { opacity: 0, y: 24 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.65, ease: EASE }}
transition={{ duration: 0.3, delay: 0.65, ease: EASE }}
>
{data.projectDuration && (
<div style={{ color: 'var(--color-text-secondary)' }}>
@@ -173,7 +173,7 @@ function CaseDetailHero({ data }: CaseDetailHeroProps) {
className="flex flex-wrap gap-4"
initial={shouldReduceMotion ? {} : { opacity: 0, y: 24 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.8, ease: EASE }}
transition={{ duration: 0.3, delay: 0.8, ease: EASE }}
>
<Button size="lg" asChild>
<StaticLink href="/contact">