Scramble Text

Brouille les caracteres puis les resout en texte final. Installez Scramble Text depuis le registre VLLNT UI avec la CLI shadcn.

Signaler un bug

Brouille les caracteres puis les resout en texte final. Fait partie de la famille content dans VLLNT UI, il est publie comme entree de registre lisible par machine — copiez la source directement dans votre application avec la CLI shadcn et possedez-la, sans dependance d'execution a une bibliotheque de composants.

Apercu

Basculez entre clair et sombre pour inspecter l'apercu Storybook integre.

Installation

Ajoutez Scramble Text a votre projet avec la CLI shadcn. La source arrive dans votre code, prete a etre adaptee :

pnpm dlx shadcn@latest add https://ui.vllnt.ai/r/scramble-text.json

Source

"use client"; import * as React from "react"; import { cn } from "../../lib/utils"; /** Props for {@link ScrambleText}. */ export type ScrambleTextProps = React.ComponentPropsWithoutRef<"span"> & { /** Milliseconds for the full resolve. Defaults to `1200`. */ duration?: number; /** Pool of glyphs used while scrambling. */ scrambleCharacters?: string; /** Final resolved text. */ text: string; }; function usePrefersReducedMotion(): boolean { const [reduced, setReduced] = React.useState(false); React.useEffect(() => { if ( typeof window === "undefined" || typeof window.matchMedia !== "function" ) { return; } const query = window.matchMedia("(prefers-reduced-motion: reduce)"); const onChange = (): void => { setReduced(query.matches); }; onChange(); query.addEventListener("change", onChange); return () => { query.removeEventListener("change", onChange); }; }, []); return reduced; } function scramble(text: string, revealed: number, pool: string): string { const characters = text.match(/[\s\S]/gu) ?? []; return characters .map((character, index) => { if (index < revealed || character === " ") { return character; } return pool.charAt(Math.floor(Math.random() * pool.length)); }) .join(""); } const defaultPool = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; /** * Resolves text left-to-right out of randomized glyphs on mount. * * Respects `prefers-reduced-motion`: the final text shows at once. * * @example * ```tsx * <ScrambleText text="DECRYPTED" /> * ``` */ export const ScrambleText = ({ className, duration = 1200, ref, scrambleCharacters = defaultPool, text, ...props }: ScrambleTextProps & { ref?: React.Ref<HTMLSpanElement> }) => { const reduced = usePrefersReducedMotion(); const [display, setDisplay] = React.useState(text); React.useEffect(() => { if (reduced) { setDisplay(text); return; } const steps = Math.max(text.length, 1); const tick = duration / steps; let revealed = 0; const timer = setInterval(() => { revealed += 1; setDisplay(scramble(text, revealed, scrambleCharacters)); if (revealed >= text.length) { clearInterval(timer); } }, tick); return () => { clearInterval(timer); }; }, [duration, reduced, scrambleCharacters, text]); return ( <span aria-label={text} className={cn("font-mono", className)} ref={ref} {...props} > <span aria-hidden="true">{display}</span> </span> ); }; ScrambleText.displayName = "ScrambleText";

Stories

Explorez chaque variante et etat dans le Storybook interactif :

Apercu

Basculez entre clair et sombre pour inspecter l'apercu Storybook integre.

Dependances

  • @vllnt/ui@^0.3.0