NovaUI
Components

ScrollArea

A custom scrollable container with styled scrollbars for vertical and horizontal overflow.

The ScrollArea component wraps React Native's ScrollView with custom-styled scrollbar indicators. It tracks scroll position, content size, and viewport dimensions via context, and renders a ScrollBar thumb that reflects the current scroll state.

Preview

Tags

v1.0.0-beta.1
v1.0.0-beta.2
v1.0.0-beta.3
v1.0.0-rc.1
v1.0.0-rc.2
v1.0.0
v1.1.0
v1.2.0
v1.3.0
v2.0.0

Installation

npx novaui-cli add scroll-area

Import

import { ScrollArea, ScrollBar } from 'novaui-components'

Basic Usage

The ScrollArea is a compound component with these parts:

  • ScrollArea — Root container with relative flex-1 styling that wraps a ScrollView with flex-1 rounded-[inherit]
  • ScrollBar — Custom scrollbar thumb indicator positioned absolutely with absolute touch-none p-0.5

Tags

v1.0.0-beta.1
v1.0.0-beta.2
v1.0.0-beta.3
v1.0.0-rc.1
v1.0.0-rc.2
v1.0.0
v1.1.0
v1.2.0
v1.3.0
v2.0.0
import { View, Text } from 'react-native'
import { ScrollArea } from 'novaui-components'
import { Separator } from 'novaui-components'

const tags = [
  'v1.0.0-beta.1',
  'v1.0.0-beta.2',
  'v1.0.0-beta.3',
  'v1.0.0-rc.1',
  'v1.0.0-rc.2',
  'v1.0.0',
  'v1.1.0',
  'v1.2.0',
  'v1.3.0',
  'v2.0.0',
]

export function BasicScrollArea() {
  return (
    <ScrollArea className="h-48 w-full max-w-sm rounded-md border border-border">
      <View className="p-4">
        <Text className="mb-4 text-sm font-medium leading-none text-foreground">
          Tags
        </Text>
        {tags.map((tag) => (
          <View key={tag}>
            <Text className="text-sm text-foreground">{tag}</Text>
            <Separator className="my-2" />
          </View>
        ))}
      </View>
    </ScrollArea>
  )
}

Horizontal Scrolling

Use horizontal on the ScrollArea and add a horizontal ScrollBar:

Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
import { View, Text } from 'react-native'
import { ScrollArea, ScrollBar } from 'novaui-components'

const items = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6']

export function HorizontalScrollArea() {
  return (
    <ScrollArea className="w-full max-w-md rounded-md border border-border" horizontal>
      <View className="flex-row gap-4 p-4">
        {items.map((item) => (
          <View
            key={item}
            className="h-20 w-36 shrink-0 items-center justify-center rounded-md bg-muted"
          >
            <Text className="text-sm text-foreground">{item}</Text>
          </View>
        ))}
      </View>
      <ScrollBar orientation="horizontal" />
    </ScrollArea>
  )
}

With Custom Content

Use ScrollArea for any overflowing content such as a chat log or settings list:

AliceHey, how's it going?
YouPretty good! Working on the UI.
AliceNice! Let me know if you need help.
YouWill do, thanks!
AliceAlso, did you see the new design specs?
YouNot yet, sending them over?
import { View, Text } from 'react-native'
import { ScrollArea } from 'novaui-components'

export function ChatScrollArea() {
  return (
    <ScrollArea className="h-56 w-full max-w-sm rounded-lg border border-border">
      <View className="flex-col gap-3 p-4">
        <View className="gap-1 rounded-md bg-muted p-3">
          <Text className="text-xs font-medium text-foreground">Alice</Text>
          <Text className="text-sm text-muted-foreground">
            Hey, how's it going?
          </Text>
        </View>
        <View className="gap-1 rounded-md bg-primary/10 p-3 self-end">
          <Text className="text-xs font-medium text-foreground">You</Text>
          <Text className="text-sm text-muted-foreground">
            Pretty good! Working on the UI.
          </Text>
        </View>
        {/* ... more messages */}
      </View>
    </ScrollArea>
  )
}

Props API

ScrollArea Props

Extends React.ComponentPropsWithoutRef<typeof ScrollView>:

PropTypeDefaultDescription
classNamestring-Additional CSS classes for the outer container (base: relative flex-1)
viewportClassNamestring-Additional CSS classes for the inner ScrollView (base: flex-1 rounded-[inherit])
horizontalbooleanfalseEnable horizontal scrolling
childrenReactNode-Content and optional ScrollBar components

ScrollBar Props

Extends React.ComponentPropsWithoutRef<typeof View>:

PropTypeDefaultDescription
orientation'vertical' | 'horizontal''vertical'Direction of the scrollbar
classNamestring-Additional CSS classes (vertical base: right-0 top-0 h-full w-2.5 border-l border-l-transparent, horizontal base: bottom-0 left-0 h-2.5 w-full flex-row border-t border-t-transparent)

Best Practices

  1. Set a fixed height: The ScrollArea needs a constrained height (or width for horizontal) to enable scrolling. Use className="h-48" or similar.

  2. Default scrollbar: If no ScrollBar child is provided, a vertical ScrollBar is rendered automatically.

  3. Hide native indicators: The component sets showsVerticalScrollIndicator={false} and showsHorizontalScrollIndicator={false} by default to avoid double scrollbars.

  4. Horizontal scroll: Pass horizontal to ScrollArea and add <ScrollBar orientation="horizontal" /> as a child.

  5. Performance: The scroll event throttle is set to 16ms (60fps). For lists with many items, consider using FlatList instead.

  • Use Separator to divide items within a scrollable list
  • Combine with Card to create scrollable card content
  • Use Table for scrollable tabular data

On this page