'use client'
// 21st's CLI points this import at its own copy of the component when it publishes.
import InkReveal, { type Origin, type Trigger } from '@/components/ui/ink-reveal'
const settings = {
trigger: 'hover',
origin: 'pointer',
ease: 'ink',
duration: 1200,
progress: 0.5,
rest: 0.2,
feather: 0.14,
grain: 0.3,
noiseScale: 5,
inkColor: '#1b1613',
// each print rests on its partner instead of a faint wash: Tōhaku's two screens, Sesshū's two landscapes
paired: false,
}
const PARTNER = [2, 3, 0, 1]
const WORKS = [
{
slug: 'pine-trees-right',
title: 'Pine Trees, right screen',
by: 'Hasegawa Tōhaku, late 16th c.',
src: 'https://cdn.21st.dev/assets/mirror/5d/5d25798f2399889aed4ec167bb9992f09d8f8a6ef7a67646c0344f91d1a7aba5.jpg',
alt: 'Pine trees emerging from mist, painted in ink on a folding screen',
},
{
slug: 'splashed-ink-landscape',
title: 'Splashed-ink landscape',
by: 'Sesshū Tōyō, 1495',
src: 'https://cdn.21st.dev/assets/mirror/21/212cd919b2d9976a978f3f3e75bf85a8872d4b08627136ac17f5bfb4bf531d53.jpg',
alt: 'A mountain landscape in loose splashed ink, with a building and a figure in a boat',
},
{
slug: 'pine-trees-left',
title: 'Pine Trees, left screen',
by: 'Hasegawa Tōhaku, late 16th c.',
src: 'https://cdn.21st.dev/assets/mirror/f6/f6517f20aa55be6babbfd8c2d889553a270b5e8cb844e7071994b2e959ceab35.jpg',
alt: 'Pine trees and a distant snowy peak in ink, from the left folding screen',
},
{
slug: 'winter-landscape',
title: 'Landscape of Four Seasons: Winter',
by: 'attributed to Sesshū Tōyō, 15th c.',
src: 'https://cdn.21st.dev/assets/mirror/26/26b2dbaa7415a67e33b7a84327f77e0cdc9a0a56bff7df3030533916276cade4.jpg',
alt: 'A winter landscape in ink: cliffs, bare trees and a temple roof under snow',
},
]
const HINT: Record<string, string> = {
hover: 'Hover or tab to a print',
inView: 'Scroll a print into view',
scroll: 'Scroll the prints up the page',
manual: 'Scrub the progress control',
}
export default function Demo(props: Partial<typeof settings> & { src?: string }) {
const s = { ...settings, ...props }
const scrolling = s.trigger === 'scroll'
return (
<div className="min-h-screen w-full bg-background px-6 py-16 text-foreground md:px-10">
<div className="mx-auto max-w-6xl">
{scrolling ? (
<p className="flex h-[65svh] items-end pb-10 font-mono text-[11px] uppercase tracking-[0.18em] text-muted-foreground">Scroll down: the prints develop as they rise</p>
) : null}
<header className="mb-10 flex flex-wrap items-end justify-between gap-6">
<div>
<p className="font-mono text-[11px] uppercase tracking-[0.18em] text-muted-foreground">Ink reveal · {HINT[s.trigger] ?? HINT.hover}</p>
<h2 className="mt-3 font-serif text-4xl leading-tight tracking-[-0.01em] md:text-5xl">Four prints, developed on contact.</h2>
</div>
<p className="max-w-xs text-sm text-muted-foreground">
{s.paired
? 'Each print rests on its partner and the other inks in over it. All four cards draw through one WebGL context.'
: 'The ink blooms from where you come in and pools at its edge. All four cards draw through one WebGL context.'}
</p>
</header>
<ul className="grid grid-cols-2 gap-4 md:grid-cols-4 md:gap-6">
{WORKS.map((w, i) => (
<li key={w.slug}>
<a
id={w.slug}
href={`#${w.slug}`}
className="group block rounded-lg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-4 focus-visible:ring-offset-background"
>
<InkReveal
src={props.src ?? w.src}
restSrc={s.paired && !props.src ? WORKS[PARTNER[i]!]!.src : undefined}
alt={w.alt}
trigger={s.trigger as Trigger}
origin={s.origin as Origin}
ease={s.ease}
duration={s.duration}
progress={s.progress}
rest={s.rest}
feather={s.feather}
grain={s.grain}
noiseScale={s.noiseScale}
inkColor={s.inkColor}
aspectRatio="3 / 4"
className="rounded-lg bg-background"
/>
<p className="mt-3 font-serif text-lg leading-snug">{w.title}</p>
<p className="text-xs text-muted-foreground">{w.by}</p>
</a>
</li>
))}
</ul>
<p className="mt-10 text-xs text-muted-foreground">All four works are in the public domain. Images from Wikimedia Commons.</p>
{scrolling ? <div className="h-[60svh]" /> : null}
</div>
</div>
)
}