'use client'; import * as React from 'react'; import { ArrowRight } from 'lucide-react'; import { cn } from '@/lib/utils'; /** * CTAButton — 全站统一的「行动召唤」组件 * * 设计意图(见 .impeccable.md / Phase B P5): * - Pill 化(rounded-full),与项目 Button 组件 size 体系一致 * - 品牌箭头签名化:内置 ArrowRight,hover 时 translate-x 形成微交互 * - 四变体覆盖全站 CTA 场景,避免"全是大红 pill"的 UI 噪音: * - primary:品牌红填充 pill + 大箭头(hero 主行动 / 底部大 CTA) * - secondary:描边墨色 pill + 大箭头(浅色 section 次行动 / 跳转按钮) * - dark:描边浅色 pill + 大箭头(深色区块(bg-dark-bg)内的次行动,如 brand/team 底部 CTA) * - inline:透明 + 小箭头 + 文字色(卡片内"了解更多"轻量次行动) * * dark 变体于 2026-08-31 P5 批次 4 新增:brand/team 底部深色 CTA 区块的次行动此前用 * text-dark-text-primary + border-dark-border 手写描边,现统一进组件,避免深色背景上误用 * secondary(text-ink)导致不可见。 * - 200-300ms transition(动效四原则区间内) * - 主行动(primary)触达品牌红 #C41E3A 单电压,遵循"每页 ≥ 3 处品牌红触达点,面积 ≤ 10%"约束 * * 抽离自 src/app/(marketing)/home-content-v15.tsx (2026-08-31),原 primary/secondary 行为完全保留; * 新增 inline 变体支持次行动场景;data-testid 透传避免破坏既有测试快照。 */ export type CTAButtonVariant = 'primary' | 'secondary' | 'dark' | 'inline'; export interface CTAButtonProps { children: React.ReactNode; href: string; variant?: CTAButtonVariant; className?: string; dataTestId?: string; /** 内部 span 的额外类名(用于覆盖默认间距/字号等极端定制场景) */ innerClassName?: string; } const VARIANT_STYLES: Record = { primary: 'bg-brand text-white hover:bg-brand-hover px-10 py-4 font-semibold text-base', secondary: 'text-ink border border-ink/20 hover:border-ink/40 hover:bg-ink/5 px-10 py-4 font-semibold text-base', dark: 'text-dark-text-primary border border-dark-border hover:border-dark-text-muted hover:bg-white/5 px-10 py-4 font-semibold text-base', inline: 'text-text-primary hover:text-brand px-0 py-0 font-medium text-sm bg-transparent border-0', }; const ARROW_STYLES: Record = { primary: 'w-5 h-5 transition-transform duration-300 group-hover:translate-x-2', secondary: 'w-5 h-5 transition-transform duration-300 group-hover:translate-x-2', dark: 'w-5 h-5 transition-transform duration-300 group-hover:translate-x-2', inline: 'w-4 h-4 transition-transform duration-300 group-hover:translate-x-1', }; export function CTAButton({ children, href, variant = 'primary', className, dataTestId, innerClassName, }: CTAButtonProps) { const isPill = variant !== 'inline'; return ( {children} ); } export default CTAButton;