Meteors

Pluie de meteores decorative avec des trainees qui tombent en arriere-plan. Installez Meteors depuis le registre VLLNT UI avec la CLI shadcn.

Signaler un bug

Pluie de meteores decorative avec des trainees qui tombent en arriere-plan. Fait partie de la famille utility 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 Meteors 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/meteors.json

Source

"use client"; import * as React from "react"; import { cn } from "../../lib/utils"; /** Props for {@link Meteors}. */ export type MeteorsProps = React.ComponentPropsWithoutRef<"div"> & { /** Count of meteors streaking across the field. Defaults to `12`. */ count?: number; }; type Meteor = { delay: number; duration: number; left: number; top: number; }; function createMeteors(count: number): Meteor[] { return Array.from({ length: count }, () => ({ delay: Math.random(), duration: 2 + Math.random() * 4, left: Math.random() * 100, top: -(Math.random() * 10), })); } type MeteorStyle = React.CSSProperties & { "--vllnt-meteor-angle"?: string; }; function meteorStyle(meteor: Meteor): MeteorStyle { return { "--vllnt-meteor-angle": "215deg", animation: `vllnt-meteor ${meteor.duration}s linear infinite`, animationDelay: `${meteor.delay}s`, left: `${meteor.left}%`, top: `${meteor.top}%`, }; } /** * Decorative shower of meteors falling diagonally across the field. * * Respects `prefers-reduced-motion`: the meteors stay parked. * * @example * ```tsx * <Meteors count={20} /> * ``` */ export const Meteors = ({ className, count = 12, ref, ...props }: MeteorsProps & { ref?: React.Ref<HTMLDivElement> }) => { const [meteors] = React.useState(() => createMeteors(count)); return ( <div aria-hidden="true" className={cn( "pointer-events-none absolute inset-0 overflow-hidden", className, )} ref={ref} {...props} > {meteors.map((meteor, index) => ( <span className="absolute h-0.5 w-0.5 rounded-full bg-muted-foreground motion-reduce:animate-none" key={index} style={meteorStyle(meteor)} > <span className="absolute right-0 top-1/2 h-px w-12 -translate-y-1/2" style={{ background: "linear-gradient(90deg, oklch(var(--muted-foreground)), transparent)", }} /> </span> ))} </div> ); }; Meteors.displayName = "Meteors";

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