Skeleton
tetra-ui/skeletonFreeComponent
A component to display placeholder content while in a loading state.
Live preview
live · rendered by the registry
Rendered by tetra-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://tetra-ui.com/r/skeleton.jsonSource
1import { createContext, useContext, useEffect, useMemo } from "react";2import Animated, {3 type SharedValue,4 useAnimatedStyle,5 useSharedValue,6 withRepeat,7 withTiming,8} from "react-native-reanimated";9import { cn } from "@/lib/utils";1011// Constants12const ANIMATION_DURATION = 1000;13const MIN_OPACITY = 0.4;14const MAX_OPACITY = 1;1516// Types17type InternalSkeletonGroupContextType = {18 opacity: SharedValue<number>;19};2021type SkeletonGroupProps = {22 children: React.ReactNode;23};2425type SkeletonProps = React.ComponentProps<typeof Animated.View>;2627// Context28const SkeletonGroupContext =29 createContext<InternalSkeletonGroupContextType | null>(null);3031const useSkeletonGroupContext = () => useContext(SkeletonGroupContext);3233// Components34export const SkeletonGroup = ({ children }: SkeletonGroupProps) => {35 const opacity = useSharedValue(MIN_OPACITY);3637 useEffect(() => {38 opacity.value = withRepeat(39 withTiming(MAX_OPACITY, { duration: ANIMATION_DURATION }),40 -1,41 true42 );43 }, [opacity]);4445 const ctx = useMemo(() => {46 return {47 opacity,48 };49 }, [opacity]);5051 return (52 <SkeletonGroupContext.Provider value={ctx}>53 {children}54 </SkeletonGroupContext.Provider>55 );56};5758export const Skeleton = ({ className, ...props }: SkeletonProps) => {59 const groupContext = useSkeletonGroupContext();60 const localOpacity = useSharedValue(MIN_OPACITY);61 const opacity = groupContext?.opacity ?? localOpacity;6263 useEffect(() => {64 if (groupContext) {65 return;66 }6768 localOpacity.value = withRepeat(69 withTiming(MAX_OPACITY, { duration: ANIMATION_DURATION }),70 -1,71 true72 );73 }, [groupContext, localOpacity]);7475 const animatedStyle = useAnimatedStyle(() => {76 return {77 opacity: opacity.value,78 };79 });8081 return (82 <Animated.View83 className={cn("w-full rounded-md bg-accent", className)}84 data-slot="skeleton"85 style={animatedStyle}86 {...props}87 />88 );89};
What it pulls in
npm packages
Files it writes
More from tetra-ui
All 41 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | tetra-ui | Components | Free | 1 dep | |
| Action Inputaction-input | tetra-ui | Components | Free | no deps | |
| Alertalert | tetra-ui | Components | Free | no deps | |
| Avataravatar | tetra-ui | Components | Free | no deps | |
| Badgebadge | tetra-ui | Components | Free | no deps | |
| Bottom Sheetbottom-sheet | tetra-ui | Components | Free | 4 deps · 7 files | |
| Buttonbutton | tetra-ui | Components | Free | no deps | |
| Cardcard | tetra-ui | Components | Free | no deps |
