Bỏ qua đến nội dung

Vùng cuộn

Một vùng chứa có thể cuộn với thanh cuộn tùy chỉnh, tương thích trên nhiều trình duyệt dành cho các khung trò chuyện, thanh bên và cây thư mục — kèm theo nút cuộn kiểu neobrutalist dày dặn.

import * as React from "react"

import { ScrollArea } from "@/components/ui/scroll-area"

Scroll area thay thanh cuộn mặc định của trình duyệt bằng thanh cuộn do bạn tự tạo kiểu — cơ chế cuộn native vẫn nằm bên dưới, nên hành vi con lăn chuột, cảm ứng và cuộn theo quán tính không bị ảnh hưởng. Được xây dựng trên thành phần Base UI Scroll Area và tạo kiểu theo công thức neobrutalist: con trượt đặc, dày dặn mang màu viền và vòng focus đậm trên viewport.

Nên dùng khi:

  • Khung chat và log — cố định chiều cao và để tin nhắn cuộn bên trong panel thay vì cả trang.
  • Sidebar và cây tệp — các danh sách điều hướng dài cuộn độc lập với nội dung chính.
  • Dải cuộn ngang — hàng thẻ tag, bộ sưu tập card và bảng rộng qua orientation="horizontal".

Cài đặt

pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/scroll-area.json
npx shadcn@latest add https://neobrutalism.com/r/base/scroll-area.json
yarn dlx shadcn@latest add https://neobrutalism.com/r/base/scroll-area.json
bunx --bun shadcn@latest add https://neobrutalism.com/r/base/scroll-area.json

Cài đặt các phụ thuộc sau:

pnpm add @base-ui/react
npm install @base-ui/react
yarn add @base-ui/react
bun add @base-ui/react

Sao chép và dán đoạn mã sau vào dự án của bạn.

components/ui/scroll-area.tsx
"use client"

import * as React from "react"
import { ScrollArea as ScrollAreaPrimitive } from "radix-ui"

import { cn } from "@/lib/utils"

function ScrollArea({
  className,
  children,
  ...props
}: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {
  return (
    <ScrollAreaPrimitive.Root
      data-slot="scroll-area"
      className={cn("relative", className)}
      {...props}
    >
      <ScrollAreaPrimitive.Viewport
        data-slot="scroll-area-viewport"
        className="size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary"
      >
        {children}
      </ScrollAreaPrimitive.Viewport>
      <ScrollBar />
      <ScrollAreaPrimitive.Corner />
    </ScrollAreaPrimitive.Root>
  )
}

function ScrollBar({
  className,
  orientation = "vertical",
  ...props
}: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {
  return (
    <ScrollAreaPrimitive.ScrollAreaScrollbar
      data-slot="scroll-area-scrollbar"
      data-orientation={orientation}
      orientation={orientation}
      className={cn(
        "flex touch-none p-px transition-colors select-none data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:h-full data-vertical:w-2.5 data-vertical:border-l data-vertical:border-l-transparent",
        className
      )}
      {...props}
    >
      <ScrollAreaPrimitive.ScrollAreaThumb
        data-slot="scroll-area-thumb"
        className="relative flex-1 rounded bg-border"
      />
    </ScrollAreaPrimitive.ScrollAreaScrollbar>
  )
}

export { ScrollArea, ScrollBar }

Cập nhật các đường dẫn import cho phù hợp với thiết lập dự án của bạn.

Cách dùng

import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"
<ScrollArea className="h-[200px] w-[350px] rounded-md border p-4">
  Your scrollable content here.
</ScrollArea>

Kết hợp

Dùng cách kết hợp sau để xây dựng một ScrollArea:

ScrollArea
└── ScrollBar

Ví dụ

Ngang

Dùng ScrollBar với orientation="horizontal" để cuộn theo chiều ngang.

import * as React from "react"
import Image from "next/image"

RTL

Để bật hỗ trợ RTL trong Neobrutalism, hãy xem hướng dẫn cấu hình RTL.

"use client"

import * as React from "react"

Khả năng truy cập

Không có mẫu WAI-ARIA nào cho scroll area — và cũng không cần, vì thành phần Base UI giữ nguyên một vùng cuộn native thật bên dưới, nên thao tác cuộn bằng con lăn, cảm ứng và bàn phím hoạt động đúng như của trình duyệt. Không phải trình duyệt nào cũng tự cho phép focus vùng cuộn bằng bàn phím: nếu nội dung không chứa phần tử nào focus được, hãy thêm tabIndex={0} và một aria-label vào viewport để người dùng bàn phím có thể tiếp cận và cuộn nó — phần style đã kèm sẵn vòng focus hiển thị cho trường hợp này. Thanh cuộn và con trượt tùy biến chỉ là tiện ích cho con trỏ chuột; chúng không bao giờ được là cách cuộn duy nhất.

Tham chiếu API

Xem tài liệu Base UI Scroll Area.