Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

List Group Laravel Package

lara-zeus/list-group

Lara Zeus List Group is a lightweight Laravel package for rendering clean, customizable grouped lists and list cards. Ideal for menus, settings, dashboards, and search results, it provides simple Blade components with Tailwind-friendly styling and easy customization.

View on GitHub
Deep Wiki
Context7

Getting Started

Pin the Filament pairing before anything else. This package's major version tracks Filament's major version: lara-zeus/list-group ^3.x is the Filament 5 line (see release/3.0.0.md). Installing against the wrong Filament major is the single most likely way to lose an afternoon to Composer.

composer show filament/filament | head -n 20   # confirm 5.x
composer require "lara-zeus/list-group:^3.0"   # explicit constraint, not a bare require

Use an explicit constraint. A bare composer require writes a floating caret that can drift this package across a Filament major during an unrelated composer update — and because the package's constraint and yours both move, Composer will happily let it happen.

Read the source before trusting any example — including the ones below. The changelog is one line ("Support filament 5") and the README description is marketing prose, not an API reference. With 4 stars and 0 dependents there is no community shorthand to lean on. Ten minutes in vendor/lara-zeus/list-group/ pays for itself:

  1. src/ — find the concrete component classes and their actual fluent methods. Names like ->items(), ->icon(), ->badge(), ->url() are the expected shape for this family of packages but must be confirmed; the sketches here are indicative only.
  2. resources/views/ — see which attributes actually render, whether output is escaped, and whether the markup is semantic <ul>/<li>.
  3. composer.json — the authoritative Filament, PHP, and Laravel floors.

First use case: one read-only block on one detail page. The cheapest, most reversible integration is a "Related records" or "Metadata" group inside a resource's infolist — grouped rows with a label, optional description, icon, badge, and drill-down link. Read-only, one screen, two lines to delete if you dislike it.

use Zeus\ListGroup\Infolists\ListGroup;   // verify namespace in src/
use Zeus\ListGroup\Infolists\ListItem;

public static function infolist(Infolist $infolist): Infolist
{
    return $infolist->schema([
        // ... native Sections/Entries
        ListGroup::make()
            ->items([
                ListItem::make('Customer')
                    ->icon('heroicon-o-user')
                    ->description($record->customer->name)
                    ->url(route('filament.admin.resources.customers.view', $record->customer_id)),

                ListItem::make('Status')
                    ->icon('heroicon-o-check-badge')
                    ->badge($record->status)
                    ->badgeColor($record->status === 'active' ? 'success' : 'warning'),
            ]),
    ]);
}

Ship to one internal resource, confirm light and dark mode, then template it before rolling out anywhere else.

Implementation Patterns

Treat it as a presentational primitive, never a data source. The component renders whatever you hand it; it does not query. Resolve relationships, apply authorization (can('view', ...)), and format values in the resource or a small presenter class — then pass primitives into ListItem. This keeps N+1 queries visible in your own code and keeps the "we might rip this out" option cheap.

Group by intent, not by table columns. One ListGroup = one job: "Related records," "Metadata," "Quick navigation." Resist dumping every field on the page into a single list — that's precisely what native Section + TextEntry is for, and it's more flexible and better supported.

Link-list pattern (navigation). Rows become a mini-index of related resources. Icon per row for scannability, ->url() per row, badges only when state is genuinely meaningful. Classic fit: on an Order detail page, jump to Shipment, Invoice, and Customer. Keep labels short — the description carries the detail.

Badge-list pattern (status). Same layout, but the badge carries state. Centralize the model-status → Filament-color mapping in one helper and restrict yourself to success/warning/danger/gray. The component won't enforce a palette; without a rule, three resources will look like three different apps within a sprint.

final class StatusColor
{
    public static function for(string $status): string
    {
        return match ($status) {
            'active', 'paid'   => 'success',
            'pending'          => 'warning',
            'failed', 'void'   => 'danger',
            default            => 'gray',
        };
    }
}

Actions, not URLs, when the row does something. If a row triggers a side effect — open a modal, resend an email, retry a job — wire it to a Filament Action so it inherits panel authorization, confirmations, and activity logging. Check the source first: a URL-only component may have no action hook, in which case Section + Action rows is the correct fallback. Know which you have before you design the page.

