Lzh on GitHub

ScrollArea

增强本机滚动功能,实现自定义、跨浏览器样式。
<script setup lang="ts">
import { ScrollAreaRoot, ScrollAreaScrollbar, ScrollAreaThumb, ScrollAreaViewport } from 'reka-ui'

const tags = Array.from({ length: 50 }).map((_, i, a) => `v1.2.0-beta.${a.length - i}`)
</script>

<template>
  <ScrollAreaRoot
    class="w-[200px] h-[225px] relative overflow-hidden shadow-sm bg-white border rounded-lg"
    style="--scrollbar-size: 10px"
  >
    <div class="absolute top-0 z-10 w-full h-6 bg-gradient-to-t from-transparent to-white" />
    <ScrollAreaViewport class="w-full h-full rounded">
      <div class="py-[15px] px-5">
        <div class="text-grass11 text-sm leading-[18px] font-semibold">
          Tags
        </div>
        <div
          v-for="tag in tags"
          :key="tag"
          class="text-mauve12 text-xs leading-[18px] mt-2.5 pt-2.5 border-t border-t-mauve6"
        >
          {{ tag }}
        </div>
      </div>
    </ScrollAreaViewport>
    <ScrollAreaScrollbar
      class="flex select-none touch-none p-0.5 z-20 bg-gray-200 transition-colors duration-[160ms] ease-out hover:bg-gray-700 data-[orientation=vertical]:w-2.5 data-[orientation=horizontal]:flex-col data-[orientation=horizontal]:h-2.5"
      orientation="vertical"
    >
      <ScrollAreaThumb
        class="flex-1 bg-mauve10 rounded-[10px] relative before:content-[''] before:absolute before:top-1/2 before:left-1/2 before:-translate-x-1/2 before:-translate-y-1/2 before:w-full before:h-full before:min-w-[44px] before:min-h-[44px]"
      />
    </ScrollAreaScrollbar>
    <ScrollAreaScrollbar
      class="flex select-none touch-none p-0.5 bg-gray-600 transition-colors duration-[160ms] ease-out hover:bg-black-800 data-[orientation=vertical]:w-2.5 data-[orientation=horizontal]:flex-col data-[orientation=horizontal]:h-2.5"
      orientation="horizontal"
    >
      <ScrollAreaThumb
        class="flex-1 bg-gray-900 rounded-[10px] relative before:content-[''] before:absolute before:top-1/2 before:left-1/2 before:-translate-x-1/2 before:-translate-y-1/2 before:w-full before:h-full before:min-w-[44px] before:min-h-[44px]"
      />
    </ScrollAreaScrollbar>

    <div class="absolute bottom-0 z-10 w-full h-6 bg-gradient-to-b from-transparent to-white" />
  </ScrollAreaRoot>
</template>

功能特点

  • 滚动条位于可滚动内容之上,不占用空间。
  • 滚动是原生的;没有通过 CSS 变换进行底层位置移动。
  • 仅在与控件交互时模拟指针行为,因此键盘控件不受影响。
  • 支持从右到左的方向。

安装

从命令行安装组件。

$ npm add reka-ui

结构

导入所有部分并将其组合在一起。

<script setup>
  import { ScrollAreaRoot, ScrollAreaScrollbar, ScrollAreaThumb, ScrollAreaViewport } from 'reka-ui'
</script>

<template>
  <ScrollAreaRoot>
    <ScrollAreaViewport />
    <ScrollAreaScrollbar orientation="horizontal">
      <ScrollAreaThumb />
    </ScrollAreaScrollbar>
    <ScrollAreaScrollbar orientation="vertical">
      <ScrollAreaThumb />
    </ScrollAreaScrollbar>
    <ScrollAreaCorner />
  </ScrollAreaRoot>
</template>

API 参考

Root

包含滚动区域的所有部分。

