TallStackUI 4.0 is here! Seven new components and thousand of improvements. See what's new .

Powerful suite of Blade components for TALL Stack apps

List

List component.

general 1 server
production 12 servers
staging 3 servers

No items.

<x-list>
<x-list.items name="general" caption="1 server" />
<x-list.items name="production" caption="12 servers" />
<x-list.items name="staging" caption="3 servers" />
</x-list>
 
<!-- or -->
 
@php
// `$items` may be an array, a Collection, or any object that implements
// `Illuminate\Contracts\Support\Arrayable`. Each entry is read with
// `data_get`, so accessors and array keys both work. The only required
// key is `name` — every other key is optional and accessible inside
// `@interact('item_menu', $item)` as `$item['extra_key']`.
$items = [
['name' => 'general', 'caption' => '1 server'],
['name' => 'production', 'caption' => '12 servers'],
['name' => 'staging', 'caption' => '3 servers'],
];
@endphp
 
<x-list :items="$items" />
general 1 server
production 12 servers

No items.

Manage your tags here.
<x-list label="Tags" hint="Manage your tags here.">
<x-list.items name="general" caption="1 server" />
<x-list.items name="production" caption="12 servers" />
</x-list>

An option to perform client-side filtering of rows.

general 1 server
production 12 servers
staging 3 servers

No items.

<x-list label="Tags" searchable>
<x-list.items name="general" caption="1 server" />
<x-list.items name="production" caption="12 servers" />
<x-list.items name="staging" caption="3 servers" />
</x-list>
general 1 server
production 12 servers

No items.

<x-list label="Tags" searchable search-placeholder="Filter tags by name or caption">
<x-list.items name="general" caption="1 server" />
<x-list.items name="production" caption="12 servers" />
</x-list>
general 1 server
production 12 servers

No items.

Click an ellipsis to act on a tag.
<x-list label="Tags" hint="Click an ellipsis to act on a tag.">
<x-list.items name="general" caption="1 server">
<x-slot:menu>
<x-dropdown.items text="Edit" wire:click="edit('general')" />
<x-dropdown.items text="Delete" wire:click="delete('general')" />
</x-slot:menu>
</x-list.items>
<x-list.items name="production" caption="12 servers">
<x-slot:menu>
<x-dropdown.items text="Edit" wire:click="edit('production')" />
<x-dropdown.items text="Delete" wire:click="delete('production')" />
</x-slot:menu>
</x-list.items>
</x-list>
<x-list label="Tags" searchable>
@foreach ($tags as $tag)
<x-list.items :name="$tag->name" :caption="$tag->servers_count.' server(s)'">
<x-slot:menu>
<x-dropdown.items text="Edit" wire:click="edit({{ $tag->id }})" />
<x-dropdown.items text="Delete" wire:click="delete({{ $tag->id }})" />
</x-slot:menu>
</x-list.items>
@endforeach
</x-list>
general 1 server
production 12 servers
staging 3 servers

No items.

@php
$tags = [
['name' => 'general', 'caption' => '1 server'],
['name' => 'production', 'caption' => '12 servers'],
['name' => 'staging', 'caption' => '3 servers'],
];
@endphp
 
<x-list label="Tags" :items="$tags" searchable />
general 1 server
production 12 servers
staging 3 servers

No items.

@php
$tags = [
['id' => 1, 'name' => 'general', 'caption' => '1 server'],
['id' => 2, 'name' => 'production', 'caption' => '12 servers'],
['id' => 3, 'name' => 'staging', 'caption' => '3 servers'],
];
@endphp
 
<x-list label="Tags" :items="$tags" searchable>
@interact('item_menu', $item)
<x-dropdown.items text="Edit" wire:click="edit('{{ $item['id'] }}')" />
<x-dropdown.items text="Delete" wire:click="delete('{{ $item['id'] }}')" />
@endinteract
</x-list>
tag-1 1 server
tag-2 2 servers
tag-3 3 servers
tag-4 4 servers
tag-5 5 servers
tag-6 6 servers
tag-7 7 servers
tag-8 8 servers
tag-9 9 servers
tag-10 10 servers
tag-11 11 servers
tag-12 12 servers
tag-13 13 servers
tag-14 14 servers
tag-15 15 servers
tag-16 16 servers
tag-17 17 servers
tag-18 18 servers
tag-19 19 servers
tag-20 20 servers
tag-21 21 servers
tag-22 22 servers
tag-23 23 servers
tag-24 24 servers
tag-25 25 servers
tag-26 26 servers
tag-27 27 servers
tag-28 28 servers
tag-29 29 servers
tag-30 30 servers
tag-31 31 servers
tag-32 32 servers
tag-33 33 servers
tag-34 34 servers
tag-35 35 servers
tag-36 36 servers
tag-37 37 servers
tag-38 38 servers
tag-39 39 servers
tag-40 40 servers
tag-41 41 servers
tag-42 42 servers
tag-43 43 servers
tag-44 44 servers
tag-45 45 servers
tag-46 46 servers
tag-47 47 servers
tag-48 48 servers
tag-49 49 servers
tag-50 50 servers

