reel
kibo-ui-registry/reelFreeComponent
A composable Reel component that looks like Instagram Stories - a full-height, 9:16 aspect ratio container with video playback and progress indicators.
Live preview
live · rendered by the registry
Rendered by Kibo UI Registry on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://www.kibo-ui.com/r/reel.jsonSource
1"use client";23import { useControllableState } from "@radix-ui/react-use-controllable-state";4import {5 ChevronLeft,6 ChevronRight,7 Pause,8 Play,9 Volume2,10 VolumeX,11} from "lucide-react";12import { AnimatePresence, motion } from "motion/react";13import type {14 ComponentProps,15 HTMLAttributes,16 MouseEventHandler,17 ReactNode,18 VideoHTMLAttributes,19} from "react";20import {21 createContext,22 useCallback,23 useContext,24 useEffect,25 useRef,26 useState,27} from "react";28import { Button } from "@/components/ui/button";29import { Progress } from "@/components/ui/progress";30import { cn } from "@/lib/utils";3132// Explicit type for reel items33export type ReelItem = {34 id: string | number;35 type: "video" | "image";36 src: string;37 duration: number; // Duration in seconds for both video and image38 alt?: string;39 title?: string;40 description?: string;41};4243type ReelContextType = {44 currentIndex: number;45 setCurrentIndex: (index: number) => void;46 isPlaying: boolean;47 setIsPlaying: (playing: boolean) => void;48 isMuted: boolean;49 setIsMuted: (muted: boolean) => void;50 progress: number;51 setProgress: (progress: number) => void;52 duration: number;53 setDuration: (duration: number) => void;54 data: ReelItem[];55 currentItem: ReelItem;56 isNavigating: boolean;57 setIsNavigating: (navigating: boolean) => void;58 isTransitioning: boolean;59 setIsTransitioning: (transitioning: boolean) => void;60};6162const ReelContext = createContext<ReelContextType | undefined>(undefined);6364const useReelContext = () => {65 const context = useContext(ReelContext);66 if (!context) {67 throw new Error("useReelContext must be used within a Reel");68 }69 return context;70};7172export type ReelProps = HTMLAttributes<HTMLDivElement> & {73 data: ReelItem[];74 defaultIndex?: number;75 index?: number;76 onIndexChange?: (index: number) => void;77 defaultPlaying?: boolean;78 playing?: boolean;79 onPlayingChange?: (playing: boolean) => void;80 defaultMuted?: boolean;81 muted?: boolean;82 onMutedChange?: (muted: boolean) => void;83 autoPlay?: boolean;84};8586export const Reel = ({87 className,88 data,89 defaultIndex = 0,90 index: controlledIndex,91 onIndexChange: controlledOnIndexChange,92 defaultPlaying,93 playing: controlledPlaying,94 onPlayingChange: controlledOnPlayingChange,95 defaultMuted = true,96 muted: controlledMuted,97 onMutedChange: controlledOnMutedChange,98 autoPlay = true,99 ...props100}: ReelProps) => {101 const [currentIndex, setCurrentIndexState] = useControllableState({102// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from Kibo UI Registry
All 41 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| announcementannouncement | Kibo UI Registry | Components | Free | no deps | |
| avatar-stackavatar-stack | Kibo UI Registry | Components | Free | no deps | |
| bannerbanner | Kibo UI Registry | Components | Free | 2 deps | |
| calendarcalendar | Kibo UI Registry | Components | Free | 3 deps | |
| choiceboxchoicebox | Kibo UI Registry | Components | Free | 2 deps | |
| code-blockcode-block | Kibo UI Registry | Components | Free | 5 deps · 2 files | |
| color-pickercolor-picker | Kibo UI Registry | Components | Free | 3 deps | |
| comboboxcombobox | Kibo UI Registry | Components | Free | 2 deps |
