# messageFollow

> Bridges a message scroller's viewport to `ScrollFollowModel`, reporting live scroll position, viewport size, and turn visibility into the model and fulfilling its scroll intents by writing scroll position directly, so every visible part of the widget renders purely from state the model owns.

```ts
import { messageFollow } from "@sdxc/ui/mixins";
```

Adds live-scroll coordination to a message scroller's viewport: reports
scroll position, size, and turn visibility into `model`, mirrors its
pinned and reachable-edge state back onto the viewport, and fulfills its scroll requests.

## Signature

```ts
messageFollow(model: ScrollFollowModel): MixinDescriptor<HTMLElement>
```

## Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| `model` | `ScrollFollowModel` | Scroll-follow state shared with the rest of the widget. |

## Examples

```tsx
let model = new ScrollFollowModel();
<div class="viewport" mix={messageFollow(model)}>
  <div class="content">
    {turns.map((turn) => (
      <div key={turn.id} data-scroll-anchor={turn.id}>{turn.body}</div>
    ))}
  </div>
  <button data-scroll-jump aria-label={jumpToLatestLabel}>↓</button>
</div>
```

## Used with it

The events, constants and types its module publishes, each imported from `@sdxc/ui/mixins` too.

### MESSAGE_SCROLLER_ANCHOR_ATTRIBUTE

Attribute every conversational turn exposes itself on, its value the
turn's stable id; `messageFollow()` reads it to find the anchor turn and
to drive its lazily attached `IntersectionObserver`'s visibility tracking.

#### Signature

```ts
const MESSAGE_SCROLLER_ANCHOR_ATTRIBUTE = "data-scroll-anchor"
```

### MESSAGE_SCROLLER_JUMP_ATTRIBUTE

Attribute the viewport's jump-to-latest control carries. `messageFollow()`
finds it beneath the viewport to wire its click and to mirror
`ScrollFollowModel.pinned` onto its visibility and tab-order reachability.

#### Signature

```ts
const MESSAGE_SCROLLER_JUMP_ATTRIBUTE = "data-scroll-jump"
```

### MESSAGE_SCROLLER_AUTOSCROLLING_ATTRIBUTE

Attribute `messageFollow()` mirrors onto the viewport whenever
`ScrollFollowModel.pinned` is `true` — present while auto-follow is
engaged, absent once the reader has scrolled away from the live edge.

#### Signature

```ts
const MESSAGE_SCROLLER_AUTOSCROLLING_ATTRIBUTE = "data-autoscrolling"
```

### MESSAGE_SCROLLER_SCROLLABLE_ATTRIBUTE

Attribute `messageFollow()` mirrors onto the viewport: a space-separated
token list of edges still reachable (`"start"`, `"end"`, or `"start end"`),
readable via `[data-scrollable~="end"]`; removed once neither edge is reachable.

#### Signature

```ts
const MESSAGE_SCROLLER_SCROLLABLE_ATTRIBUTE = "data-scrollable"
```
