本周新增
收藏 128 次,评论 32 条,新粉丝 12 位。
'use client'
import { useState } from 'react'
import { Button, Card, LoadingOverlay, Stack, Text } from '@hina-ui/react'
export default function Demo() {
const [loading, setLoading] = useState(false)
async function reload() {
setLoading(true)
await new Promise(resolve => setTimeout(resolve, 1800))
setLoading(false)
}
return (
<Stack gap="sm" align="start">
<Card className="relative w-96">
<Stack gap="xs">
<Text weight="medium">本周新增</Text>
<Text tone="muted" size="sm">
收藏 128 次,评论 32 条,新粉丝 12 位。
</Text>
</Stack>
<LoadingOverlay visible={loading} text="正在刷新" />
</Card>
<Button variant="outline" tone="neutral" disabled={loading} onClick={reload}>
刷新
</Button>
</Stack>
)
}
tsx
用法
import { LoadingOverlay } from '@hina-ui/react'
ts
加载遮罩铺满最近的定位容器,把内容压淡并放上加载指示;把它放进带 relative 的容器里,用 visible 控制显隐。它一出现就挡住下面的交互,但要过一小段时间才真正显示出来,很快结束的请求不会闪一下。
这块内容在加载期间被压淡,也不能点击。
'use client'
import { useState } from 'react'
import { Card, LoadingOverlay, Stack, Switch, Text } from '@hina-ui/react'
export default function Demo() {
const [loading, setLoading] = useState(true)
return (
<Stack gap="md" align="start">
<Switch checked={loading} onCheckedChange={setLoading}>
显示遮罩
</Switch>
<Card className="relative w-96">
<Text>这块内容在加载期间被压淡,也不能点击。</Text>
<LoadingOverlay visible={loading} />
</Card>
</Stack>
)
}
tsx
示例
文字
text 在加载指示下方显示一行说明,同时作为指示的无障碍名称。
正在把草稿同步到云端。
import { Card, LoadingOverlay, Text } from '@hina-ui/react'
export default function Demo() {
return (
<Card className="relative h-40 w-96">
<Text>正在把草稿同步到云端。</Text>
<LoadingOverlay visible text="正在同步" size="lg" />
</Card>
)
}
tsx
延时与最短停留
delay 是 visible 变为真之后等多久再淡入,默认 300 毫秒,这段时间内撤掉它什么都不会出现;设为 0 立即显示,适合用户主动触发、明知要等的操作。minVisible 是显示之后至少停留多久,默认 300 毫秒,避免刚出现就消失的闪动;设为 0 则请求一结束就淡出。
默认延时下快请求看不到遮罩;打开「立即显示」后两种请求都会看到。
'use client'
import { useState } from 'react'
import { Button, Card, Inline, LoadingOverlay, Stack, Switch, Text } from '@hina-ui/react'
export default function Demo() {
const [loading, setLoading] = useState(false)
const [immediate, setImmediate] = useState(false)
const [result, setResult] = useState('')
async function request(ms: number) {
setLoading(true)
setResult('')
await new Promise(resolve => setTimeout(resolve, ms))
setLoading(false)
setResult(`${ms} 毫秒后返回`)
}
return (
<Stack gap="md" align="start">
<Inline gap="md" align="center">
<Button variant="outline" tone="neutral" disabled={loading} onClick={() => request(150)}>
快请求
</Button>
<Button variant="outline" tone="neutral" disabled={loading} onClick={() => request(1500)}>
慢请求
</Button>
<Switch checked={immediate} onCheckedChange={setImmediate}>
立即显示
</Switch>
</Inline>
<Card className="relative w-96">
<Text>{result || '默认延时下快请求看不到遮罩;打开「立即显示」后两种请求都会看到。'}</Text>
<LoadingOverlay visible={loading} delay={immediate ? 0 : undefined} />
</Card>
</Stack>
)
}
tsx
自定义内容
children 替换薄面里的加载指示与文字,可以放品牌形象、进度说明等自己的内容;薄面、延时与挡住交互的行为不变。自定义内容里应当有 role="status" 或者等价的文字,辅助技术才知道这里在等待。
书架里的内容正在整理。

书音正在整理书架,稍等一下。
import { Card, Image, LoadingOverlay, Stack, Text } from '@hina-ui/react'
export default function Demo() {
return (
<Card className="relative h-56 w-96">
<Text>书架里的内容正在整理。</Text>
<LoadingOverlay visible delay={0}>
<Stack gap="xs" align="center" role="status">
<Image
src="/mascot/run.gif"
alt="星见书音抱着书跑过来"
ratio={1}
fit="contain"
skeleton={false}
eager
lazy={false}
className="size-28"
/>
<Text size="sm" tone="muted">
书音正在整理书架,稍等一下。
</Text>
</Stack>
</LoadingOverlay>
</Card>
)
}
tsx
覆盖整个视口
fixed 让遮罩覆盖整个视口,用于整页级别的等待。
'use client'
import { useState } from 'react'
import { Button, Image, LoadingOverlay, Stack, Text } from '@hina-ui/react'
export default function Demo() {
const [loading, setLoading] = useState(false)
async function reload() {
setLoading(true)
await new Promise(resolve => setTimeout(resolve, 2000))
setLoading(false)
}
return (
<>
<Button variant="outline" tone="neutral" onClick={reload}>
覆盖整页两秒
</Button>
<LoadingOverlay visible={loading} fixed>
<Stack gap="xs" align="center" role="status">
<Image
src="/mascot/run.gif"
alt="星见书音抱着书跑过来"
ratio={1}
fit="contain"
skeleton={false}
eager
lazy={false}
className="size-32"
/>
<Text size="sm" tone="muted">
正在切换账号
</Text>
</Stack>
</LoadingOverlay>
</>
)
}
tsx
行为
visible变为真时立即挡住区域内的交互,等待delay后淡入;变为假时淡出并移除,显示未满minVisible则补足后再淡出。- 延时内撤掉不会闪现。
- 遮罩不停止页面滚动,也不接管焦点;需要打断整页任务时用 Dialog 的锁定。
无障碍
- 加载指示是
role="status",名称取自text,没有时取语言包的「加载中」。 - 显示的文字对辅助技术隐藏,避免与指示的名称重复播报。
API
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
visible | boolean | false | 是否显示 |
text | string | — | 指示下方的说明 |
fixed | boolean | false | 是否覆盖整个视口 |
size | 'sm' | 'md' | 'lg' | 'md' | 加载指示的尺寸 |
delay | number | 300 | 显示前等待的毫秒数, 0 立即显示 |
minVisible | number | 300 | 显示后至少停留的毫秒数 |
className | string | — | 追加至遮罩的类名 |
内容属性
| 属性 | 说明 |
|---|---|
children | 薄面里的内容,默认是加载指示与 text |