feat(hero): refine light hero tech-sense with engineering grid and tuned ink links
浅色 Hero 科技感变体(HERO_VARIANT='grid'):墨色工程网格 + 品牌红节点 + 墨色细连线 连线 globalAlpha 上限 0.7→0.42,加边缘径向淡出(确定性,快照零漂移) 工程网格 CSS 加 radial mask 聚焦版心(呼应 McKinsey 穿透噪声) 清理死 CSS:移除 hero-dot-grid/hero-dot-spot 及 --hero-dot-* 变量 保留 --spot-x/--spot-y(spotlight 聚光复用) 门禁:type-check 0 / eslint 0 / 单测 17 passed
This commit is contained in:
@@ -5,7 +5,7 @@ import { motion } from 'framer-motion';
|
||||
import { ScrollReveal, StaggerReveal } from '@/components/ui/scroll-reveal';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import { HeroParticleField } from '@/components/sections/hero-particle-field';
|
||||
import { HeroParticleField, type HeroVariant } from '@/components/sections/hero-particle-field';
|
||||
import { ArrowRight, Lightbulb, Database, Layers, Code, Puzzle, Server, Quote, Calendar } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { EASE_OUT } from '@/components/ui/page-decoration';
|
||||
@@ -136,12 +136,23 @@ function StyledTitle({ lines }: { lines: (string | undefined)[] }) {
|
||||
|
||||
// ===== 品牌 CTA 按钮已抽离为可复用 UI 组件:@/components/ui/cta-button =====
|
||||
|
||||
// ===== Hero 区:浅色 editorial 画布 + 品牌红单电压 =====
|
||||
// 设计方向(2026-08-31 重设计,参考 Accenture Radical Relevance):
|
||||
// ===== Hero 区:浅色画布 + 精密工程网格科技感 + 品牌红单电压 =====
|
||||
// 设计方向(2026-08-31 重设计,参考 Accenture Radical Relevance;2026-09-01 科技感升级):
|
||||
// - 声明先行:H1 → 主张 → CTA,一屏只负责「一句话说清你是谁 + 一个行动」
|
||||
// - 数据指标下沉为独立成果带(HeroStatsBand),由滚动触发(Glance 层),不再挤在 hero 内
|
||||
// - 单一电压:hero 内只有品牌红一个彩色,其余全走中性 token
|
||||
// - 单一电压:hero 内只有品牌红一个彩色;连线走墨色(浅底)/中性灰(深底),不抢品牌红
|
||||
// - 字重收敛:大标题 700(原 900),对齐 Accenture「字重 9→3」的克制
|
||||
// - 科技感引擎:HeroParticleField 变体(固定种子、reduced-motion/自动化降级 → 快照零漂移)
|
||||
//
|
||||
// ===== HERO_VARIANT 观感开关(默认 'grid':浅色底 + 工程网格科技感)=====
|
||||
// 定调:Hero 保持浅色背景(与全站浅色咨询风一致),科技感由「精密工程网格 + 动态粒子 + 墨色细连线」承担,
|
||||
// 不做深色 Hero。深色变体保留待选(改这一行即生效,无需改其它代码):
|
||||
// 'grid' 浅色工程网格 + 品牌红漂移节点 + 墨色细连线 ← 默认落地
|
||||
// 'network' 深色节点网络(品牌红节点 + 中性灰连线)
|
||||
// 'constellation' 深色数据星图(品牌红脉冲节点 + 暗白次级点 + 竖向数据流)
|
||||
// 'spotlight' 深色聚光 + 粒子 + 工程网格(纵深最强,复用 L2 光标聚光)
|
||||
const HERO_VARIANT: HeroVariant = 'grid';
|
||||
|
||||
function HeroSection({ heroData }: {
|
||||
heroData?: Record<string, any> | null;
|
||||
}) {
|
||||
@@ -150,6 +161,12 @@ function HeroSection({ heroData }: {
|
||||
const siteConfig = useSiteConfig();
|
||||
const reduceMotion = useReducedMotion();
|
||||
|
||||
// 科技感变体开关(见文件顶部 HERO_VARIANT 注释):深色变体统一走深色画布 + 主题感知文字
|
||||
const dark = HERO_VARIANT !== 'grid';
|
||||
const showGrid = HERO_VARIANT === 'constellation' || HERO_VARIANT === 'spotlight'; // 深色工程网格
|
||||
const showLightGrid = HERO_VARIANT === 'grid'; // 浅色工程网格(墨色 hairline,精密质感)
|
||||
const showCursorGlow = HERO_VARIANT === 'spotlight';
|
||||
|
||||
const heading = heroData?.heading || heroData?.headingBottom || '让每一家企业都拥有数据驱动的决策能力';
|
||||
const subheading = heroData?.subheading || heroData?.description || '';
|
||||
const ctaLabel = heroData?.ctaLabel || '预约咨询';
|
||||
@@ -161,7 +178,7 @@ function HeroSection({ heroData }: {
|
||||
return (
|
||||
<section
|
||||
ref={containerRef}
|
||||
className="relative min-h-[90vh] flex items-center overflow-hidden bg-bg-primary"
|
||||
className={`relative min-h-[90vh] flex items-center overflow-hidden ${dark ? 'bg-dark-bg text-white' : 'bg-bg-primary'}`}
|
||||
data-testid="hero-section"
|
||||
onPointerMove={(e) => {
|
||||
if (!spotRef.current || !containerRef.current) return;
|
||||
@@ -170,21 +187,25 @@ function HeroSection({ heroData }: {
|
||||
spotRef.current.style.setProperty('--spot-y', `${e.clientY - rect.top}px`);
|
||||
}}
|
||||
>
|
||||
{/* L1 静态点阵:token 化(颜色/alpha 随主题反色),深底自动切中性浅灰 */}
|
||||
<div className="absolute inset-0 pointer-events-none hero-dot-grid" aria-hidden="true" />
|
||||
{/* L2 光标聚光(Skim 层):mask 跟随鼠标,仅写 2 个 CSS 变量,无 canvas、无逐帧 JS;
|
||||
reduced-motion 下不渲染,避免动态 */}
|
||||
{!reduceMotion && (
|
||||
<div ref={spotRef} className="absolute inset-0 pointer-events-none hero-dot-spot opacity-60" aria-hidden="true" />
|
||||
{/* L1 工程网格:浅底墨色 hairline(grid)/ 深底白色 hairline(constellation、spotlight) */}
|
||||
{showLightGrid && (
|
||||
<div className="absolute inset-0 pointer-events-none hero-grid-overlay--light" aria-hidden="true" />
|
||||
)}
|
||||
{/* L3 动态粒子(品牌红点缀):rAF 持续循环漂移;
|
||||
reduced-motion / 自动化环境下降级为一次性静态帧 */}
|
||||
<HeroParticleField />
|
||||
{showGrid && (
|
||||
<div className="absolute inset-0 pointer-events-none hero-grid-overlay--dark" aria-hidden="true" />
|
||||
)}
|
||||
{/* L2 品牌红光标聚光(仅 spotlight 变体 + 非 reduced-motion):跟随鼠标,仅写 2 个 CSS 变量,无 canvas、无逐帧 JS */}
|
||||
{showCursorGlow && !reduceMotion && (
|
||||
<div ref={spotRef} className="absolute inset-0 pointer-events-none hero-spot-glow opacity-70" aria-hidden="true" />
|
||||
)}
|
||||
{/* L3 动态粒子(品牌红点缀 + 科技感变体):rAF 持续循环漂移;
|
||||
reduced-motion / 自动化环境下降级为一次性静态帧(连线/星图位置由固定种子复现 → 快照零漂移) */}
|
||||
<HeroParticleField variant={HERO_VARIANT} dark={dark} />
|
||||
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10 w-full py-16 sm:py-20 md:py-24 lg:py-24">
|
||||
<div className="grid items-center gap-16">
|
||||
<div className="max-w-4xl">
|
||||
{/* 品牌口号 Badge:浅色画布上的品牌红信号(hero 不重复渲染 Logo,避免与导航栏重复) */}
|
||||
{/* 品牌口号 Badge:画布上的品牌红信号(深底走 brand-light 保证对比度;hero 不重复渲染 Logo,避免与导航栏重复) */}
|
||||
{slogan && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
@@ -192,18 +213,18 @@ function HeroSection({ heroData }: {
|
||||
transition={{ duration: 0.35, delay: 0.03, ease: EASE_OUT }}
|
||||
className="mb-6"
|
||||
>
|
||||
<span className="inline-flex items-center gap-2 px-3 py-1.5 rounded-full bg-brand/5 text-brand text-sm font-medium border border-brand/15">
|
||||
<span className={`inline-flex items-center gap-2 px-3 py-1.5 rounded-full text-sm font-medium border ${dark ? 'bg-brand/10 text-brand-light border-brand/30' : 'bg-brand/5 text-brand border-brand/15'}`}>
|
||||
{slogan}
|
||||
</span>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{/* 主标题:大胆、直接(浅色画布上的墨色宣言) */}
|
||||
{/* 主标题:大胆、直接(深底白色 / 浅底墨色,随 HERO_VARIANT 切换) */}
|
||||
<motion.h1
|
||||
initial={{ opacity: 0, y: 40 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.45, delay: 0.06, ease: EASE_OUT }}
|
||||
className="text-4xl sm:text-5xl md:text-6xl lg:text-6xl 2xl:text-7xl font-bold text-ink leading-[1.05] tracking-tight mb-7 sm:mb-8"
|
||||
className={`text-4xl sm:text-5xl md:text-6xl lg:text-6xl 2xl:text-7xl font-bold leading-[1.05] tracking-tight mb-7 sm:mb-8 ${dark ? 'text-white' : 'text-ink'}`}
|
||||
>
|
||||
{heading}
|
||||
</motion.h1>
|
||||
@@ -214,7 +235,7 @@ function HeroSection({ heroData }: {
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.35, delay: 0.16, ease: EASE_OUT }}
|
||||
className="text-lg sm:text-xl text-text-secondary max-w-2xl leading-relaxed mb-10"
|
||||
className={`text-lg sm:text-xl max-w-2xl leading-relaxed mb-10 ${dark ? 'text-white/70' : 'text-text-secondary'}`}
|
||||
>
|
||||
{subheading}
|
||||
</motion.p>
|
||||
@@ -232,7 +253,7 @@ function HeroSection({ heroData }: {
|
||||
<a
|
||||
href={secondaryCtaHref}
|
||||
data-testid="hero-secondary-link"
|
||||
className="group inline-flex items-center gap-2 text-sm font-medium text-text-secondary hover:text-ink transition-colors duration-200 py-4"
|
||||
className={`group inline-flex items-center gap-2 text-sm font-medium transition-colors duration-200 py-4 ${dark ? 'text-white/70 hover:text-white' : 'text-text-secondary hover:text-ink'}`}
|
||||
>
|
||||
{secondaryCtaLabel}
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-300 group-hover:translate-x-1" />
|
||||
|
||||
Reference in New Issue
Block a user