Files
novalon-website/src/components/detail/detail-cta-section.tsx
T
zhangxiangand阿睿 2aa0e21319 refactor(animations): converge P1 motion durations to ≤300ms target
- 151 scripted + 1 manual duration fixes across 46 files
- framer entrance 0.5/0.6s -> 0.3s
- Tailwind hover -> duration-150, entrance -> duration-300
- preserve flip-clock/page-transition per semantic decision
- design-system.ts dead-code deferred
- P1 violations 156 -> 5; P0 remains 0; OK class 249 -> 400
- verified: tsc clean, eslint 0 errors
- verified: 130/130 jest suites, 1573 passed
- verified: visual regression 46/46 zero-pixel diff

Co-Authored-By: 阿睿 <workbuddy@tencent.com>
2026-09-20 11:50:58 +08:00

89 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { motion } from 'framer-motion';
import { ArrowRight, MessageCircle } from 'lucide-react';
import type { HeroTheme } from '@/lib/constants/hero-themes';
interface DetailCTASectionProps {
theme: HeroTheme;
title?: string;
description?: string;
primaryAction: { label: string; href: string };
secondaryAction?: { label: string; href: string };
}
export function DetailCTASection({
theme: _theme,
title = '准备好开始了吗?',
description = '联系我们,获取专属方案和报价',
primaryAction,
secondaryAction,
}: DetailCTASectionProps) {
return (
<section className="relative py-24 sm:py-32 md:py-40 overflow-hidden bg-brand-section">
{/* 背景纹理 */}
<div className="absolute inset-0 pointer-events-none opacity-[0.04]"
style={{
backgroundImage: `radial-gradient(circle at 25% 25%, rgba(255,255,255,0.3) 1px, transparent 1px)`,
backgroundSize: '48px 48px',
}}
/>
<div className="absolute inset-0 pointer-events-none">
<div className="absolute top-1/3 right-1/4 w-[500px] h-[500px] bg-white/[0.03] rounded-full blur-[140px]" />
</div>
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10">
<motion.div
initial={{ opacity: 0, y: 32 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-100px' }}
transition={{ duration: 0.3, ease: [0.22, 1, 0.36, 1] }}
className="max-w-3xl"
>
{/* 标签 */}
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-white/10 text-white/80 text-sm font-medium mb-8 border border-white/20">
<MessageCircle className="w-4 h-4" />
免费咨询
</div>
<h2 className="text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-black text-white tracking-tight leading-[0.95] mb-10">
{title}
</h2>
<p className="text-lg md:text-xl text-white/70 max-w-2xl leading-relaxed mb-12">
{description}
</p>
<div className="flex flex-col sm:flex-row items-start sm:items-center gap-5">
<a
href={primaryAction.href}
className="group inline-flex items-center gap-3 px-10 py-4 bg-white text-brand font-bold text-base hover:bg-white/90 transition-all duration-200"
>
<span>{primaryAction.label}</span>
<ArrowRight className="w-5 h-5 transition-transform duration-300 group-hover:translate-x-1" />
</a>
{secondaryAction && (
<a
href={secondaryAction.href}
className="group inline-flex items-center gap-2.5 px-8 py-4 text-white/80 font-semibold text-sm border border-white/30 hover:border-white/60 hover:text-white hover:bg-white/10 transition-all duration-200"
>
{secondaryAction.label}
</a>
)}
</div>
<motion.p
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
transition={{ delay: 0.5, duration: 0.3 }}
className="mt-10 text-sm text-white/50"
>
平均响应时间 &lt; 2小时 · 7×24小时技术支持 · 无需预付费用
</motion.p>
</motion.div>
</div>
</section>
);
}