No items.

<!--
The `height` attribute accepts one of `'40'`, `'60'`, `'80'` or `'96'`,
which translate to `max-h-{n}` plus a custom-styled scrollbar.
-->
<x-list label="Tags" :items="$tags" searchable height="60" />
general 1 server

No tags configured yet.

<!--
The empty slot is shown when the list has zero items AND when
the search filter matches none. The default falls back to the
`ts-ui::messages.list.empty` translation key.
-->
<x-list label="Tags" searchable>
<x-slot:empty>
<div class="flex flex-col items-center gap-2 py-4">
<p class="text-sm text-secondary-700 dark:text-dark-100">No tags configured yet.</p>
<x-button text="Create tag" wire:click="create" />
</div>
</x-slot:empty>
<x-list.items name="general" caption="1 server" />
</x-list>
signup-flow active
checkout-v2 rolling out
legacy-onboarding retired

No items.

<x-list label="Features">
<x-list.items name="signup-flow">
<x-badge color="green" round xs>active</x-badge>
</x-list.items>
<x-list.items name="checkout-v2">
<x-badge color="amber" round xs>rolling out</x-badge>
</x-list.items>
<x-list.items name="legacy-onboarding">
<x-badge color="red" round xs>retired</x-badge>
</x-list.items>
</x-list>

An option to compress the padding and display the component compacted.

general 1 server
production 12 servers
staging 3 servers

No items.

general 1 server
production 12 servers
staging 3 servers

No items.

<x-list label="Default" :items="$tags" searchable />
 
<x-list label="Compact" :items="$tags" searchable compact />

An option to renders rows on the client.

No items.

<!-- First slice of 20, the default -->
<x-list label="Tags" :items="$tags" searchable height="60" lazy />
 
<!-- First slice of 4 -->
<x-list label="Tags" :items="$tags" searchable height="60" lazy="4" />

The row markup is still the same component, so every soft customization of list.items reaches the lazy rows unchanged. Search still sees the whole dataset: the filter runs over the JSON array, not over the rendered rows.

height is required, and the interact slots are refused

A scroll container is required for the sentinel to intersect. The server resolves the @interact('item_caption') , @interact('item_action') , and @interact('item_menu') interactions during row rendering. Without a server render for each row, these interactions cannot be resolved, so the combination throws.

An option to renders controls on the right of the row.

general 1 server
production 12 servers

No items.

<x-list label="Environments">
<x-list.items name="general" caption="1 server">
<x-slot:action>
<x-button sm wire:click="deploy('general')">Deploy</x-button>
</x-slot:action>
<x-slot:menu>
<x-dropdown.items text="Edit" wire:click="edit('general')" />
<x-dropdown.items text="Delete" wire:click="delete('general')" />
</x-slot:menu>
</x-list.items>
<x-list.items name="production" caption="12 servers">
<x-slot:action>
<x-button sm color="red" wire:click="deploy('production')">Deploy</x-button>
</x-slot:action>
</x-list.items>
</x-list>

An option to display a lazy loading skeleton indicator.

<!-- 4 items, the default -->
<x-list skeleton />
 
<!-- The label, the search bar and the item count are derived from the props -->
<x-list skeleton="6" searchable label="Tags" />
  • x-list.items is an internal child component, it expects the parent x-list Alpine scope to be present. Using it standalone will fail with Alpine errors. Always wrap inside x-list .
  • name is required on every row (slot or data-driven). An empty or missing name throws an InvalidArgumentException at render time.
  • height is restricted to the tokens 40 , 60 , 80 and 96 , anything else throws.
  • The per-row menu is rendered through an internal x-floating at z-40 so it sits below Dialog/Modal/Slide/Toast overlays at z-50 . Customize the panel via the menu.floating block on x-list.items , not via floating's own customization.

Code highlighting provided by Torchlight