"use client" /** * ScrollArea — Radix-backed scroll container with always-visible-on-hover * scrollbars that respect platform conventions. * * Use when you need an **explicitly bounded** scrolling region (lists in * popovers, sidebar nav trees, long config panels) and the default * browser scrollbar is too coarse or visually noisy. * * Bound it with a height (`h-64`) or a max height (`max-h-80`) on the root. A * max height reaches the scrolling box through `max-h-[inherit]` below, because * that box is sized `size-full` and `h-full` against an `auto` height resolves to * `auto`: without the inherit, a `max-h-*` root would clip nothing and the list * would paint straight out of whatever panel it sits in. * * Accessibility: * - The scrolling box carries `role="region"` + `viewportLabel`, and enters the * Tab order only while it actually scrolls (`useScrollOverflow`), which is * axe's `scrollable-region-focusable` without a focus stop on every short list. */ import * as React from "react" import { ScrollArea as ScrollAreaPrimitive } from "radix-ui" import { useScrollOverflow } from "../../hooks/use-scroll-overflow" import { cn } from "../../lib/utils" function ScrollArea({ className, children, viewportLabel = "Scrollable content", ...props }: React.ComponentProps & { /** Accessible name for the scroll viewport (WCAG 1.4.10 / keyboard scroll). */ viewportLabel?: string }) { const { ref, overflowing } = useScrollOverflow() return ( {/* Not `asChild` with a `ScrollRegion` inside, which is what this was. Radix renders the viewport's overflow on one div and a `display: table` content div inside it; `asChild` collapsed the two, and overflow does not apply to a table box, so nothing clipped and nothing scrolled. The region's own behaviour is kept by wearing its attributes here. */} {children} ) } function ScrollBar({ className, orientation = "vertical", ...props }: React.ComponentProps) { return ( ) } export { ScrollArea, ScrollBar }