Loom Loader
loomui/loom-loaderFreeComponent
Threads drawn through a frame and pulled off the far side, with a shuttle crossing them.
Live preview
live · rendered by the registry
Rendered by loomui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://loomui.design/r/loom-loader.jsonSource
1"use client"23import * as React from "react"45import { cn } from "@/lib/utils"67export interface LoomLoaderProps extends React.ComponentProps<"div"> {8 /** How many warp threads are on the frame. Three to seven reads best. */9 strands?: number10 /** Milliseconds for one thread to be drawn through and pulled off. */11 duration?: number12 /** Announced to screen readers while the loader is on screen. */13 label?: string14}1516/** The frame the threads are strung across, in user units. */17const BOX = 4018const INSET = 51920/**21 * Warp threads are drawn with `pathLength="1"`, so the dash animation is22 * written in fractions of a line rather than in pixels and the same keyframes23 * hold at any size.24 */25export function LoomLoader({26 strands = 5,27 duration = 1400,28 label = "Loading",29 className,30 style,31 ...props32}: LoomLoaderProps) {33 const positions = React.useMemo(() => {34 const span = BOX - INSET * 235 const gap = strands > 1 ? span / (strands - 1) : 036 return Array.from({ length: strands }, (_, index) => INSET + index * gap)37 }, [strands])3839 return (40 <div41 data-slot="loom-loader"42 role="status"43 aria-label={label}44 className={cn("text-primary inline-block size-10", className)}45 style={46 { "--loom-duration": `${duration}ms`, ...style } as React.CSSProperties47 }48 {...props}49 >50 <svg51 viewBox={`0 0 ${BOX} ${BOX}`}52 fill="none"53 aria-hidden="true"54 className="size-full overflow-visible"55 >56 {positions.map((x, index) => (57 <line58 key={x}59 x1={x}60 y1={INSET}61 x2={x}62 y2={BOX - INSET}63 pathLength={1}64 stroke="currentColor"65 strokeWidth={2}66 strokeLinecap="round"67 strokeOpacity={0.3}68 // Drawn whole at rest, so a reduced-motion frame is a woven glyph69 // rather than an empty box.70 strokeDasharray={1}71 className="animate-loom-thread motion-reduce:animate-none"72 style={{73 // Threads start one after another, which is what turns five74 // lines into a weave instead of five lines blinking together.75 animationDelay: `${(index / strands) * duration * 0.6}ms`,76 }}77 />78 ))}7980 {/* The shuttle. It carries the weft across the warp and back. */}81 <line82 x1={INSET}83 y1={INSET - 1}84 x2={INSET}85// … truncated
What it pulls in
Other registry items
Files it writes
More from loomui
All 91 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Aurora Backdropaurora-backdrop | loomui | Components | Free | no deps | |
| Bento Gridbento-grid | loomui | Components | Free | no deps | |
| Card Stackcard-stack | loomui | Components | Free | no deps | |
| Compare Slidercompare-slider | loomui | Components | Free | no deps | |
| Confetti Buttonconfetti-button | loomui | Components | Free | no deps | |
| Count Upcount-up | loomui | Components | Free | no deps | |
| Credit Cardcredit-card | loomui | Components | Free | no deps | |
| Drawerdrawer | loomui | Components | Free | 1 dep |
