Skip to content
Esc
navigateopen⌘Jpreview
On this page

Scroll Area

Augments native scroll functionality for custom, cross-browser styling.

import * as React from 'react';

import * as stylex from '@stylexjs/stylex';

import { ScrollArea } from '@/components/ui/scroll-area';
import { Separator } from '@/components/ui/separator';
import { space, fontSize, fontWeight, stroke, container } from '@/lib/constants.stylex';
import { colors, font, radius } from '@/lib/tokens.stylex';

const tags = Array.from({ length: 50 }, (_, i) => `v1.2.0-beta.${50 - i}`);

export default function ScrollAreaDemo() {
  return (
    <ScrollArea style={styles.root}>
      <div {...stylex.props(styles.inner)}>
        <h4 {...stylex.props(styles.heading)}>Tags</h4>
        {tags.map((tag) => (
          <React.Fragment key={tag}>
            <div {...stylex.props(styles.tag)}>{tag}</div>
            <Separator />
          </React.Fragment>
        ))}
      </div>
    </ScrollArea>
  );
}

const styles = stylex.create({
  root: {
    borderColor: colors.border,
    borderRadius: radius.md,
    borderStyle: 'solid',
    borderWidth: stroke.border,
    height: container.xs,
    width: container.xs,
  },
  inner: {
    display: 'flex',
    flexDirection: 'column',
    fontFamily: font.sans,
    gap: space.s2,
    padding: space.s4,
  },
  heading: {
    fontSize: fontSize.sm,
    fontWeight: fontWeight.medium,
    margin: 0,
  },
  tag: {
    fontSize: fontSize.sm,
  },
});

Install

npx shadcn@latest add @madeui/scroll-area

Usage

import { ScrollArea, ScrollBar } from '@/components/ui/scroll-area';

Give the ScrollArea a fixed size via style. For horizontal scrolling, add <ScrollBar orientation="horizontal" /> as a child.

Horizontal

import * as stylex from '@stylexjs/stylex';

import { ScrollArea, ScrollBar } from '@/components/ui/scroll-area';
import { space, fontSize, fontWeight, stroke, container } from '@/lib/constants.stylex';
import { colors, font, radius } from '@/lib/tokens.stylex';

const artworks = [
  { title: 'Ocean Horizon', artist: 'Reyes' },
  { title: 'Desert Bloom', artist: 'Okafor' },
  { title: 'City Lights', artist: 'Petrova' },
  { title: 'Quiet Forest', artist: 'Lindgren' },
  { title: 'Northern Sky', artist: 'Haruki' },
  { title: 'Red Canyon', artist: 'Alvarez' },
];

export default function ScrollAreaHorizontal() {
  return (
    <ScrollArea style={styles.root}>
      <div {...stylex.props(styles.row)}>
        {artworks.map((art) => (
          <div key={art.title} {...stylex.props(styles.card)}>
            <div {...stylex.props(styles.thumb)} />
            <div {...stylex.props(styles.title)}>{art.title}</div>
            <div {...stylex.props(styles.artist)}>{art.artist}</div>
          </div>
        ))}
      </div>
      <ScrollBar orientation="horizontal" />
    </ScrollArea>
  );
}

const styles = stylex.create({
  root: {
    width: container.xl,
  },
  row: {
    display: 'flex',
    gap: space.s4,
    paddingBottom: space.s4,
    width: 'max-content',
  },
  card: {
    display: 'flex',
    flexDirection: 'column',
    fontFamily: font.sans,
    gap: space.s2,
    width: container.card,
  },
  thumb: {
    backgroundColor: colors.muted,
    borderColor: colors.border,
    borderRadius: radius.md,
    borderStyle: 'solid',
    borderWidth: stroke.border,
    height: space.s16,
    width: '100%',
  },
  title: {
    fontSize: fontSize.sm,
    fontWeight: fontWeight.medium,
  },
  artist: {
    color: colors.mutedForeground,
    fontSize: fontSize.xs,
  },
});

API reference

Built on Base UI Scroll Area. ScrollArea composes Root, Viewport, a vertical ScrollBar, and Corner; all props are forwarded to the Base UI Root — see the Base UI Scroll Area API reference. Both exports accept a style prop (StyleXStyles, merged last).

Was this page helpful?