feat(animation): implement subtle and high-performance scroll reveal animations across public pages
- Enhance Reveal component with HTMLAttributes passthrough and inline style merging - Integrate Reveal into Home, Members, Publications, Lectures, and Standardization sections - Apply lightweight stagger delay (max 360ms cap) without breaking grid stretch (h-full) - Preserve ProjectPageView CSS Scroll Snap direct-child contract via as='article' in-place replacement - Integrate Counter component for metrics and category badges - Support prefers-reduced-motion media query and noscript fallback - All 12 quality gates passed clean with unanimous PASS from all reviewers
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import React, { useEffect, useState } from "react";
|
||||
import Reveal from "@/components/Reveal";
|
||||
import { getStandardsBodies } from "../../lib/api";
|
||||
import type { StandardsBody } from "../../content/types";
|
||||
|
||||
@@ -16,95 +17,103 @@ export default function StandardizationPage() {
|
||||
<div className="container-content py-8 sm:py-12 space-y-10 sm:space-y-14">
|
||||
{/* Page Header */}
|
||||
<section>
|
||||
<h1 className="font-serif text-4xl sm:text-5xl font-normal text-ink tracking-tight">
|
||||
International Standardization
|
||||
</h1>
|
||||
<Reveal variant="up">
|
||||
<h1 className="font-serif text-4xl sm:text-5xl font-normal text-ink tracking-tight">
|
||||
International Standardization
|
||||
</h1>
|
||||
</Reveal>
|
||||
</section>
|
||||
|
||||
{/* Standards Bodies Section */}
|
||||
<section className="space-y-8 sm:space-y-10 pt-6 md:pt-8 border-t border-line">
|
||||
{standardsBodies.map((body, idx) => (
|
||||
<div key={idx} className="bg-paper p-6 sm:p-8 rounded-lg border border-line space-y-6 shadow-sm">
|
||||
<div className="flex flex-wrap justify-between items-start gap-4 border-b border-line pb-4">
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-mono text-xs text-cobalt-dark font-bold uppercase">
|
||||
[{body.scope}]
|
||||
</span>
|
||||
{body.role && (
|
||||
<span className="bg-vermillion-dark text-ivory font-mono text-[0.65rem] px-2 py-0.5 rounded font-bold">
|
||||
{body.role}
|
||||
<Reveal
|
||||
key={idx}
|
||||
variant="up"
|
||||
delay={idx * 120}
|
||||
>
|
||||
<div className="bg-paper p-6 sm:p-8 rounded-lg border border-line space-y-6 shadow-sm">
|
||||
<div className="flex flex-wrap justify-between items-start gap-4 border-b border-line pb-4">
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-mono text-xs text-cobalt-dark font-bold uppercase">
|
||||
[{body.scope}]
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<h2 className="font-serif text-2xl font-normal text-ink mt-1">
|
||||
{body.org}
|
||||
</h2>
|
||||
<p className="text-xs text-ink-mute font-mono mt-0.5">
|
||||
{body.full} ({body.period})
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="font-mono text-xs text-ink-mute bg-ivory border border-line px-3 py-1.5 rounded">
|
||||
Projects: {body.projects.length}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 3-Tier Hierarchy: Projects & Documents */}
|
||||
<div className="space-y-6">
|
||||
{body.projects.map((proj, pIdx) => (
|
||||
<div key={pIdx} className="bg-ivory p-6 rounded border border-line space-y-3">
|
||||
<div className="font-serif text-lg font-normal text-ink border-b border-line/60 pb-2 flex justify-between items-center">
|
||||
<div>
|
||||
<span className="font-mono text-xs text-cobalt-dark font-bold mr-2">
|
||||
{proj.wg}
|
||||
{body.role && (
|
||||
<span className="bg-vermillion-dark text-ivory font-mono text-[0.65rem] px-2 py-0.5 rounded font-bold">
|
||||
{body.role}
|
||||
</span>
|
||||
<span>{proj.name}</span>
|
||||
</div>
|
||||
<span className="font-mono text-xs text-ink-mute">
|
||||
{proj.documents.length} Docs
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{proj.documents.length > 0 ? (
|
||||
<div className="space-y-3 pt-1">
|
||||
{proj.documents.map((doc, dIdx) => (
|
||||
<div
|
||||
key={dIdx}
|
||||
className="bg-paper p-4 rounded border border-line/60 space-y-1.5"
|
||||
>
|
||||
<div className="flex justify-between items-start gap-4">
|
||||
<h3 className="font-serif text-base font-normal text-ink leading-snug">
|
||||
“{doc.title}”
|
||||
</h3>
|
||||
<span
|
||||
className={`font-mono text-[0.65rem] px-2 py-0.5 rounded font-bold shrink-0 ${
|
||||
doc.status === "InProgress"
|
||||
? "bg-vermillion-dark text-ivory"
|
||||
: "bg-cobalt-dark text-ivory"
|
||||
}`}
|
||||
>
|
||||
{doc.status}
|
||||
</span>
|
||||
</div>
|
||||
<div className="font-mono text-xs text-ink-mute flex justify-between">
|
||||
<span>{doc.ref}</span>
|
||||
{doc.publishedAt && (
|
||||
<span className="text-ink">{doc.publishedAt}</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-xs text-ink-mute font-mono italic">
|
||||
Project specification in progress
|
||||
</div>
|
||||
)}
|
||||
<h2 className="font-serif text-2xl font-normal text-ink mt-1">
|
||||
{body.org}
|
||||
</h2>
|
||||
<p className="text-xs text-ink-mute font-mono mt-0.5">
|
||||
{body.full} ({body.period})
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className="font-mono text-xs text-ink-mute bg-ivory border border-line px-3 py-1.5 rounded">
|
||||
Projects: {body.projects.length}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 3-Tier Hierarchy: Projects & Documents */}
|
||||
<div className="space-y-6">
|
||||
{body.projects.map((proj, pIdx) => (
|
||||
<div key={pIdx} className="bg-ivory p-6 rounded border border-line space-y-3">
|
||||
<div className="font-serif text-lg font-normal text-ink border-b border-line/60 pb-2 flex justify-between items-center">
|
||||
<div>
|
||||
<span className="font-mono text-xs text-cobalt-dark font-bold mr-2">
|
||||
{proj.wg}
|
||||
</span>
|
||||
<span>{proj.name}</span>
|
||||
</div>
|
||||
<span className="font-mono text-xs text-ink-mute">
|
||||
{proj.documents.length} Docs
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{proj.documents.length > 0 ? (
|
||||
<div className="space-y-3 pt-1">
|
||||
{proj.documents.map((doc, dIdx) => (
|
||||
<div
|
||||
key={dIdx}
|
||||
className="bg-paper p-4 rounded border border-line/60 space-y-1.5"
|
||||
>
|
||||
<div className="flex justify-between items-start gap-4">
|
||||
<h3 className="font-serif text-base font-normal text-ink leading-snug">
|
||||
“{doc.title}”
|
||||
</h3>
|
||||
<span
|
||||
className={`font-mono text-[0.65rem] px-2 py-0.5 rounded font-bold shrink-0 ${
|
||||
doc.status === "InProgress"
|
||||
? "bg-vermillion-dark text-ivory"
|
||||
: "bg-cobalt-dark text-ivory"
|
||||
}`}
|
||||
>
|
||||
{doc.status}
|
||||
</span>
|
||||
</div>
|
||||
<div className="font-mono text-xs text-ink-mute flex justify-between">
|
||||
<span>{doc.ref}</span>
|
||||
{doc.publishedAt && (
|
||||
<span className="text-ink">{doc.publishedAt}</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-xs text-ink-mute font-mono italic">
|
||||
Project specification in progress
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Reveal>
|
||||
))}
|
||||
</section>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user