Mixins / foldkit-mixins-ui

MessageScrollerSlots

const · packages/mixins-ui/src/messageScroller.ts:37

const MessageScrollerSlots: Slots.Contract<{
  readonly root: Slot.UnnamedSlot<
    Capability.Capability<
      'Container',
      readonly [
        Capability.Capability<
          'Interactive',
          readonly [Capability.Capability<'Base', readonly []>]
        >,
      ]
    >,
    readonly Slot.EventName[],
    readonly Slot.AttributeName[],
    readonly Slot.RequirementName[],
    boolean
  >
  readonly log: Slot.UnnamedSlot<
    Capability.Capability<
      'Container',
      readonly [
        Capability.Capability<
          'Interactive',
          readonly [Capability.Capability<'Base', readonly []>]
        >,
      ]
    >,
    readonly Slot.EventName[],
    readonly [Attr.AttrToken<'role'>, Attr.AttrToken<'aria-label'>],
    readonly Slot.RequirementName[],
    boolean
  >
  readonly jump: Slot.UnnamedSlot<
    Capability.Capability<
      'Interactive',
      readonly [Capability.Capability<'Base', readonly []>]
    >,
    readonly [Event.EventToken<'click'>],
    readonly [Attr.AttrToken<'aria-label'>],
    readonly Slot.RequirementName[],
    boolean
  >
  readonly count: Slot.UnnamedSlot<
    Capability.Capability<
      'Container',
      readonly [
        Capability.Capability<
          'Interactive',
          readonly [Capability.Capability<'Base', readonly []>]
        >,
      ]
    >,
    readonly Slot.EventName[],
    readonly Slot.AttributeName[],
    readonly Slot.RequirementName[],
    boolean
  >
}>

A message scroller: a conversation's messages in a ScrollArea that keeps the newest in view while the reader is at the bottom, stops following once they scroll up, and offers a button back to the latest that counts what arrived meanwhile. Older messages loaded above leave what the reader looks at where it was.

scroll position -> FollowEnd -> LeftEnd / ReachedEnd -> update -> following
new message -> Appended -> unseen (while not following)
jump button -> Jumped -> ScrollToEnd -> ReachedEnd

The scroll position is the browser's, and the Mount on the log reads it: while the log's end is in view it scrolls to the end whenever the log grows, a streamed answer included, and otherwise keeps the first message in view at the same place. The Model only mirrors what the Mount saw, for the button; the application tells it what arrived (Appended), since only the application knows a new message from an older one loaded above.

The log is the APG's role="log", named by label: a reader hears what is added to it, and a ChatMessage still streaming is aria-busy, so an answer is read once whole. The scroller fills the height of what holds it.