Skip to content

Commit 2d040bc

Browse files
author
omar-bear
committed
feat: add Skeleton component with documentation and examples
1 parent f4ca4ed commit 2d040bc

File tree

12 files changed

+961
-1
lines changed

12 files changed

+961
-1
lines changed

apps/docs/pages/docs/Components/_meta.en-US.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"image": "Image",
66
"divider": "Divider",
77
"icon": "Icon",
8+
"skeleton": "Skeleton",
89
"spinner": "Spinner",
910
"modal": "Modal",
1011
"draggable-modal": "DraggableModal"
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
---
2+
searchable: true
3+
---
4+
5+
import { CodeEditor } from '@components/code-editor';
6+
import PropsTable from "@components/docs/props-table";
7+
8+
# Skeleton
9+
10+
The Skeleton component provides animated placeholders while content is loading. It supports different shapes and automatically adapts to dark mode.
11+
12+
## Import
13+
14+
```js
15+
import { Skeleton, SkeletonProvider } from "react-native-ficus-ui";
16+
```
17+
18+
## Usage
19+
20+
### Basic skeleton
21+
22+
<CodeEditor code={`<VStack spacing="md">
23+
<Skeleton w="200" h="20" />
24+
<Skeleton w="150" h="15" />
25+
<Skeleton w="300" h="12" />
26+
</VStack>`} />
27+
28+
### Skeleton Box
29+
30+
<CodeEditor code={`<VStack spacing="md">
31+
<Skeleton.Box w="100%" h="100" />
32+
<Skeleton.Box w="200" h="50" borderRadius="lg" />
33+
<Skeleton.Box w="150" h="30" borderRadius="full" />
34+
</VStack>`} />
35+
36+
### Skeleton Text
37+
38+
<CodeEditor code={`<VStack spacing="md">
39+
<Skeleton.Text fontSize="sm" />
40+
<Skeleton.Text fontSize="md" />
41+
<Skeleton.Text fontSize="lg" />
42+
<Skeleton.Text fontSize="xl" />
43+
<Skeleton.Text fontSize="2xl" />
44+
</VStack>`} />
45+
46+
### Multi-line text skeleton
47+
48+
<CodeEditor code={`<VStack spacing="lg">
49+
<Skeleton.Text noOfLines={2} />
50+
<Skeleton.Text noOfLines={3} lineSpacing="md" />
51+
<Skeleton.Text noOfLines={4} lineSpacing="lg" />
52+
</VStack>`} />
53+
54+
### Skeleton Circle
55+
56+
<CodeEditor code={`<HStack spacing="md">
57+
<Skeleton.Circle boxSize="30" />
58+
<Skeleton.Circle boxSize="50" />
59+
<Skeleton.Circle boxSize="70" />
60+
<Skeleton.Circle boxSize="100" />
61+
</HStack>`} />
62+
63+
### Loading state with content
64+
65+
<CodeEditor code={`function LoadingExample() {
66+
const [isLoaded, setIsLoaded] = React.useState(false);
67+
68+
React.useEffect(() => {
69+
const timer = setTimeout(() => setIsLoaded(true), 3000);
70+
return () => clearTimeout(timer);
71+
}, []);
72+
73+
return (
74+
<VStack spacing="md">
75+
<Button onPress={() => setIsLoaded(!isLoaded)}>
76+
{isLoaded ? 'Show Skeleton' : 'Show Content'}
77+
</Button>
78+
79+
<Skeleton isLoaded={isLoaded}>
80+
<Text>This content appears when loaded!</Text>
81+
</Skeleton>
82+
83+
<Skeleton.Text fontSize="lg" isLoaded={isLoaded}>
84+
<Text fontSize="lg" fontWeight="bold">
85+
This is a loaded text with large font size
86+
</Text>
87+
</Skeleton.Text>
88+
</VStack>
89+
);
90+
}`} />
91+
92+
### Synchronized animation with SkeletonProvider
93+
94+
<CodeEditor code={`<SkeletonProvider>
95+
<VStack spacing="md">
96+
<HStack spacing="md" alignItems="center">
97+
<Skeleton.Circle boxSize="50" />
98+
<VStack flex={1} spacing="xs">
99+
<Skeleton.Text fontSize="lg" w="70%" />
100+
<Skeleton.Text fontSize="sm" w="50%" />
101+
</VStack>
102+
</HStack>
103+
104+
<Skeleton.Box w="100%" h="100" borderRadius="md" />
105+
106+
<Skeleton.Text noOfLines={3} />
107+
</VStack>
108+
</SkeletonProvider>`} />
109+
110+
### Card layout example
111+
112+
<CodeEditor code={`<Box bg="white" p="lg" borderRadius="lg" shadow="sm">
113+
<SkeletonProvider>
114+
<VStack spacing="md">
115+
<HStack spacing="md" alignItems="center">
116+
<Skeleton.Circle boxSize="40" />
117+
<VStack flex={1} spacing="xs">
118+
<Skeleton.Text w="60%" />
119+
<Skeleton.Text w="40%" fontSize="sm" />
120+
</VStack>
121+
</HStack>
122+
123+
<Skeleton.Box h="120" borderRadius="md" />
124+
125+
<VStack spacing="xs">
126+
<Skeleton.Text />
127+
<Skeleton.Text />
128+
<Skeleton.Text w="80%" />
129+
</VStack>
130+
</VStack>
131+
</SkeletonProvider>
132+
</Box>`} />
133+
134+
### Custom shimmer settings
135+
136+
<CodeEditor code={`<VStack spacing="lg">
137+
<Text fontSize="md" fontWeight="bold">Default shimmer (enabled)</Text>
138+
<Skeleton.Box w="200" h="30" />
139+
140+
<Text fontSize="md" fontWeight="bold">No shimmer animation</Text>
141+
<Skeleton.Box w="200" h="30" shimmer={false} />
142+
143+
<Text fontSize="md" fontWeight="bold">Custom animation duration</Text>
144+
<SkeletonProvider duration={800}>
145+
<Skeleton.Box w="200" h="30" />
146+
</SkeletonProvider>
147+
</VStack>`} />
148+
149+
## Props
150+
151+
### Skeleton
152+
153+
Extends every `Box` props.
154+
155+
#### `isLoaded`
156+
<PropsTable
157+
description="If true, the skeleton will be replaced by the children."
158+
prop={{ type: "boolean", required: false, defaultValue: "false" }}
159+
/>
160+
161+
#### `shimmer`
162+
<PropsTable
163+
description="If true, the skeleton will show a shimmer animation."
164+
prop={{ type: "boolean", required: false, defaultValue: "true" }}
165+
/>
166+
167+
#### `duration`
168+
<PropsTable
169+
description="The duration of the shimmer animation in milliseconds. Overrides provider duration."
170+
prop={{ type: "number", required: false, defaultValue: "1200" }}
171+
/>
172+
173+
### Skeleton.Text
174+
175+
Extends every `Skeleton` props.
176+
177+
#### `fontSize`
178+
<PropsTable
179+
description="The font size to calculate the skeleton height automatically."
180+
prop={{ type: "ResponsiveValue<string | number>", required: false, defaultValue: "'md'" }}
181+
/>
182+
183+
#### `noOfLines`
184+
<PropsTable
185+
description="The number of lines to render for multi-line text skeleton."
186+
prop={{ type: "number", required: false, defaultValue: "1" }}
187+
/>
188+
189+
#### `lineSpacing`
190+
<PropsTable
191+
description="The spacing between lines when noOfLines > 1."
192+
prop={{ type: "ResponsiveValue<string | number>", required: false, defaultValue: "'xs'" }}
193+
/>
194+
195+
### Skeleton.Circle
196+
197+
Extends every `Skeleton` props.
198+
199+
#### `boxSize`
200+
<PropsTable
201+
description="The size of the circle (both width and height)."
202+
prop={{ type: "ResponsiveValue<number | string>", required: false, defaultValue: "40" }}
203+
/>
204+
205+
### SkeletonProvider
206+
207+
#### `duration`
208+
<PropsTable
209+
description="The duration of the shimmer animation in milliseconds for all child skeleton components."
210+
prop={{ type: "number", required: false, defaultValue: "1200" }}
211+
/>
212+
213+
#### `paused`
214+
<PropsTable
215+
description="If true, the shimmer animation will be paused."
216+
prop={{ type: "boolean", required: false, defaultValue: "false" }}
217+
/>
218+
219+
## Accessibility
220+
221+
The Skeleton component includes proper accessibility features:
222+
223+
- Automatically sets appropriate `accessibilityLabel` when content is loading
224+
- Maintains proper screen reader support
225+
- Respects user's reduced motion preferences
226+
227+
## Styling
228+
229+
Skeleton components can be styled using all standard Ficus UI style props:
230+
231+
<CodeEditor code={`<VStack spacing="md">
232+
<Skeleton.Box
233+
w="200"
234+
h="30"
235+
bg="blue.100"
236+
borderRadius="full"
237+
borderWidth={2}
238+
borderColor="blue.300"
239+
/>
240+
241+
<Skeleton.Text
242+
fontSize="lg"
243+
bg="red.100"
244+
borderRadius="md"
245+
p="sm"
246+
/>
247+
248+
<Skeleton.Circle
249+
boxSize="60"
250+
bg="green.200"
251+
borderWidth={3}
252+
borderColor="green.400"
253+
/>
254+
</VStack>`} />
255+
256+
## Performance
257+
258+
The Skeleton component is optimized for performance:
259+
260+
- Uses `react-native-reanimated` for 60fps animations
261+
- Pure React Native implementation - no external native dependencies
262+
- Lightweight shimmer effect with minimal CPU usage
263+
- Works perfectly in Expo Go and all React Native environments

0 commit comments

Comments
 (0)