import { Text, View } from "react-native";
import { Button } from "@/component-lib/button";
import { useKitTheme } from "@/component-lib/shared/native";
import { Empty, Skeleton } from "@/component-lib/skeleton";
import { Section } from "./layout"; // Section and Row: page layout for the demo
export function SkeletonDemo() {
const { tokens } = useKitTheme();
return (
<>
<Section title="Skeleton · pulse">
<View style={{ flexDirection: "row", gap: 12, alignItems: "center" }}>
<Skeleton variant="circle" width={48} />
<View style={{ flex: 1 }}>
<Skeleton lines={2} lastLineWidth={45} />
</View>
</View>
<Skeleton variant="rect" height={120} label="Loading the chart" />
</Section>
<Section title="Skeleton · wave">
<Skeleton lines={4} animation="wave" />
<View style={{ flexDirection: "row", gap: 12 }}>
<Skeleton variant="rect" width="48%" height={90} radius={16} animation="wave" />
<Skeleton variant="rect" width="48%" height={90} radius={16} animation="wave" />
</View>
</Section>
<Section title="Skeleton · none">
<Skeleton lines={3} animation="none" />
</Section>
<Section title="Empty">
<View style={{ borderWidth: 1, borderColor: tokens.border, borderRadius: tokens.radius }}>
<Empty
icon={<Text style={{ fontSize: 36 }}>🗂️</Text>}
title="No invoices yet"
description="Invoices you create or import show up here. Start with one, or import last year's from a spreadsheet."
actions={
<>
<Button>New invoice</Button>
<Button variant="outline">Import</Button>
</>
}
/>
</View>
<View style={{ borderWidth: 1, borderColor: tokens.border, borderRadius: tokens.radius }}>
<Empty size="sm" title="No results" description="Try a shorter search." />
</View>
</Section>
</>
);
}Install
npx @grampro/kit@native add SkeletonUsage
import { Skeleton, Empty } from "@/component-lib/skeleton";
<Skeleton variant="text" lines={3} />
<Empty title="No invoices yet" description="Create one to get paid." />Props
SkeletonProps
| Prop | Type | Description |
|---|---|---|
variant | SkeletonVariant | Default text. |
lines | number | Number of bars, for text. Default 1. |
lastLineWidth | number | Width of the last line as a percentage, for text. Default 60. |
width | DimensionValue | A number is dp; a string is a percentage such as "50%". |
height | DimensionValue | A number is dp. Left out, each variant uses its own height, which is what keeps a skeleton the size of the thing it stands in for. |
radius | number | Corner radius for rect, in dp. |
animation | SkeletonAnimation | Default pulse. The device's reduce-motion setting turns any of them off. |
label | string | Announced while the placeholder is up. Leave it out inside a region that already says it is busy: two announcements are worse than one. |
style | StyleProp<ViewStyle> | |
styles | Partial<{ root: StyleProp<ViewStyle>; line: StyleProp<ViewStyle> }> |
EmptyProps
| Prop | Type | Description |
|---|---|---|
title (required) | ReactNode | What is missing, in a few words. |
description | ReactNode | Why it is empty, and what to do about it. |
icon | ReactNode | Decorative: an illustration or icon above the title. |
actions | ReactNode | The way out: usually one button, occasionally two. |
size | "sm" | "md" | "lg" | Default md. sm suits an empty panel inside a screen. |
style | StyleProp<ViewStyle> | |
styles | Partial<{ root: StyleProp<ViewStyle>; icon: StyleProp<ViewStyle>; title: StyleProp<Text… |
Native and web
- Respects the device's Reduce Motion setting.
- Web version: Skeleton & Empty on the web.