For AI agents: the complete documentation index is available at https://ifhover.github.io/leaf-ui/v/0.6.0/en/llms.txt, the full documentation bundle is available at https://ifhover.github.io/leaf-ui/v/0.6.0/en/llms-full.txt, and this page is available as Markdown at https://ifhover.github.io/leaf-ui/v/0.6.0/en/components/scrollbar.md.
  • English
  • Scrollbar

    Browse long or wide content inside a region.

    Basic usage

    Scrollbars fade in when the pointer enters the region and fade out when it leaves, without taking up content space. Wheel, touch and keyboard scrolling retain native behavior.

    Project activity 1
    Project activity 2
    Project activity 3
    Project activity 4
    Project activity 5
    Project activity 6
    Project activity 7
    Project activity 8
    Project activity 9
    Project activity 10
    Project activity 11
    Project activity 12
    basic.tsx
    import { Scrollbar } from '@ifhover/leaf-ui';
    
    export function ScrollbarBasic() {
      return (
        <Scrollbar height={200} aria-label={'Project activity'}>
          {Array.from({ length: 12 }, (_, index) => (
            <div key={String(index)} style={{ padding: '12px 20px' }}>
              {'Project activity'} {index + 1}
            </div>
          ))}
        </Scrollbar>
      );
    }
    

    Horizontal and always visible

    orientation controls the scrolling axes. Use scrollbar="always" to keep bars visible, or hidden to hide them without disabling scrolling. Drag a thumb or click its track to move through the content.

    Project 1
    Project 2
    Project 3
    Project 4
    Project 5
    Project 6
    basic.tsx
    import { Scrollbar } from '@ifhover/leaf-ui';
    
    export function ScrollbarHorizontal() {
      return (
        <Scrollbar
          orientation="horizontal"
          scrollbar="always"
          aria-label={'Project board'}
        >
          <div style={{ display: 'flex', width: 'max-content', gap: 16, padding: '12px 12px 24px' }}>
            {Array.from({ length: 6 }, (_, index) => (
              <div
                key={String(index)}
                style={{
                  width: 180,
                  padding: 24,
                  borderRadius: 'var(--leaf-radius)',
                  background: 'var(--leaf-color-surface-muted)',
                }}
              >
                {'Project'} {index + 1}
              </div>
            ))}
          </div>
        </Scrollbar>
      );
    }
    

    Dynamic content and scroll control

    Thumbs update when content or container sizes change. The forwarded ref points to the scrolling viewport: call scrollTo, read scrollTop, or use it with BackTop. At a scroll boundary, or when content fits, the wheel continues scrolling the page.

    Item 1
    Item 2
    Item 3
    basic.tsx
    import { Button, Flex, Scrollbar } from '@ifhover/leaf-ui';
    
    import { useRef, useState } from 'react';
    
    export function ScrollbarDynamic() {
      const viewport = useRef<HTMLDivElement>(null);
      const [count, setCount] = useState(3);
      return (
        <Flex direction="column" gap="md">
          <Flex gap="sm" wrap>
            <Button variant="outline" onClick={() => setCount((previous) => previous + 3)}>
              {'Add items'}
            </Button>
            <Button
              variant="ghost"
              onClick={() => viewport.current?.scrollTo({ top: 0, behavior: 'smooth' })}
            >
              {'Back to top'}
            </Button>
          </Flex>
          <Scrollbar ref={viewport} maxHeight={200} aria-label={'Dynamic list'}>
            {Array.from({ length: count }, (_, index) => (
              <div key={String(index)} style={{ padding: '12px 20px' }}>
                {'Item'} {index + 1}
              </div>
            ))}
          </Scrollbar>
        </Flex>
      );
    }
    

    Scrollbar API

    import type { ScrollbarProps } from '@ifhover/leaf-ui';
    PropertyTypeDefaultDescription
    heightCSSProperties['height']—Viewport height.
    maxHeightCSSProperties['maxHeight']—Maximum height; unconstrained content determines its own height.
    orientation'vertical' | 'horizontal' | 'both''both'Scrolling axes.
    scrollbar'auto' | 'always' | 'hidden''auto'Scrollbar visibility.
    viewportClassNamestring—Class for the scrolling viewport.
    viewportStyleCSSProperties—Styles for the scrolling viewport.
    contentClassNamestring—Class for the content container.
    contentStyleCSSProperties—Styles for the content container.
    verticalOffsetnumber0Top inset for the vertical track, useful with sticky headers.

    style and className apply to the outer wrapper. id, role, tabIndex, region names and onScroll apply to the scrolling viewport. Provide aria-label or aria-labelledby to name it. Focus a thumb with Tab and use arrow keys, PageUp / PageDown or Home / End.

    ScrollArea uses the same scrollbar implementation and defaults to vertical scrolling. Existing usage remains supported.