第 1 章
第 2 章
第 3 章
第 4 章
第 5 章
第 6 章
第 7 章
第 8 章
第 9 章
第 10 章
第 11 章
第 12 章
第 13 章
第 14 章
第 15 章
第 16 章
第 17 章
第 18 章
第 19 章
第 20 章
第 21 章
第 22 章
第 23 章
第 24 章
<script setup lang="ts">
import { Card, ScrollArea, Stack, Text } from '@hina-ui/vue'
const chapters = Array.from({ length: 24 }, (_, i) => `第 ${i + 1} 章`)
</script>
<template>
<Card class="w-full max-w-xs" :padded="false">
<ScrollArea class="h-64">
<Stack gap="none" class="p-2">
<Text v-for="chapter in chapters" :key="chapter" size="sm" class="px-3 py-2">
{{ chapter }}
</Text>
</Stack>
</ScrollArea>
</Card>
</template>
用法
import { ScrollArea } from '@hina-ui/vue'
给区域一个高度,超出的部分即可滚动。滚动条浮在内容之上,不占用内容的宽度,并且在各个平台上外观一致。
第 1 行
第 2 行
第 3 行
第 4 行
第 5 行
第 6 行
第 7 行
第 8 行
第 9 行
第 10 行
第 11 行
第 12 行
<script setup lang="ts">
import { ScrollArea, Stack, Text } from '@hina-ui/vue'
</script>
<template>
<ScrollArea class="bg-inset h-40 w-full max-w-sm rounded-md">
<Stack class="p-4">
<Text v-for="i in 12" :key="i">第 {{ i }} 行</Text>
</Stack>
</ScrollArea>
</template>
组件库中所有需要内部滚动的地方都经由这个组件:下拉列表、菜单、Dialog 和 Drawer 的正文、AppShell 的主区域。其他组件不各自引入滚动库,因此滚动行为不会出现分歧。
示例
方向
direction 取 vertical、horizontal 或 both。横向区域中滚轮会横向滚动,因为鼠标没有对应的横向手势,而浮层滚动条大多数时候是隐藏的。
<script setup lang="ts">
import { Card, Inline, ScrollArea } from '@hina-ui/vue'
</script>
<template>
<ScrollArea direction="horizontal" class="bg-inset w-full max-w-md rounded-md">
<Inline gap="sm" :wrap="false" class="p-4">
<Card
v-for="i in 12"
:key="i"
class="bg-surface grid size-20 shrink-0 place-items-center"
:padded="false"
>
{{ i }}
</Card>
</Inline>
</ScrollArea>
</template>
内容方向继承外层,也可用 dir="rtl" 显式设置。横向阴影的位置和渐变方向一起镜像,始终从边缘向内容内侧淡出。
边缘阴影
某一侧还有未显示的内容时,该侧出现阴影,滚动到尽头后消失。边界本身已经足够清楚时,把 shadow 设为假。
带边缘阴影
第 1 行
第 2 行
第 3 行
第 4 行
第 5 行
第 6 行
第 7 行
第 8 行
第 9 行
第 10 行
关闭边缘阴影
第 1 行
第 2 行
第 3 行
第 4 行
第 5 行
第 6 行
第 7 行
第 8 行
第 9 行
第 10 行
<script setup lang="ts">
import { ScrollArea, Stack, Text } from '@hina-ui/vue'
</script>
<template>
<Stack class="w-full max-w-sm">
<Stack gap="xs">
<Text tone="muted" size="sm">带边缘阴影</Text>
<ScrollArea class="bg-inset h-32 rounded-md">
<Stack class="p-4">
<Text v-for="i in 10" :key="i">第 {{ i }} 行</Text>
</Stack>
</ScrollArea>
</Stack>
<Stack gap="xs">
<Text tone="muted" size="sm">关闭边缘阴影</Text>
<ScrollArea :shadow="false" class="bg-inset h-32 rounded-md">
<Stack class="p-4">
<Text v-for="i in 10" :key="i">第 {{ i }} 行</Text>
</Stack>
</ScrollArea>
</Stack>
</Stack>
</template>
滚动条的显示时机
autoHide 决定滚动条何时淡出:never 始终显示,scroll 滚动时显示,leave 在指针离开前一直显示,move 在区域内移动指针时显示。
never
第 1 行
第 2 行
第 3 行
第 4 行
第 5 行
第 6 行
第 7 行
第 8 行
scroll
第 1 行
第 2 行
第 3 行
第 4 行
第 5 行
第 6 行
第 7 行
第 8 行
leave
第 1 行
第 2 行
第 3 行
第 4 行
第 5 行
第 6 行
第 7 行
第 8 行
move
第 1 行
第 2 行
第 3 行
第 4 行
第 5 行
第 6 行
第 7 行
第 8 行
<script setup lang="ts">
import { ScrollArea, Stack, Text } from '@hina-ui/vue'
const modes = ['never', 'scroll', 'leave', 'move'] as const
</script>
<template>
<Stack class="w-full max-w-sm">
<Stack v-for="mode in modes" :key="mode" gap="xs">
<Text tone="muted" size="sm">{{ mode }}</Text>
<ScrollArea :auto-hide="mode" class="bg-inset h-24 rounded-md">
<Stack class="p-4">
<Text v-for="i in 8" :key="i">第 {{ i }} 行</Text>
</Stack>
</ScrollArea>
</Stack>
</Stack>
</template>
键盘访问
区域内可以滚动但没有可聚焦元素时,键盘无法到达它。设置 focusable 后区域进入 Tab 顺序,渲染为 role="region",并用 label 提供名称。
第 1 行
第 2 行
第 3 行
第 4 行
第 5 行
第 6 行
第 7 行
第 8 行
第 9 行
第 10 行
<script setup lang="ts">
import { ScrollArea, Stack, Text } from '@hina-ui/vue'
</script>
<template>
<ScrollArea focusable label="更新说明" class="bg-inset h-32 w-full max-w-sm rounded-md">
<Stack class="p-4">
<Text v-for="i in 10" :key="i">第 {{ i }} 行</Text>
</Stack>
</ScrollArea>
</template>
行为
- 滚动条覆盖在内容之上,内容开始溢出时布局宽度不变。
- 组件接管之前即可原生滚动。自定义滚动条在挂载后的下一帧初始化,并保留原生滚动位置;浮层首次打开或重新打开时,都不会等待浏览器空闲或滚动停止。
- 内容因动画改变尺寸时滚动条自行更新,不需要额外接入观察器。
- 对话框、菜单这类锁定页面的浮层打开时,区域立即停止响应滚轮与触摸;浮层里的滚动区域不受影响,浮层关闭后恢复。
无障碍
- 不设置
focusable时,区域是普通容器:键盘可以到达其中的可聚焦元素,浏览器随之滚动。 - 设置
focusable后,区域以role="region"进入 Tab 顺序,名称取自label,方向键可以滚动它。
API
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
direction | 'vertical' | 'horizontal' | 'both' | 'vertical' | 滚动的方向 |
dir | 'ltr' | 'rtl' | 'auto' | 继承 | 视口与阴影层的内容方向 |
autoHide | 'never' | 'scroll' | 'leave' | 'move' | 'leave' | 滚动条何时淡出 |
scrollbar | boolean | true | 是否显示滚动条 |
wheelRedirect | boolean | true | 横向区域中滚轮是否横向滚动 |
shadow | boolean | true | 是否显示边缘阴影 |
focusable | boolean | false | 是否让区域进入 Tab 顺序 |
label | string | — | 无障碍名称, focusable 时使用 |
class | string | — | 追加至外层元素的类名 |
| 插槽 | 说明 |
|---|---|
default | 滚动区域的内容 |
| 暴露 | 类型 | 说明 |
|---|---|---|
viewport | HTMLElement | undefined | 滚动元素,在挂载后的下一帧完成初始化后可用。 |