One phrase strobing through the corners of the type space on a fixed interval, never settling: KT Flux thin (wght 200) against heavy (600), and its SRIF axis at 100 against 500 -- sans against serif out of the same file -- plus true Mincho upright and oblique. Each tick picks a random frame and steps past a repeat, so the word always visibly changes. All frames render stacked in one inline-grid cell with baseline alignment and line-height 1: the widest locks the span's width, so the sentence around it never reflows horizontally or pumps vertically as faces swap, and only the shown frame drops its visibility. Japanese has no Flux glyphs, so it alternates Mincho weights against a system gothic instead. Reduced motion holds a single frame.
We are a design collective.
Source
"use client";
import { useState } from "react";
import FontFlicker from "@/components/FontFlicker";
import DraggablePanel from "../DraggablePanel";
import { PanelSelect, PanelToggle } from "../_kansei/controls";
import ScrambleLink from "../ScrambleLink";
/* The reels-caption flicker: one phrase strobes through the corners of the type
space and never settles — KT Flux thin/heavy against its own SRIF (sans ⇄
serif) axis, plus true Mincho upright and oblique. Every frame renders
stacked in one inline-grid cell, so the widest locks the width and the
sentence around it never reflows as the faces swap. Japanese can't ride Flux
(Latin only), so it alternates Mincho weights against a gothic instead. */
type Lang = "en" | "jp";
const SENTENCE = {
en: { before: "We are a ", word: "new age", after: " design collective." },
jp: { before: "私たちは、", word: "新しい世代", after: "のデザインコレクティブです。" },
};
export default function FlickerType() {
const [lang, setLang] = useState<Lang>("en");
const [period, setPeriod] = useState(240);
const [still, setStill] = useState(false);
const copy = SENTENCE[lang];
return (
<div
className="fixed inset-0 flex flex-col items-center justify-center overflow-hidden px-8"
style={{ background: "var(--paper)", color: "var(--ink)" }}
>
<p
className="max-w-[22ch] text-center text-[clamp(24px,4.2vw,54px)] leading-[1.35]"
style={{
fontFamily: lang === "jp" ? "var(--mincho)" : "var(--flux)",
fontVariationSettings: lang === "jp" ? "normal" : '"wght" 300, "SRIF" 100',
}}
>
{copy.before}
<FontFlicker
key={`${lang}-${period}-${still}`}
text={copy.word}
jp={lang === "jp"}
period={period}
still={still}
/>
{copy.after}
</p>
<DraggablePanel
isLight={false}
controls={[
{
label: "Period · ms",
value: period,
set: (v) => setPeriod(Math.round(v)),
min: 80,
max: 800,
step: 20,
},
]}
>
<PanelSelect
label="Language"
value={lang}
options={["en", "jp"] as const}
set={setLang}
isLight={false}
/>
<PanelToggle label="Freeze" value={still} set={setStill} isLight={false} />
</DraggablePanel>
<div className="fixed bottom-6 left-6 z-10">
<ScrambleLink
from="FONT FLICKER"
to="← LAB"
href="/lab"
className="text-[11px] tracking-[0.1em] text-foreground/30 uppercase hover:text-foreground/60 transition-colors"
style={{ fontVariationSettings: "'wght' 400, 'SRIF' 100" }}
/>
</div>
</div>
);
}