Logo Loom
loomui/logo-loomFreeComponent
A logo row woven into place, every other mark arriving from the other side of the thread.
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/logo-loom.jsonSource
1"use client"23import * as React from "react"45import { cn } from "@/lib/utils"67export interface LogoLoomProps extends React.ComponentProps<"div"> {8 /** Milliseconds between one logo arriving and the next. */9 stagger?: number10 /** Length of a single logo's arrival, in milliseconds. */11 duration?: number12 /** How far a logo travels in, as a CSS length. */13 distance?: string14 /** Draw the thread the logos are woven onto. */15 thread?: boolean16 /** Weave again every time the row comes back into view. */17 repeat?: boolean18}1920export function LogoLoom({21 children,22 className,23 stagger = 90,24 duration = 700,25 distance = "1.6rem",26 thread = true,27 repeat = false,28 ...props29}: LogoLoomProps) {30 const ref = React.useRef<HTMLDivElement>(null)31 const [woven, setWoven] = React.useState(false)3233 React.useEffect(() => {34 const node = ref.current35 if (!node) {36 return37 }3839 const observer = new IntersectionObserver(40 ([entry]) => {41 if (entry.isIntersecting) {42 setWoven(true)43 } else if (repeat) {44 setWoven(false)45 }46 },47 { threshold: 0.35 }48 )4950 observer.observe(node)51 return () => observer.disconnect()52 }, [repeat])5354 const logos = React.Children.toArray(children)5556 return (57 <div58 ref={ref}59 data-slot="logo-loom"60 data-woven={woven ? "" : undefined}61 className={cn(62 "relative flex flex-wrap items-center justify-center gap-x-10 gap-y-6",63 className64 )}65 {...props}66 >67 {/* The warp. It runs behind every logo, and only the logos that carry a68 background hide it, which is what makes the row read as woven rather69 than as a row of logos on a line. */}70 {thread ? (71 <span72 aria-hidden="true"73 className="border-muted-foreground/25 absolute inset-x-0 top-1/2 -z-10 border-t border-dashed"74 />75 ) : null}7677 {logos.map((logo, index) => (78 <span79 key={index}80 data-slot="logo-loom-item"81 className={cn(82 "relative px-3 opacity-0",83 // Every other logo sits over the thread and the rest sit under it.84 // The pass a logo takes is also the direction it arrives from, so85 // the row interlaces as it lands.86 index % 2 === 0 ? "bg-background" : "bg-transparent",87 woven &&88 "animate-loom-weave motion-reduce:animate-none motion-reduce:opacity-100"89 )}90// … 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 |
