Skip to main content

Data display

List code

Copy the implementation or inspect every file that belongs to this component unit.

resources/views/components/ui/list.blade.php

@props([
    'flush' => false,
])

@php
    /*
    | List group — a vertical stack of rows for simple collections (settings,
    | members, files) where a full table would be overkill. Place one or more
    | <x-ui.list.item> inside. By default it renders a bordered, rounded, divided
    | card; set `flush` to drop the outer border/rounding for embedding inside an
    | existing surface (e.g. a card body).
    |
    | Usage:
    |   <x-ui.list>
    |       <x-ui.list.item icon="user" title="Ada Lovelace" description="Owner" />
    |       <x-ui.list.item icon="user" title="Grace Hopper" description="Admin" />
    |   </x-ui.list>
    |
    |   <x-ui.card padding="none">
    |       <x-ui.list flush>...</x-ui.list>
    |   </x-ui.card>
    */
    $base = 'divide-y divide-gray-200 dark:divide-gray-800';

    $chrome = $flush
        ? ''
        : 'rounded-2xl border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900 overflow-hidden';
@endphp

<ul role="list" {{ $attributes->merge(['class' => trim($base.' '.$chrome)]) }}>
    {{ $slot }}
</ul>

resources/views/components/ui/list/item.blade.php

@props([
    'href' => null,
    'icon' => null,
    'iconWeight' => 'regular',
    'title' => null,
    'description' => null,
    'active' => false,
])

@php
    /*
    | A single row inside <x-ui.list>. Renders an <a> when `href` is set (with a
    | trailing chevron + hover state), otherwise a static row. Use the `title` /
    | `description` props for the common icon + text layout, the `leading` slot
    | for a custom left element (avatar, checkbox), the `actions` slot for
    | right-aligned controls, or the default slot for fully custom content.
    |
    | Usage:
    |   <x-ui.list.item icon="user" title="Ada Lovelace" description="Owner" />
    |   <x-ui.list.item href="/files/1" icon="file" title="Report.pdf" description="2.4 MB" />
    |   <x-ui.list.item title="Push notifications">
    |       <x-slot:actions><x-ui.toggle :checked="true" /></x-slot:actions>
    |   </x-ui.list.item>
    */
    $hasStructured = $title !== null || $description !== null || $icon !== null
        || isset($leading) || isset($actions);

    $state = $active
        ? 'bg-brand-50 dark:bg-brand-950/40'
        : ($href ? 'hover:bg-gray-50 dark:hover:bg-gray-800/60' : '');

    $classes = "relative flex items-center gap-3.5 px-4 py-3 text-sm transition {$state}";
@endphp

@if ($href)
    <li role="listitem">
        <a href="{{ $href }}"
           @if ($active) aria-current="true" @endif
           {{ $attributes->merge(['class' => "group {$classes} cursor-pointer"]) }}>
            @if ($hasStructured)
                @if (isset($leading))
                    <span class="shrink-0">{{ $leading }}</span>
                @elseif ($icon)
                    <span class="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-gray-100 dark:bg-gray-800 text-gray-500 dark:text-gray-400 {{ $active ? 'text-brand-600 dark:text-brand-400' : '' }}">
                        <x-ui.icon :name="$icon" :weight="$iconWeight" size="lg" />
                    </span>
                @endif

                <span class="min-w-0 flex-1">
                    @if ($title)<span class="block truncate font-medium text-gray-900 dark:text-white">{{ $title }}</span>@endif
                    @if ($description)<span class="block truncate text-gray-500 dark:text-gray-400">{{ $description }}</span>@endif
                    {{ $slot }}
                </span>
            @else
                <span class="min-w-0 flex-1">{{ $slot }}</span>
            @endif

            @if (isset($actions))
                <span class="shrink-0" @click.stop.prevent>{{ $actions }}</span>
            @endif

            <x-ui.icon name="caret-right" weight="bold" size="sm" class="shrink-0 text-gray-300 dark:text-gray-600 transition group-hover:text-gray-400 dark:group-hover:text-gray-500" />
        </a>
    </li>
@else
    <li role="listitem" {{ $attributes->merge(['class' => $classes]) }}>
        @if ($hasStructured)
            @if (isset($leading))
                <span class="shrink-0">{{ $leading }}</span>
            @elseif ($icon)
                <span class="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-gray-100 dark:bg-gray-800 text-gray-500 dark:text-gray-400 {{ $active ? 'text-brand-600 dark:text-brand-400' : '' }}">
                    <x-ui.icon :name="$icon" :weight="$iconWeight" size="lg" />
                </span>
            @endif

            <span class="min-w-0 flex-1">
                @if ($title)<span class="block truncate font-medium text-gray-900 dark:text-white">{{ $title }}</span>@endif
                @if ($description)<span class="block truncate text-gray-500 dark:text-gray-400">{{ $description }}</span>@endif
                {{ $slot }}
            </span>
        @else
            <span class="min-w-0 flex-1">{{ $slot }}</span>
        @endif

        @if (isset($actions))
            <span class="shrink-0">{{ $actions }}</span>
        @endif
    </li>
@endif