codewithdennis / filament-advanced-choice
Beautiful, customizable radio and checkbox form layouts for FilamentPHP.
Package info
github.com/CodeWithDennis/filament-advanced-choice
Language:Blade
pkg:composer/codewithdennis/filament-advanced-choice
Fund package maintenance!
Requires
- php: ^8.1
- filament/forms: ^4.0|^5.0
- spatie/laravel-package-tools: ^1.15.0
Requires (Dev)
- laravel/pint: ^1.0
- nunomaduro/collision: ^7.9||^8.0
- phpstan/phpstan: ^2.1
README
This package introduces eight new form fields for FilamentPHP. Four of them are based on Radio, and four are based on CheckboxList.
Requirements
- Filament 4/5
Installation
1. Install with Composer:
composer require codewithdennis/filament-advanced-choice
2. To make sure styling works, add this to your custom FilamentPHP theme:
@source '../../../../vendor/codewithdennis/filament-advanced-choice/resources/**/*.blade.php';
3. Run npm run build or npm run dev so the theme rebuilds.
Components
CheckboxList
Vertical list layout with descriptions for multiple selections.
CheckboxList::make('delivery_type') ->searchable() ->bulkToggleable() ->options([ 'standard' => 'Standard Delivery', 'express' => 'Express Delivery', 'overnight' => 'Overnight Delivery', 'same_day' => 'Same Day Delivery', 'economy' => 'Economy Delivery', 'premium' => 'Premium Delivery', 'international' => 'International Delivery', 'local' => 'Local Delivery', ]) ->descriptions([ 'standard' => 'Delivery within 5-7 business days', 'express' => 'Delivery within 2-3 business days', 'overnight' => 'Next day delivery available', 'same_day' => 'Delivery on the same day', 'economy' => 'Budget-friendly delivery option', 'premium' => 'Premium service with tracking', 'international' => 'Worldwide shipping available', 'local' => 'Same city delivery service', ]) ->extras([ 'standard' => '$5.00 flat rate', 'express' => '$10.00 flat rate', 'overnight' => '$20.00 flat rate', 'same_day' => '$25.00 flat rate', 'economy' => '$3.00 flat rate', 'premium' => '$15.00 flat rate', 'international' => '$50.00 flat rate', 'local' => '$8.00 flat rate', ]);
CheckboxCards
Card-based layout with descriptions and extras support for multiple selections.
CheckboxCards::make('delivery_type') ->searchable() ->bulkToggleable() ->options([ 'standard' => 'Standard Delivery', 'express' => 'Express Delivery', 'overnight' => 'Overnight Delivery', 'same_day' => 'Same Day Delivery', 'economy' => 'Economy Delivery', 'premium' => 'Premium Delivery', 'international' => 'International Delivery', 'local' => 'Local Delivery', ]) ->descriptions([ 'standard' => 'Delivery within 5-7 business days', 'express' => 'Delivery within 2-3 business days', 'overnight' => 'Next day delivery available', 'same_day' => 'Delivery on the same day', 'economy' => 'Budget-friendly delivery option', 'premium' => 'Premium service with tracking', 'international' => 'Worldwide shipping available', 'local' => 'Same city delivery service', ]) ->extras([ 'standard' => '$5.00 flat rate', 'express' => '$10.00 flat rate', 'overnight' => '$20.00 flat rate', 'same_day' => '$25.00 flat rate', 'economy' => '$3.00 flat rate', 'premium' => '$15.00 flat rate', 'international' => '$50.00 flat rate', 'local' => '$8.00 flat rate', ]);
CheckboxStackedCards
Stacked card layout with descriptions and extras support for multiple selections.
CheckboxStackedCards::make('delivery_type') ->options(DeliveryTypeEnum::class) ->searchable() ->bulkToggleable();
CheckboxTable
Responsive table layout with descriptions for multiple selections.
CheckboxTable::make('delivery_type') ->options(DeliveryTypeEnum::class) ->searchable() ->bulkToggleable();
RadioList
Vertical list layout with descriptions.
RadioList::make('delivery_type') ->options(DeliveryTypeEnum::class);
RadioTable
Responsive table layout with descriptions.
RadioTable::make('delivery_type') ->options(DeliveryTypeEnum::class);
RadioCards
Card-based layout with descriptions and extras support.
Smallest useful example with options(), descriptions(), and extras():
RadioCards::make('plan') ->options([ 'hobby' => 'Hobby', 'pro' => 'Pro', ]) ->descriptions([ 'hobby' => 'For side projects', 'pro' => 'For teams', ]) ->extras([ 'hobby' => '$9/mo', 'pro' => '$29/mo', ]);
Same layout with a backed enum:
RadioCards::make('delivery_type') ->options(DeliveryTypeEnum::class);
RadioStackedCards
Stacked card layout with descriptions and extras support.
RadioStackedCards::make('delivery_type') ->options(DeliveryTypeEnum::class);
Search, bulk actions, and disabling options
These come from FilamentPHP’s Radio and CheckboxList APIs (inherited unchanged).
Search:
CheckboxList::make('delivery_type') ->options(DeliveryTypeEnum::class) ->searchable() ->searchPrompt('Search delivery types...') ->noSearchResultsMessage('No delivery types found.');
Bulk select (checkbox-style fields only):
CheckboxList::make('delivery_type') ->options(DeliveryTypeEnum::class) ->bulkToggleable();
Disable one option:
CheckboxList::make('delivery_type') ->options(DeliveryTypeEnum::class) ->disableOptionWhen(fn (string $value): bool => $value === 'premium');
Enum support
Pass a backed enum class name to options() instead of an array. Implement:
Filament\Support\Contracts\HasLabel(main label)Filament\Support\Contracts\HasDescription(subtitle)CodeWithDennis\FilamentAdvancedChoice\Filament\Interfaces\HasExtra(extras()column)
Full enum example
<?php declare(strict_types=1); namespace App\Enums; use CodeWithDennis\FilamentAdvancedChoice\Filament\Interfaces\HasExtra; use Filament\Support\Contracts\HasDescription; use Filament\Support\Contracts\HasLabel; enum DeliveryTypeEnum: string implements HasDescription, HasExtra, HasLabel { case Standard = 'standard'; case Express = 'express'; case Overnight = 'overnight'; case SameDay = 'same_day'; case Economy = 'economy'; case Premium = 'premium'; case International = 'international'; case Local = 'local'; public function getLabel(): string { return match ($this) { self::Standard => __('Standard Delivery'), self::Express => __('Express Delivery'), self::Overnight => __('Overnight Delivery'), self::SameDay => __('Same Day Delivery'), self::Economy => __('Economy Delivery'), self::Premium => __('Premium Delivery'), self::International => __('International Delivery'), self::Local => __('Local Delivery'), }; } public function getDescription(): string { return match ($this) { self::Standard => __('Delivery within 5-7 business days'), self::Express => __('Delivery within 2-3 business days'), self::Overnight => __('Next day delivery available'), self::SameDay => __('Delivery on the same day'), self::Economy => __('Budget-friendly delivery option'), self::Premium => __('Premium service with tracking'), self::International => __('Worldwide shipping available'), self::Local => __('Same city delivery service'), }; } public function getExtra(): ?string { return match ($this) { self::Standard => __('$5.00 flat rate'), self::Express => __('$10.00 flat rate'), self::Overnight => __('$20.00 flat rate'), self::SameDay => __('$25.00 flat rate'), self::Economy => __('$3.00 flat rate'), self::Premium => __('$15.00 flat rate'), self::International => __('$50.00 flat rate'), self::Local => __('$8.00 flat rate'), }; } }
Example schema snippet
use App\Enums\DeliveryTypeEnum; use CodeWithDennis\FilamentAdvancedChoice\Filament\Forms\Components\RadioStackedCards; use Filament\Schemas\Schema; public static function configure(Schema $schema): Schema { return $schema ->columns(1) ->components([ RadioStackedCards::make('delivery_type') ->options(DeliveryTypeEnum::class), ]); }
If a case implements getColor(), some layouts tint that option (same idea as core FilamentPHP enums).
Either pass extras([...]) keyed by the enum value, or rely on getExtra() on each case.
Customization
Field color
use Filament\Support\Colors\Color; CheckboxCards::make('plan') ->options(Plan::class) ->color(Color::Rose);
Hide native inputs on cards
CheckboxCards::make('delivery_type') ->options(DeliveryTypeEnum::class) ->hiddenInputs();
Hidden input icon
By default, the hidden input icon for card components is heroicon-s-check-circle. You can override it:
RadioCards::make('delivery_type') ->options(DeliveryTypeEnum::class) ->hiddenInputIcon('heroicon-o-chevron-double-down') ->hiddenInputs();
visibleInputs() reverses hiddenInputs() (shows the native control again).
Contributing
Contributions and pull requests are always welcome and appreciated. If you want to discuss a bigger idea first, feel free to open a GitHub issue, but you do not have to. When you open a PR, running composer format first helps keep CI green.
Security
Report suspected vulnerabilities per .github/SECURITY.md. Do not post exploit details in a public issue.
License
This package is released under the MIT License. The complete terms are in LICENSE.