Wrap it once, use it everywhere. If it appears in more than three resources or more than one panel, put a thin class in front of it:

final class MetadataList extends ListGroup
{
    public static function fromArray(array $rows): static
    {
        return static::make()->items(array_map(
            fn (array $row) => ListItem::make($row['label'])
                ->icon($row['icon'] ?? null)
                ->badge($row['badge'] ?? null)
                ->badgeColor($row['badge_color'] ?? null)
                ->url($row['url'] ?? null),
            $rows,
        ));
    }
}

With a single maintainer and zero Packagist dependents, this wrapper is the only cheap risk mitigation available: when the markup shifts under a silent patch, you edit one file instead of forty.

The description also claims Blade component and form support. Verify in src/ whether form mode exposes the same fluent API or a reduced one — don't assume parity between infolist and form rendering. In a form it's read-only display beside editable fields ("here's what this change affects"), which is a genuinely useful pattern if it holds up.

Standardize before you scale. Pick one link layout and one badge layout, document them, and treat ad-hoc variations as a code-review conversation. That's the difference between "a UI component we installed" and "our house style for detail pages."

Gotchas and Tips

Major version = Filament version, and it is the top trap. 3.x → Filament 5; earlier package lines → earlier Filament majors. No forward or backward compatibility across majors. When you upgrade Filament, upgrade this package in the same PR. If other lara-zeus/* packages lag on Filament 5, align all constraints before touching any of them — otherwise Composer demands a Filament version some Zeus package cannot accept, and you'll be resolving conflicts under deploy pressure.

The asset pipeline is the number-one real-world failure mode. Either the package ships precompiled CSS or your Tailwind build must scan its Blade views. If it's the latter, the package's view path needs to be in your content glob (Tailwind v3) or @source directive (Tailwind v4) — and you must re-verify that after every Filament/Tailwind major bump. The symptom is unmistakable: the layout collapses to an unstyled <ul>, rows stack with no spacing, badges lose their color pills, icons lose alignment. Compare the rendered class names against your compiled CSS before filing an issue upstream.

Escaping is your responsibility until proven otherwise. Filament entries often render raw HTML via HtmlString. Whether this component does is a one-line check in the Blade view. If user-controlled strings land in label/description/badge, sanitize on the way in. Don't assume it escapes, and don't assume it doesn't — both assumptions are testable in thirty seconds.

Handle empty and null states explicitly. What happens with zero items — an empty card leaving a visible gap in the infolist, or an exception? What does ->url(null) or ->badge(null) produce — <a href="">, or a blank pill? Read the view, then guard at the container:

ListGroup::make()
    ->items($items)
    ->visible(fn ($record) => $record->related->isNotEmpty());

Check link semantics. openUrlInNewTab() should imply target="_blank" and rel="noopener noreferrer". Internal Filament routes are low-risk; external URLs from this component deserve the two-line verification in the view.

Re-verify dark mode, RTL, and accessibility after every major bump. A major release is exactly when view markup drifts. Check contrast in both themes, confirm the markup uses semantic <ul>/<li> (screen readers rely on it), and spot-check RTL if the app is localized. If you need richer a11y semantics than the component provides, that's the cue to go in-house rather than patch around it.

Debugging sequence that saves time. (1) php artisan vendor:publish and check the service provider for a publish tag — if views are publishable, publish and inspect locally. (2) Drop {{ dump($item) }} into the published view to see exactly what gets handed to it. (3) If nothing renders at all, run php artisan filament:cache-components --clear — Filament's component caching bites everyone once, and it is not the package's fault.

Extension levers are limited. Your options are the fluent API, subclassing, overriding the published view, or forking. If you find yourself forking to add features, the requirement has outgrown the package: a Section with a couple of custom TextEntry views is roughly half a day and removes the dependency entirely.

Upgrade discipline as a habit. Pin exact versions in composer.lock, and keep a five-line note in the repo covering "why we chose this over hand-rolling" and "how to replace it in an hour." If the single maintainer stalls on a future Filament major, that note is what lets someone swap or fork without a scramble.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib