@hoddy-ui/skeleton
v1.0.0
Published
Skeleton placeholder components for Expo and React Native
Maintainers
Readme
@hoddy-ui/skeleton
Skeleton placeholder components for Expo and React Native. Use them to show loading states with an animated shimmer that follows the shape of your placeholder blocks.
Expo SDK 54
This package is built for Expo SDK 54. It has been tested with:
| Dependency | Version | |------------|--------| | expo | ~54.0.0 | | react-native | 0.81.x | | react-native-reanimated | ~4.1.x | | expo-linear-gradient | ~15.0.x | | @react-native-masked-view/masked-view | 0.3.x |
Installation
yarn add @hoddy-ui/skeletonOr with npm:
npm install @hoddy-ui/skeletonPeer dependencies are required. If you are using Expo SDK 54, you typically already have react, react-native, react-native-reanimated, expo-linear-gradient, and @react-native-masked-view/masked-view installed. If not, install them according to your Expo version.
Peer dependencies
react(>=18.2.0)react-native(>=0.81.0)react-native-reanimated(~4.1.x)expo-linear-gradient(~15.0.x)@react-native-masked-view/masked-view(0.3.x)expo(~54.0.0) — for Expo projects
Usage
Wrap one or more SkeletonBlock components inside SkeletonView. The blocks define the shape of the shimmer; the shimmer animation is visible only where the blocks are.
import { SkeletonView, SkeletonBlock } from "@hoddy-ui/skeleton";
function LoadingCard() {
return (
<SkeletonView>
<SkeletonBlock height={20} style={{ marginBottom: 8 }} />
<SkeletonBlock width="80%" height={16} />
<SkeletonBlock width="60%" height={16} style={{ marginTop: 8 }} />
</SkeletonView>
);
}API reference
SkeletonView
Container that renders an animated shimmer masked by its children. Children should be opaque shapes (e.g. SkeletonBlock) so the shimmer is visible only in those areas.
| Prop | Type | Description |
|------|------|-------------|
| children | React.ReactNode | Required. Typically one or more SkeletonBlock components. |
| style | ViewStyle | Optional. Applied to the container and mask layout. |
| shimmerBaseColor | string | Optional. Base (background) color of the shimmer. Overrides the built-in default. |
| shimmerHighlightColor | string | Optional. Highlight (moving band) color of the shimmer. Overrides the built-in default. |
| theme | "light" \| "dark" | Optional. Theme used for built-in default colors when shimmerBaseColor / shimmerHighlightColor are not set. Defaults to "light". |
SkeletonBlock
A single rectangular placeholder. Use only inside SkeletonView as a mask child. Rendered as opaque black so the parent shimmer shows through the mask in this shape.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| width | DimensionValue | "100%" | Block width (e.g. "80%", 100, ms(80) if you use react-native-size-matters). |
| height | DimensionValue | 16 | Block height. |
| borderRadius | number | 6 | Corner radius. |
| style | ViewStyle | — | Optional extra styles (e.g. margin, marginBottom). |
SkeletonShimmer
Internal component that renders the animated gradient. You usually do not use it directly. It is exported for advanced cases where you want to use it inside your own MaskedView (e.g. custom layout). In that case wrap your tree in SkeletonProvider and provide value with optional baseColor, highlightColor, and theme.
SkeletonProvider
Context provider for shimmer colors and theme. SkeletonView uses it internally. Use it yourself only if you build a custom skeleton layout and need to pass colors/theme to SkeletonShimmer.
useSkeletonColors
Hook that returns the current skeleton context value: { baseColor?, highlightColor?, theme? }. Use when implementing custom components that need to read or depend on the active skeleton theme/colors.
Types
- SkeletonShimmerColors —
{ baseColor?: string; highlightColor?: string } - SkeletonTheme —
"light" | "dark" - SkeletonContextValue — Extends
SkeletonShimmerColorswiththeme?: SkeletonTheme
Customizing colors
All default colors are defined inside this package. There is no dependency on hoddy-ui theme or any external design system.
- Use built-in theme: set
theme="light"ortheme="dark"onSkeletonView. Light uses#E4E7EC(base) and#F7F9FC(highlight); dark uses#161616and#333. - Override with custom colors: pass
shimmerBaseColorand/orshimmerHighlightColoronSkeletonView. These take precedence over theme defaults.
<SkeletonView theme="dark">
<SkeletonBlock height={24} />
</SkeletonView>
<SkeletonView
shimmerBaseColor="#e0e0e0"
shimmerHighlightColor="#f5f5f5"
>
<SkeletonBlock height={24} />
</SkeletonView>More examples
Card-style skeleton (avatar + lines)
<SkeletonView style={{ padding: 16 }}>
<View style={{ flexDirection: "row", marginBottom: 12 }}>
<SkeletonBlock width={48} height={48} borderRadius={24} />
<View style={{ marginLeft: 12, flex: 1 }}>
<SkeletonBlock height={16} style={{ marginBottom: 6 }} />
<SkeletonBlock width="70%" height={14} />
</View>
</View>
<SkeletonBlock height={14} style={{ marginBottom: 6 }} />
<SkeletonBlock width="90%" height={14} />
</SkeletonView>List row skeleton
<SkeletonView style={{ flexDirection: "row", alignItems: "center", paddingVertical: 12 }}>
<SkeletonBlock width={40} height={40} borderRadius={8} />
<View style={{ marginLeft: 12, flex: 1 }}>
<SkeletonBlock height={16} width="60%" style={{ marginBottom: 6 }} />
<SkeletonBlock height={12} width="40%" />
</View>
</SkeletonView>Full-screen placeholder
<SkeletonView style={{ flex: 1, padding: 24 }}>
<SkeletonBlock height={200} style={{ marginBottom: 24, borderRadius: 12 }} />
<SkeletonBlock height={20} style={{ marginBottom: 8 }} />
<SkeletonBlock height={16} style={{ marginBottom: 8 }} />
<SkeletonBlock height={16} width="80%" />
</SkeletonView>License
MIT
