Primitives
Skeleton
A placeholder block that takes the place of content while the content loads.
Primitives
A placeholder block that takes the place of content while the content loads.
import { Skeleton } from 'ferry-ui'
export default function SkeletonHero() {
return (
<div aria-busy="true" className="flex w-full max-w-xs items-center gap-3 rounded-lg border bg-surface-100 p-4">
<Skeleton className="size-10 rounded-full" />
<div className="flex flex-1 flex-col gap-2">
<Skeleton className="h-4 w-32" />
<Skeleton className="h-3.5 w-44" />
</div>
</div>
)
}loading prop. Table States and Resource Card have their own skeleton components.loading prop of Button.Import the component. A skeleton has one part.
import { Skeleton } from 'ferry-ui'
<Skeleton className="h-4 w-32" />Set the size and the radius with className. This demo shows an avatar, a square picture, a badge, a field and a line of text.
import { Skeleton } from 'ferry-ui'
export default function SkeletonShapes() {
return (
<>
{/* An avatar */}
<Skeleton className="size-8 rounded-full" />
{/* A square picture */}
<Skeleton className="size-10 rounded-md" />
{/* A badge */}
<Skeleton className="h-5 w-12 rounded-full" />
{/* A field or a button */}
<Skeleton className="h-[34px] w-28" />
{/* A line of text */}
<Skeleton className="h-4 w-40" />
</>
)
}Use one skeleton for each line of text. Make the last line shorter.
import { Skeleton } from 'ferry-ui'
export default function SkeletonText() {
return (
<div aria-busy="true" className="flex w-full max-w-xs flex-col gap-2">
<Skeleton className="h-5 w-40" />
<Skeleton className="h-3.5 w-full" />
<Skeleton className="h-3.5 w-full" />
<Skeleton className="h-3.5 w-3/4" />
</div>
)
}Use one skeleton for each row of a list. Give each skeleton the height of a row.
import { Skeleton } from 'ferry-ui'
export default function SkeletonList() {
return (
<div aria-busy="true" className="flex w-full max-w-sm flex-col gap-2">
<Skeleton className="h-11 w-full" />
<Skeleton className="h-11 w-full" />
<Skeleton className="h-11 w-full" />
</div>
)
}Show the skeleton while the data loads. Then show the content in the same place. Because the sizes are the same, the layout does not move.
import * as React from 'react'
import { Avatar, AvatarFallback, Button, Skeleton } from 'ferry-ui'
export default function SkeletonContent() {
const [loading, setLoading] = React.useState(false)
function reload() {
setLoading(true)
window.setTimeout(() => setLoading(false), 1500)
}
return (
<div className="flex w-full max-w-xs flex-col gap-4">
<div aria-busy={loading} className="flex items-center gap-3 rounded-lg border bg-surface-100 p-4">
{loading ? (
<>
<Skeleton className="size-8 rounded-full" />
<div className="flex h-10 flex-col justify-center gap-1.5">
<Skeleton className="h-4 w-24" />
<Skeleton className="h-3.5 w-36" />
</div>
</>
) : (
<>
<Avatar>
<AvatarFallback>MC</AvatarFallback>
</Avatar>
<div className="flex h-10 flex-col justify-center">
<span className="text-sm font-medium text-foreground">Maya Chen</span>
<span className="text-[13px] text-foreground-light">maya@example.com</span>
</div>
</>
)}
</div>
<Button className="self-start" loading={loading} onClick={reload}>
Load again
</Button>
</div>
)
}aria-busy on the region that loads.Skeleton accepts each attribute of the <div> element.
Skeleton has no props of its own. It accepts the attributes of the element it renders.