Split witness with center-stage capability focus, blur handoff, and icon chips — logo-cloud-10 DNA for registry workflows.
@nusaiba
registry/blocks/features/10/features-blur-section.tsx
"use client";
import { useCallback, useEffect, useState } from "react";
import type { LucideIcon } from "lucide-react";
import {
ClipboardCopyIcon,
EyeIcon,
KeyRoundIcon,
SparklesIcon,
SquareTerminalIcon,
} from "lucide-react";
import { AnimatePresence, motion, useInView, useReducedMotion } from "motion/react";
import { defaultSpring, motionViewport } from "@/lib/motion-tokens";
import { cn } from "@/lib/utils";
import { SectionShell, ContentRail } from "@/components/layout-contract";
const CYCLE_MS = 3800;
type Capability = {
id: string;
label: string;
detail: string;
icon: LucideIcon;
};
const capabilities: Capability[] = [
{
id: "motion",
label: "Motion",
detail: "40 live patterns · spring tokens",
icon: SparklesIcon,
},
{
id: "cli",
label: "CLI",
detail: "npx shadcn add @nusaiba/*",
icon: SquareTerminalIcon,
},
{
id: "token",
label: "Token",
detail: "Pro registry auth",
icon: KeyRoundIcon,
},
{
id: "preview",
label: "Preview",
detail: "inspect before install",
icon: EyeIcon,
},
{
id: "prompt",
label: "Prompt",
detail: "copy per block page",
icon: ClipboardCopyIcon,
},
];
function PeerChip({
capability,
isActive,
onSelect,
reduceMotion,
}: {
capability: Capability;
isActive: boolean;
onSelect: () => void;
reduceMotion: boolean;
}) {
const Icon = capability.icon;
return (
<button
aria-label={`Show ${capability.label}`}
aria-pressed={isActive}
className={cn(
"relative flex size-10 items-center justify-center rounded-[var(--radius-md)] transition-[background-color,box-shadow,transform] active:scale-[0.96] md:size-11",
"after:absolute after:top-1/2 after:left-1/2 after:size-10 after:-translate-1/2",
isActive
? "bg-muted/40 shadow-[0_0_0_1px_rgba(0,0,0,0.06)] dark:shadow-[0_0_0_1px_rgba(255,255,255,0.08)]"
: "bg-transparent hover:bg-muted/20",
)}
onClick={onSelect}
type="button"
>
<motion.span
animate={
reduceMotion
? undefined
: {
opacity: isActive ? 1 : 0.4,
filter: isActive ? "blur(0px)" : "blur(1px)",
scale: isActive ? 1 : 0.9,
}
}
className="inline-flex text-primary"
transition={{ type: "spring", duration: 0.3, bounce: 0 }}
>
<Icon className="size-4" strokeWidth={2} />
</motion.span>
</button>
);
}
export function FeaturesBlurWordsSection() {
const reduceMotion = useReducedMotion();
const [rootNode, setRootNode] = useState<HTMLElement | null>(null);
const isInView = useInView({ current: rootNode }, { ...motionViewport, amount: 0.35 });
const [active, setActive] = useState(0);
const [cycleActive, setCycleActive] = useState(false);
const activeCapability = capabilities[active]!;
const ActiveIcon = activeCapability.icon;
useEffect(() => {
if (!isInView || reduceMotion) return;
setCycleActive(true);
}, [isInView, reduceMotion]);
useEffect(() => {
if (!cycleActive || reduceMotion) return;
const timer = setInterval(() => {
setActive((current) => (current + 1) % capabilities.length);
}, CYCLE_MS);
return () => clearInterval(timer);
}, [cycleActive, reduceMotion]);
const selectCapability = useCallback((index: number) => {
setActive(index);
setCycleActive(false);
setTimeout(() => setCycleActive(true), CYCLE_MS);
}, []);
return (
<SectionShell spacingMode="section" className="bg-background" ref={setRootNode}>
<ContentRail maxWidth="max-w-5xl" className="grid gap-10 lg:grid-cols-2 lg:items-center lg:gap-14">
<motion.div
className="max-w-md space-y-2"
initial={reduceMotion ? false : { opacity: 0, y: 10, filter: "blur(4px)" }}
transition={defaultSpring}
viewport={motionViewport}
whileInView={reduceMotion ? undefined : { opacity: 1, y: 0, filter: "blur(0px)" }}
>
<p className="font-medium text-primary text-xs uppercase tracking-[0.22em]">
Witness
</p>
<h2 className="text-balance font-medium text-2xl tracking-tight md:text-4xl">
One capability in focus
</h2>
<p className="text-pretty text-muted-foreground text-sm leading-relaxed md:text-base">
Cycle or pick a chip — each block ships with motion docs, CLI paths, and
preview before anything touches your repo.
</p>
</motion.div>
<div className="flex flex-col items-center gap-8 lg:items-end">
<div className="relative flex min-h-[7.5rem] w-full max-w-sm items-center justify-center lg:justify-end">
<AnimatePresence initial={false} mode="wait">
<motion.div
animate={{ opacity: 1, filter: "blur(0px)", y: 0 }}
className="flex w-full flex-col items-center gap-3 text-center lg:items-end lg:text-right"
exit={{
opacity: 0,
filter: "blur(6px)",
y: -8,
transition: { duration: 0.18, ease: "easeIn" },
}}
initial={{ opacity: 0, filter: "blur(8px)", y: 8 }}
key={activeCapability.id}
transition={{ type: "spring", duration: 0.35, bounce: 0 }}
>
<span className="inline-flex size-12 items-center justify-center rounded-[var(--radius-md)] border border-foreground/10 bg-primary/[0.06] text-primary shadow-[0_1px_2px_rgba(0,0,0,0.04)] dark:shadow-[0_1px_2px_rgba(0,0,0,0.2)]">
<ActiveIcon className="size-5" strokeWidth={2} />
</span>
<p className="font-medium text-3xl tracking-tight md:text-4xl">
{activeCapability.label}
</p>
<p className="max-w-xs text-pretty font-mono text-[11px] text-muted-foreground uppercase tracking-[0.14em] md:text-xs">
{activeCapability.detail}
</p>
</motion.div>
</AnimatePresence>
</div>
<ul className="flex flex-wrap items-center justify-center gap-2 md:gap-2.5 lg:justify-end">
{capabilities.map((capability, index) => (
<li key={capability.id}>
<PeerChip
capability={capability}
isActive={index === active}
onSelect={() => selectCapability(index)}
reduceMotion={!!reduceMotion}
/>
</li>
))}
</ul>
</div>
</ContentRail>
</SectionShell>
);
}




























