

<Demo name="message-scroller/demos/message-scroller" />

## Installation [#installation]

<CodeBlockTabs defaultValue="npm">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="npm">
      npm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="pnpm">
      pnpm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="yarn">
      yarn
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="bun">
      bun
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="npm">
    ```bash
    npx shadcn@latest add @dotui/message-scroller
    ```
  </CodeBlockTab>

  <CodeBlockTab value="pnpm">
    ```bash
    pnpm dlx shadcn@latest add @dotui/message-scroller
    ```
  </CodeBlockTab>

  <CodeBlockTab value="yarn">
    ```bash
    yarn dlx shadcn@latest add @dotui/message-scroller
    ```
  </CodeBlockTab>

  <CodeBlockTab value="bun">
    ```bash
    bun x shadcn@latest add @dotui/message-scroller
    ```
  </CodeBlockTab>
</CodeBlockTabs>

## Usage [#usage]

```tsx
import {
  MessageScroller,
  MessageScrollerButton,
  MessageScrollerContent,
  MessageScrollerItem,
  MessageScrollerProvider,
  MessageScrollerViewport,
} from "@/ui/message-scroller"
```

```tsx
<MessageScrollerProvider>
  <MessageScroller>
    <MessageScrollerViewport>
      <MessageScrollerContent>
        {messages.map((message) => (
          <MessageScrollerItem key={message.id}>
            {/* message */}
          </MessageScrollerItem>
        ))}
      </MessageScrollerContent>
    </MessageScrollerViewport>
    <MessageScrollerButton />
  </MessageScroller>
</MessageScrollerProvider>
```

## Anatomy [#anatomy]

`MessageScrollerProvider` holds the scroll state — autoscroll follows new
content while the reader sits at the bottom edge and lets go the moment they
scroll away. `MessageScrollerViewport` is the scrollable area,
`MessageScrollerContent` lays the messages out, and each
`MessageScrollerItem` renders lazily as it nears the viewport, so long
conversations stay cheap. `MessageScrollerButton` appears once the reader
leaves the edge and scrolls them back to the newest message.

The `useMessageScroller`, `useMessageScrollerScrollable` and
`useMessageScrollerVisibility` hooks expose imperative scrolling and scroll
state to anything inside the provider.

## Examples [#examples]

<Examples className="md:grid-cols-2">
  <Example name="message-scroller/demos/basic" title="Basic" />
</Examples>

## API Reference [#api-reference]

### MessageScrollerProvider [#messagescrollerprovider]

<Reference name="message-scroller-provider" />

### MessageScroller [#messagescroller]

<Reference name="message-scroller" />

### MessageScrollerViewport [#messagescrollerviewport]

<Reference name="message-scroller-viewport" />

### MessageScrollerContent [#messagescrollercontent]

<Reference name="message-scroller-content" />

### MessageScrollerItem [#messagescrolleritem]

<Reference name="message-scroller-item" />

### MessageScrollerButton [#messagescrollerbutton]

<Reference name="message-scroller-button" />
