404 / Not Found Glitch
beui/not-found-glitchFreeBlock
Digits scramble through random glyphs before resolving, with a chromatic split on hover.
Install it
npx shadcn@latest add https://beui.dev/r/not-found-glitch.jsonSource
1"use client";2// beui.dev/components/blocks/not-found34import { useEffect, useState } from "react";5import { useReducedMotion } from "motion/react";6import {7 NOT_FOUND_DEFAULTS,8 NotFoundActions,9 NotFoundStage,10 type NotFoundProps,11} from "./shared";1213const GLYPHS = "ABCDEFGHJKLMNPQRSTUVWXYZ0123456789#%&@$?/\\";14const SCRAMBLE_MS = 700;15const TICK_MS = 45;1617/**18 * Renders the code, scrambling each character on mount before it settles.19 * SSR and the first paint show the real code, so the scramble is a pure20 * client-side enhancement and reduced-motion users see the code immediately.21 */22function Scramble({ text }: { text: string }) {23 const reduce = useReducedMotion();24 const [display, setDisplay] = useState(text);2526 useEffect(() => {27 if (reduce) {28 setDisplay(text);29 return;30 }31 const chars = text.split("");32 const start = performance.now();33 let raf = 0;34 let last = 0;3536 const loop = (now: number) => {37 if (now - last >= TICK_MS) {38 last = now;39 const progress = Math.min((now - start) / SCRAMBLE_MS, 1);40 const settled = Math.floor(progress * chars.length);41 setDisplay(42 chars43 .map((ch, i) =>44 i < settled || ch === " "45 ? ch46 : GLYPHS[Math.floor(Math.random() * GLYPHS.length)],47 )48 .join(""),49 );50 }51 if (now - start < SCRAMBLE_MS) {52 raf = requestAnimationFrame(loop);53 } else {54 setDisplay(text);55 }56 };57 raf = requestAnimationFrame(loop);58 return () => cancelAnimationFrame(raf);59 }, [text, reduce]);6061 return <span className="tabular-nums">{display}</span>;62}6364export function NotFoundGlitch({65 className,66 code = NOT_FOUND_DEFAULTS.code,67 title = NOT_FOUND_DEFAULTS.title,68 description = NOT_FOUND_DEFAULTS.description,69 homeHref,70 homeLabel,71 browseHref,72 browseLabel,73}: NotFoundProps) {74 return (75 <NotFoundStage className={className}>76 <div className="group relative select-none font-mono font-bold leading-none tracking-tighter text-foreground [font-size:clamp(5rem,18vw,11rem)]">77 {/* Chromatic ghost layers, nudged apart on hover. */}78 <span79 aria-hidden80 className="pointer-events-none absolute inset-0 text-[#ff0040] opacity-0 mix-blend-screen transition-[transform,opacity] duration-150 ease-out group-hover:translate-x-[3px] group-hover:opacity-70 motion-reduce:hidden"81 >82// … truncated
What it pulls in
npm packages
Files it writes
More from beui
All 104 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| File Upload Attachment Uploadattachment-upload | beui | Blocks | Free | 4 deps · 5 files | |
| Availability Scheduleravailability-scheduler | beui | Blocks | Free | 4 deps · 15 files | |
| Bloom Menubloom-menu | beui | Blocks | Free | 4 deps · 3 files | |
| Command Palettecommand-palette | beui | Blocks | Free | 4 deps · 3 files | |
| Dynamic Islanddynamic-island | beui | Blocks | Free | 3 deps · 3 files | |
| Expandable Action Barexpandable-action-bar | beui | Blocks | Free | 3 deps · 2 files | |
| Expandable Tabsexpandable-tabs | beui | Blocks | Free | 3 deps · 3 files | |
| Feedback Widgetfeedback-widget | beui | Blocks | Free | 4 deps · 9 files |