属性默认值类型描述
as'div'AsTag | Component此组件应渲染为的元素或组件。可以通过 asChild 覆盖。
asChildfalseboolean将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南
dir'ltr' | 'rtl'组合框(如果适用)的阅读方向。如果省略,则从 ConfigProvider 全局继承或假定为从左到右 (LTR) 阅读模式。
scrollHideDelay600number如果类型设置为 scrollhover,此 prop 确定在用户停止与滚动条交互后,滚动条隐藏前的毫秒时长。
type'hover''scroll' | 'always' | 'hover' | 'auto'描述滚动条可见性的性质,类似于 MacOS 中滚动条偏好设置控制原生滚动条可见性的方式。
  • auto - 表示当内容在相应方向溢出时,滚动条可见。
  • always - 表示无论内容是否溢出,滚动条始终可见。
  • scroll - 表示当用户沿其相应方向滚动时,滚动条可见。
  • hover - 当用户沿其相应方向滚动并且用户悬停在滚动区域上时。

方法

方法名称类型描述
scrollTop() => void滚动视口到顶部。
scrollTopLeft() => void滚动视口到左上角。

Viewport

滚动区域的视口。

属性默认值类型描述
as'div'AsTag | Component此组件应渲染为的元素或组件。可以通过 asChild 覆盖。
asChildfalseboolean将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南
noncestringnonce 属性添加到 style 标签中,可供内容安全策略使用。如果省略,则从 ConfigProvider 全局继承。

Scrollbar

垂直滚动条。添加第二个带有 orientation prop 的 Scrollbar 可启用水平滚动。

使用 Presence 组件构建 - 支持任何[动画技术](animation techniques),同时保持对存在(presence)触发事件的访问。
属性默认值类型描述
as'div'AsTag | Component此组件应渲染为的元素或组件。可以通过 asChild 覆盖。
asChildfalseboolean将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南
forceMountfalseboolean当需要更多控制时,用于强制挂载。在与 Vue 动画库控制动画时很有用。
orientation'vertical''vertical' | 'horizontal'滚动条的方向。

数据属性

属性
[data-state]"visible" | "hidden"
[data-orientation]"vertical" | "horizontal"

Thumb

用于 ScrollAreaScrollbar 中的滑块。

属性默认值类型描述
as'div'AsTag | Component此组件应渲染为的元素或组件。可以通过 asChild 覆盖。
asChildfalseboolean将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南

数据属性

属性
[data-state]"visible" | "hidden"

Corner

垂直和水平滚动条相交的角落。

属性默认值类型描述
as'div'AsTag | Component此组件应渲染为的元素或组件。可以通过 asChild 覆盖。
asChildfalseboolean将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南

示例

定制滚动

将公开的 viewport(视口)用于在默认方法之外修改或设置滚动位置。

<script setup lang="ts">
import { ScrollAreaRoot, ScrollAreaScrollbar, ScrollAreaThumb, ScrollAreaViewport } from 'reka-ui'

const scrollArea = useTemplateRef('scrollArea')
function scrollToBottom() {
  const viewport = scrollArea.value?.viewport
  if (viewport) {
    const top = scrollArea.value?.$el.scrollHeight
    container.scrollTo({
      top,
      behavior: 'smooth'
    })
  }
}
</script>

<template>
  <ScrollAreaRoot ref="scrollArea">
    <ScrollAreaViewport />
    <ScrollAreaScrollbar orientation="horizontal">
      <ScrollAreaThumb />
    </ScrollAreaScrollbar>
    <ScrollAreaScrollbar orientation="vertical">
      <ScrollAreaThumb />
    </ScrollAreaScrollbar>
    <ScrollAreaCorner />
  </ScrollAreaRoot>
</template>

可访问性

在大多数情况下,最好依赖原生滚动并利用 CSS 中可用的自定义选项。当这还不够时,ScrollArea 在保持浏览器原生滚动行为(以及可访问性功能,如键盘滚动)的同时提供了额外的可定制性。

键盘交互

由于组件依赖于原生滚动,因此默认支持通过键盘滚动。特定键盘交互在不同平台之间可能有所不同,因此我们在此处不作具体说明,也不添加特定的事件监听器来处理通过按键事件滚动。