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
Prefer the singular field classes (RadioCard, RadioStackedCard, CheckboxCard, CheckboxStackedCard). The plural names (RadioCards, RadioStackedCards, CheckboxCards, CheckboxStackedCards) remain as deprecated aliases for backward compatibility.
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', ]);
CheckboxCard
Card-based layout with descriptions and extras support for multiple selections.
CheckboxCard::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', ]);
CheckboxStackedCard
Stacked card layout with descriptions and extras support for multiple selections.
CheckboxStackedCard::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);
RadioCard
Card-based layout with descriptions and extras support.
Smallest useful example with options(), descriptions(), and extras():
RadioCard::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:
RadioCard::make('delivery_type') ->options(DeliveryTypeEnum::class);
RadioStackedCard
Stacked card layout with descriptions and extras support.
RadioStackedCard::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\RadioStackedCard; use Filament\Schemas\Schema; public static function configure(Schema $schema): Schema { return $schema ->columns(1) ->components([ RadioStackedCard::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; CheckboxCard::make('plan') ->options(Plan::class) ->color(Color::Rose);
Hide native inputs on cards
CheckboxCard::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:
RadioCard::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.







