feat: binary micro-interactions across the page
Section headlines are written out behind a column of digits, mono labels resolve from binary, the portrait assembles itself from bits, section indexes rattle and keep one bit alive, cards get corner marks, the header shows the scroll position as an eight-bit number, pressed links and buttons shed a few digits, and the work stage leans towards the pointer. All effects respect reduced motion and leave the content readable without JavaScript. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
import * as React from "react";
|
||||
import { BinaryTicker } from "@/src/components/bits/BinaryTicker";
|
||||
import { BitWipe } from "@/src/components/bits/BitWipe";
|
||||
import { DecodeText } from "@/src/components/bits/DecodeText";
|
||||
import { Reveal } from "@/src/components/Reveal";
|
||||
|
||||
interface BlockProps {
|
||||
@@ -32,22 +35,22 @@ export const Block: React.FC<BlockProps> = ({
|
||||
{index}
|
||||
</span>
|
||||
<span className="h-px w-10 bg-slate-300" />
|
||||
<span className="font-mono text-[11px] uppercase tracking-[0.25em] text-slate-500">
|
||||
{label}
|
||||
</span>
|
||||
<span
|
||||
<DecodeText
|
||||
text={label}
|
||||
className="font-mono text-[11px] uppercase tracking-[0.25em] text-slate-500"
|
||||
/>
|
||||
<BinaryTicker
|
||||
value={parseInt(index, 10)}
|
||||
alive
|
||||
className="ml-auto hidden font-mono text-[10px] tracking-[0.3em] text-slate-300 md:block"
|
||||
aria-hidden="true"
|
||||
>
|
||||
{parseInt(index, 10).toString(2).padStart(8, "0")}
|
||||
</span>
|
||||
/>
|
||||
</div>
|
||||
</Reveal>
|
||||
<Reveal delay={0.1}>
|
||||
<BitWipe delay={0.1}>
|
||||
<h2 className="m-0 max-w-6xl text-4xl font-bold leading-[0.95] tracking-tighter text-slate-900 md:text-7xl lg:text-[6.5rem]">
|
||||
{title}
|
||||
</h2>
|
||||
</Reveal>
|
||||
</BitWipe>
|
||||
<div className="mt-14 md:mt-24">{children}</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import * as React from "react";
|
||||
import { motion } from "framer-motion";
|
||||
import { Button } from "@/src/components/Button";
|
||||
import { DecodeText } from "@/src/components/bits/DecodeText";
|
||||
import { PathScene } from "@/src/components/illustrations/PathScenes";
|
||||
import { SERVICE_PATHS, type ServicePath } from "@/src/content/paths";
|
||||
|
||||
@@ -50,9 +51,11 @@ const PathStory: React.FC<{ path: ServicePath; active: boolean }> = ({
|
||||
<div className="md:order-2 md:col-span-7">
|
||||
<div className="relative overflow-hidden rounded-3xl bg-slate-900 md:sticky md:top-28">
|
||||
<div className="flex items-center justify-between border-b border-slate-800 px-5 py-4 md:px-7">
|
||||
<span className="font-mono text-[11px] uppercase tracking-[0.2em] text-slate-300">
|
||||
{current?.title}
|
||||
</span>
|
||||
<DecodeText
|
||||
key={current?.title}
|
||||
text={current?.title ?? ""}
|
||||
className="font-mono text-[11px] uppercase tracking-[0.2em] text-slate-300"
|
||||
/>
|
||||
<span className="font-mono text-[11px] tracking-[0.2em] text-slate-500">
|
||||
{step + 1} / {path.steps.length}
|
||||
</span>
|
||||
@@ -151,7 +154,7 @@ export const PathPicker: React.FC = () => {
|
||||
aria-selected={selected}
|
||||
aria-controls={`path-panel-${path.id}`}
|
||||
onClick={() => setActiveId(path.id)}
|
||||
className={`group flex h-full flex-col justify-between rounded-3xl border p-5 text-left transition-all duration-300 md:p-7 ${
|
||||
className={`bit-card group flex h-full flex-col justify-between rounded-3xl border p-5 text-left transition-all duration-300 md:p-7 ${
|
||||
selected
|
||||
? "border-slate-900 bg-slate-900 text-white"
|
||||
: "border-slate-200 bg-white text-slate-900 hover:-translate-y-1 hover:border-slate-400"
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
import * as React from "react";
|
||||
import Image from "next/image";
|
||||
import { motion } from "framer-motion";
|
||||
import { BitReveal } from "@/src/components/bits/BitReveal";
|
||||
import { BitWipe } from "@/src/components/bits/BitWipe";
|
||||
import { DecodeText } from "@/src/components/bits/DecodeText";
|
||||
|
||||
/**
|
||||
* PortraitSection: the introduction, with the portrait fading out of a dark surface
|
||||
@@ -22,8 +25,8 @@ export const PortraitSection: React.FC<{
|
||||
{/* Portrait: right side on wide screens, top on small ones. */}
|
||||
<motion.div
|
||||
className="relative h-[110vw] w-full md:absolute md:inset-y-0 md:right-0 md:h-auto md:w-[62%]"
|
||||
initial={{ opacity: 0, scale: 1.06 }}
|
||||
whileInView={{ opacity: 1, scale: 1 }}
|
||||
initial={{ scale: 1.06 }}
|
||||
whileInView={{ scale: 1 }}
|
||||
viewport={{ once: true, margin: "-10%" }}
|
||||
transition={{ duration: 1.4, ease: [0.16, 1, 0.3, 1] }}
|
||||
>
|
||||
@@ -39,6 +42,8 @@ export const PortraitSection: React.FC<{
|
||||
<div className="absolute inset-0 hidden bg-gradient-to-r from-slate-900 via-slate-900/75 to-slate-900/10 md:block" />
|
||||
<div className="absolute inset-x-0 bottom-0 h-2/5 bg-gradient-to-t from-slate-900 to-transparent" />
|
||||
<div className="absolute inset-x-0 top-0 h-24 bg-gradient-to-b from-slate-900 to-transparent" />
|
||||
{/* The portrait assembles itself out of binary digits. */}
|
||||
<BitReveal />
|
||||
</motion.div>
|
||||
|
||||
<div className="relative z-10 mx-auto w-full max-w-[1400px] px-5 pb-20 md:px-12 md:py-40">
|
||||
@@ -54,13 +59,16 @@ export const PortraitSection: React.FC<{
|
||||
{index}
|
||||
</span>
|
||||
<span className="h-px w-10 bg-slate-600" />
|
||||
<span className="font-mono text-[11px] uppercase tracking-[0.25em] text-slate-400">
|
||||
{label}
|
||||
</span>
|
||||
<DecodeText
|
||||
text={label}
|
||||
className="font-mono text-[11px] uppercase tracking-[0.25em] text-slate-400"
|
||||
/>
|
||||
</div>
|
||||
<h2 className="m-0 text-5xl font-bold leading-[0.95] tracking-tighter text-white md:text-7xl lg:text-[6.5rem]">
|
||||
{title}
|
||||
</h2>
|
||||
<BitWipe tone="light" delay={0.35}>
|
||||
<h2 className="m-0 text-5xl font-bold leading-[0.95] tracking-tighter text-white md:text-7xl lg:text-[6.5rem]">
|
||||
{title}
|
||||
</h2>
|
||||
</BitWipe>
|
||||
<div className="mt-10 md:mt-14">{children}</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user