---
title: Live List
description: A list the server re-renders while it is being read, which keeps the reader's place when entries arrive above it and points to new entries out of sight.
visibility: guest
draft: false
---

# Live List

`<x-wirekit::live-list>` holds a list that changes while somebody reads it: an inbox that a broadcast refreshes, a queue that new orders join. An entry inserted above the rows in view would push them down, and the reader would lose the line they were on. The live list keeps the first row in view where it was, and when new entries land out of sight, a hint says so and brings them into view.

## Basic Usage

Put the list in the slot and mark each row with `data-wk-live-row`. A row the server marks `data-wk-live-fresh` is new or has moved.

:::preview{title="An inbox with a new conversation"}
<x-wirekit::live-list>
    <x-wirekit::stack gap="xs">
        <x-wirekit::card data-wk-live-row data-wk-live-fresh>
            <x-wirekit::card.body>
                <x-wirekit::text weight="medium">Refund for order 1042</x-wirekit::text>
                <x-wirekit::text size="sm" intent="muted">Arrived a moment ago</x-wirekit::text>
            </x-wirekit::card.body>
        </x-wirekit::card>
        <x-wirekit::card data-wk-live-row>
            <x-wirekit::card.body>
                <x-wirekit::text weight="medium">Invoice address change</x-wirekit::text>
                <x-wirekit::text size="sm" intent="muted">12 minutes ago</x-wirekit::text>
            </x-wirekit::card.body>
        </x-wirekit::card>
        <x-wirekit::card data-wk-live-row>
            <x-wirekit::card.body>
                <x-wirekit::text weight="medium">Delivery to a pick-up point</x-wirekit::text>
                <x-wirekit::text size="sm" intent="muted">1 hour ago</x-wirekit::text>
            </x-wirekit::card.body>
        </x-wirekit::card>
    </x-wirekit::stack>
</x-wirekit::live-list>
:::

## Live Renders

`live` says that a render answers a live event. Set it when the component re-renders because something arrived, and leave it off when the reader asked for a different list, a filter or the next page: only a live render keeps the reader's place, and a filter that moved the reader to the top would otherwise be undone.

```php
// 1. A Livewire component that re-renders its inbox when a conversation arrives.
use Livewire\Attributes\On;

public bool $live = false;

#[On('echo-private:inbox,ConversationArrived')]
public function arrived(): void
{
    $this->live = true;
}

public function updatedFilter(): void
{
    $this->live = false;
}
```

```blade
{{-- 2. Every row with its key, and the rows that arrived marked fresh. --}}
<x-wirekit::live-list :live="$live">
    @foreach ($conversations as $conversation)
        <a href="{{ route('conversations.show', $conversation) }}"
           wire:key="conversation-{{ $conversation->id }}"
           data-wk-live-row
           @if ($conversation->arrivedRecently()) data-wk-live-fresh @endif
        >{{ $conversation->subject }}</a>
    @endforeach
</x-wirekit::live-list>
```

The list keeps its place in the region it scrolls in: a panel of its own with `overflow-y: auto`, or the page. It does not depend on the browser's scroll anchoring, so it behaves the same in every engine.

## Fresh Rows Out of Sight

A fresh row the reader cannot see raises a hint at the top of the list, "New entries above", or at the bottom, "New entries below", and a screen reader hears the same sentence. The hint brings the first such row into view and puts the focus on its link, or on the row itself where it has no link. A fresh row counts until it has been in view once.

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `live` | bool | `false` | This render answers a live event: keep the reader's place and point to fresh rows out of sight. Leave it off for a filter or a page change. |
| `scope` | string\|null | `null` | Scoped personalization name |

| Attribute | On | Does |
| --- | --- | --- |
| `data-wk-live-row` | each row | A row the list keeps in place |
| `data-wk-live-fresh` | a row | The row is new or has moved, and counts toward a hint while it is out of sight |

## Accessibility

- The hints are buttons, named by their text, and they announce themselves in a `role="status"` region when they appear after a live render.
- A hint moves the focus to the row it brings into view, so the next Tab continues from there.
- Without `live`, the list leaves the scroll alone, so a list the reader filtered starts where the reader expects.

## Keyboard Interaction

| Key | Action |
| --- | --- |
| `Tab` | Reaches a hint while it shows, in reading order |
| `Enter` / `Space` | On a hint, brings the first fresh row in its direction into view and focuses it |
