'use client'
import { useState } from 'react'
import { Avatar, Button, Card, Inline, Skeleton, Stack, Text } from '@hina-ui/react'
export default function Demo() {
const [loading, setLoading] = useState(true)
return (
<Stack className="w-full max-w-sm">
<Card>
<Inline gap="sm" align="start">
<Skeleton loading={loading} className="rounded-full">
<Avatar size="lg" src="/avatars/selfie.webp" alt="星见书音" />
</Skeleton>
<Stack gap="xs" className="min-w-0 flex-1">
<Skeleton loading={loading}>
<Text className="font-medium">星见书音</Text>
</Skeleton>
<Skeleton loading={loading}>
<Text tone="muted" size="sm">
翻译了 128 本轻小说
</Text>
</Skeleton>
</Stack>
</Inline>
</Card>
<Button size="sm" variant="soft" tone="neutral" onClick={() => setLoading(!loading)}>
{loading ? '显示内容' : '显示骨架'}
</Button>
</Stack>
)
}
tsx
用法
import { Skeleton } from '@hina-ui/react'
ts
用它包住真实内容,再传入 loading。loading 为真时内容隐藏但仍然参与布局,因此占位块的尺寸与内容将来的尺寸完全一致;loading 变为假之后包裹元素消失,只剩内容本身。
'use client'
import { useState } from 'react'
import { Button, Inline, Skeleton, Stack, Text } from '@hina-ui/react'
export default function Demo() {
const [loading, setLoading] = useState(true)
return (
<Stack className="w-full max-w-sm">
<Inline>
<Skeleton loading={loading}>
<Text>ATRI</Text>
</Skeleton>
<Skeleton loading={loading}>
<Text tone="muted" size="sm">
第 42 章
</Text>
</Skeleton>
</Inline>
<Button size="sm" variant="soft" tone="neutral" onClick={() => setLoading(!loading)}>
{loading ? '加载完成' : '重新加载'}
</Button>
</Stack>
)
}
tsx
不放内容时,Skeleton 就是一个普通的块,尺寸由类名给出。
import { Skeleton, Stack } from '@hina-ui/react'
export default function Demo() {
return (
<Stack gap="sm" className="w-full max-w-sm">
<Skeleton className="h-4 w-1/3" />
<Skeleton className="h-4 w-full" />
<Skeleton className="h-4 w-4/5" />
</Stack>
)
}
tsx
示例
形状
形状完全由类名决定:图片用圆角矩形,头像用 rounded-full,一行文字用一条短块。
import { Card, Inline, Skeleton, Stack } from '@hina-ui/react'
export default function Demo() {
return (
<Card className="w-full max-w-sm">
<Stack gap="sm">
<Skeleton className="h-32 w-full rounded-lg" />
<Inline gap="sm" align="center">
<Skeleton className="size-10 rounded-full" />
<Stack gap="xs" className="flex-1">
<Skeleton className="h-4 w-1/2" />
<Skeleton className="h-3 w-1/3" />
</Stack>
</Inline>
</Stack>
</Card>
)
}
tsx
行为
- 渐变光带从左向右扫过固定底色,默认周期为 1.2 秒;RTL 布局中方向反转。
- 系统开启减弱动态效果时停止扫光,占位块保持静止。
loading为假时组件只渲染传入的内容,不留下任何包裹元素。
无障碍
- 占位块带
aria-hidden和inert,屏幕阅读器会跳过它,其中的内容也无法获得焦点。 - 加载状态在拥有它的区域上播报,不必在每个占位块上重复。
API
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
loading | boolean | true | 是否显示占位块 |
as | string | 'span' | 渲染的标签 |
className | string | — | 追加至占位块的类名 |
| 属性 | 说明 |
|---|---|
children | 真实内容,占位块的尺寸取自它 |