Skip to content
  1. Keyline UI
  2. Scroll area
Keyline UIComponents
  • Get started
    • Installation
    • Theming
    • Modes
    • Configuration
    • Composition
  • Actions
    • Button
    • Button group
    • Split button
    • Toggle
    • Toggle group
    • Toolbar
    • Menu
    • Menubar
    • Context menu
  • Inputs
    • Field and form
    • Checkbox
    • Checkbox group
    • Radio group
    • Switch
    • Slider
    • Segmented
    • Select
    • Native select
    • Combobox
    • Multiselect
    • Number field
    • OTP field
    • Time field
    • Date picker and calendar
    • Date range
  • Data
    • Table
    • Chart
    • Stat and meter
    • Status and badge
    • Progress
    • Skeleton
    • Empty
    • Avatar
    • Kbd
    • Marker
  • Navigation
    • Tabs
    • Breadcrumb
    • Pagination
    • Nav
    • Navigation menu
    • Command menu
  • Overlays
    • Dialog
    • Alert dialog
    • Drawer
    • Sheet
    • Popover
    • Hover card
    • Tooltip
    • Toast
    • Notice
  • Layout
    • App shell
    • Sidebar
    • Panel
    • Resizable
    • Scroll area
    • Accordion
    • Collapsible
    • Carousel
    • Inspector
    • Item
    • Direction
  • Conversation
    • Message
    • Bubble
    • Message scroller
    • Attachment
    • Questionnaire
  • Blocks
    • Shipments

Scroll area

Native scrolling, so wheel, touch, keyboard and find-in-page all work, with a bar drawn as a cell on the frame's edge. Where the system's scrollbars overlay content, the thumb shows while you scroll and then fades; where they take space, it always shows.

Loading the live example…

"use client"

import { Item, ItemContent, ItemList, ItemMeta } from "@/components/keyline/ui/item"
import { Panel, PanelBody, PanelHeader } from "@/components/keyline/ui/panel"
import { ScrollArea } from "@/components/keyline/ui/scroll-area"

const WHO = ["Dwight", "Jim", "Phyllis", "Stanley", "Andy", "Darryl"]
const WHAT = ["closed a sale with", "called", "emailed a quote to", "delivered to", "followed up with", "visited"]
const CLIENTS = ["Lackawanna County", "Blue Cross of Pennsylvania", "Vance Refrigeration", "Scranton Business Park", "Penn Paper Supply", "Mount Airy Casino"]

// a day's activity, a line every quarter of an hour from 9:00
const LOG = Array.from({ length: 32 }, (_, i) => {
  const m = 9 * 60 + i * 15
  return {
    at: `${Math.floor(m / 60)}:${String(m % 60).padStart(2, "0")}`,
    line: `${WHO[i % 6]} ${WHAT[(i * 5) % 6]} ${CLIENTS[(i * 7) % 6]}`,
  }
})

export function ActivityLog() {
  return (
    <Panel>
      <PanelHeader title="Today's activity" description="32 entries since 9:00" />
      <PanelBody flush>
        <ScrollArea label="Today's activity" className="h-[260px]">
          <ItemList layout="cell" aria-label="Activity">
            {LOG.map((l) => (
              <Item key={l.at}>
                <ItemContent title={l.line} />
                <ItemMeta>{l.at}</ItemMeta>
              </Item>
            ))}
          </ItemList>
        </ScrollArea>
      </PanelBody>
    </Panel>
  )
}

Installation

npx shadcn@latest add @keyline-ui/scroll-area

Run it where your components.json is. The first time, map the @keyline-ui registry: one command, in Installation.

Usage

import { ScrollArea } from "@/components/keyline/ui/scroll-area"
<ScrollArea label="Today's activity" className="h-[260px]">
  …
</ScrollArea>

Props

PropTypeDefaultDescription
labelstringDefault —Names the region. It takes focus when it overflows, so keyboard users can scroll it.
scrollbars"vertical" | "horizontal" | "both"Default "vertical"Which bars to draw. An axis without one still scrolls.
scrollbarVisibility"system" | "scroll" | "always"Default "system"When the thumb shows.
track"cell" | "rail"Default "cell"cell inside a frame; rail, a 1px line, on the page background.
viewportClassName · contentClassNamestringDefault —For the scrolling viewport and the content inside it.

Built on Base UI Scroll Area. This site's sidebar and code blocks scroll in it.

Sheet 61 of 73PreviousResizableNextAccordion
On this page