# Message scroller: Jumping to messages

> `useMessageScroller` drives the thread from outside it, and `useMessageScrollerVisibility` reports the current turn, so the outline highlights where you are.

Example: https://hextaui.com/docs/message-scroller/examples/jump
Component docs: https://hextaui.com/docs/message-scroller.md

## Add this example

```bash
npx shadcn@latest add https://hextaui.com/r/message-scroller-jump.json
```

This adds `components/examples/message-scroller/jump.tsx` with the Message scroller component and the HextaUI theme tokens.

## Source

```tsx title="components/examples/message-scroller/jump.tsx"
"use client"

import { Bubble, BubbleContent } from "@/components/ui/bubble"
import { Item, ItemContent, ItemGroup, ItemTitle } from "@/components/ui/item"
import { Message, MessageContent } from "@/components/ui/message"
import {
  MessageScroller,
  MessageScrollerContent,
  MessageScrollerItem,
  MessageScrollerProvider,
  MessageScrollerViewport,
  useMessageScroller,
  useMessageScrollerVisibility,
} from "@/components/ui/message-scroller"

const topics = [
  "Install the component",
  "Anchor each turn",
  "Follow streamed replies",
  "Load earlier messages",
  "Jump around the thread",
]

function Outline() {
  const { scrollToMessage } = useMessageScroller()
  const { currentAnchorId } = useMessageScrollerVisibility()

  return (
    <ItemGroup variant="grouped" className="w-44 shrink-0">
      {topics.map((topic, index) => (
        <Item
          key={topic}
          size="xs"
          render={<button type="button" />}
          aria-current={
            currentAnchorId === `topic-${index}` ? "true" : undefined
          }
          aria-pressed={currentAnchorId === `topic-${index}`}
          onClick={() =>
            scrollToMessage(`topic-${index}`, { behavior: "smooth" })
          }
        >
          <ItemContent>
            <ItemTitle>{topic}</ItemTitle>
          </ItemContent>
        </Item>
      ))}
    </ItemGroup>
  )
}

export function MessageScrollerJump() {
  return (
    <MessageScrollerProvider defaultScrollPosition="start">
      <div className="flex w-full max-w-xl items-start gap-4">
        <Outline />
        <div className="h-80 min-w-0 flex-1 overflow-hidden rounded-xl border">
          <MessageScroller>
            <MessageScrollerViewport aria-label="Guide">
              <MessageScrollerContent>
                {topics.map((topic, index) => [
                  <MessageScrollerItem
                    key={`q${index}`}
                    messageId={`topic-${index}`}
                    scrollAnchor
                  >
                    <Message align="end">
                      <MessageContent>
                        <Bubble variant="secondary">
                          <BubbleContent>
                            How do I {topic.toLowerCase()}?
                          </BubbleContent>
                        </Bubble>
                      </MessageContent>
                    </Message>
                  </MessageScrollerItem>,
                  <MessageScrollerItem
                    key={`a${index}`}
                    messageId={`a${index}`}
                  >
                    <Message>
                      <MessageContent>
                        <Bubble variant="ghost">
                          <BubbleContent>
                            Here is how to {topic.toLowerCase()}. The outline on
                            the side highlights this question while it is the
                            current turn, and clicking another one jumps
                            straight to it.
                          </BubbleContent>
                        </Bubble>
                      </MessageContent>
                    </Message>
                  </MessageScrollerItem>,
                ])}
              </MessageScrollerContent>
            </MessageScrollerViewport>
          </MessageScroller>
        </div>
      </div>
    </MessageScrollerProvider>
  )
}
```

## Props in this example

### MessageScrollerProvider

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `defaultScrollPosition` | `"start" \| "end" \| "last-anchor"` | `"end"` | Where the thread opens. |

### MessageScrollerViewport

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `aria-label` | `string` | – | Names the conversation region. |

### MessageScrollerItem

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `messageId` | `string` | – | Stable id for following, anchors and counts. |
| `scrollAnchor` | `boolean` | `false` | Scroll this item to the top when it arrives, with defaultScrollPosition="last-anchor". |

## More Message scroller examples

- [Group chat](https://hextaui.com/docs/message-scroller/examples/group-chat.md)
- [Keeping context](https://hextaui.com/docs/message-scroller/examples/peek.md)
- [Opening saved threads](https://hextaui.com/docs/message-scroller/examples/saved-thread.md)
- [Loading earlier messages](https://hextaui.com/docs/message-scroller/examples/history.md)
