Files
landing_page/refer_landing_page/app/publications/page.tsx
T
Godopu f3972cac27 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
2026-08-26 00:11:24 +09:00

97 lines
3.4 KiB
TypeScript

"use client";
import React, { useEffect, useState } from "react";
import Reveal from "@/components/Reveal";
import { CategoryNav } from "./_components/CategoryNav";
import { getPublications, getPatents } from "../../lib/api";
import type { Publication, Patent } from "../../content/types";
export default function PublicationsIndexPage() {
const [publications, setPublications] = useState<Publication[]>([]);
const [patents, setPatents] = useState<Patent[]>([]);
useEffect(() => {
getPublications().then((p) => {
if (p) setPublications(p);
});
getPatents().then((pat) => {
if (pat) setPatents(pat);
});
}, []);
const counts = {
"intl-journal-conf": publications.filter((p) => p.category === "intl-journal-conf").length,
"domestic-journal-conf": publications.filter((p) => p.category === "domestic-journal-conf").length,
patent: patents.length,
};
// Selected representative publications (curated via database isHighlight flag)
const highlights = publications.filter((p) => p.isHighlight);
return (
<div className="container-content py-8 sm:py-12 space-y-10 sm:space-y-14">
{/* Page Header */}
<section>
<Reveal variant="up">
<h1 className="font-serif text-4xl sm:text-5xl font-normal text-ink tracking-tight">
PUBLICATIONS
</h1>
</Reveal>
</section>
{/* Category Summary Cards */}
<section className="pt-6 md:pt-8 border-t border-line">
<CategoryNav counts={counts} />
</section>
{/* Highlights Section */}
<section className="space-y-6 pt-6 md:pt-8 border-t border-line">
<Reveal variant="up">
<h2 className="font-serif text-2xl sm:text-3xl font-normal text-cobalt-dark">
Highlights
</h2>
</Reveal>
<div className="divide-y divide-line border border-line bg-paper rounded-lg overflow-hidden shadow-sm">
{highlights.map((pub, idx) => (
<Reveal
key={`${pub.category}-${idx}`}
as="article"
variant="up"
delay={Math.min(idx, 6) * 60}
className="p-5 hover:bg-ivory/60 transition-colors space-y-2"
>
<div className="flex flex-wrap items-center gap-2 text-xs font-mono text-ink-mute">
<span className="px-2 py-0.5 rounded bg-ivory border border-line text-ink font-bold">
{pub.publishedAt?.substring(0, 7) || "Recent"}
</span>
<span>·</span>
<span className="capitalize">{pub.category.replace(/-/g, " ")}</span>
{pub.doi && (
<>
<span>·</span>
<span className="text-vermillion-dark">DOI: {pub.doi}</span>
</>
)}
</div>
<h3 className="font-serif text-base font-normal text-ink leading-snug">
{pub.title}
</h3>
{pub.authors && (
<p className="text-xs text-ink-mute">
{pub.authors}
</p>
)}
{pub.venue && (
<p className="text-xs italic text-ink-mute">
{pub.venue}{pub.volume ? `, ${pub.volume}` : ""}
</p>
)}
</Reveal>
))}
</div>
</section>
</div>
);
}