Advanced Choice
A beautifully styled, fully customizable set of radio group components for FilamentPHP.
Author:
CodeWithDennis
Documentation
- Requirements
- Installation
- Components
- Search, bulk actions, and disabling options
- Enum support
- Customization
- Contributing
- Security
- License
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.
The author
I build Laravel & FilamentPHP plugins, tinker with code, and game way too much when I’m off the clock.
From the same author
Advanced Components
This plugin extends existing FilamentPHP components with advanced features and enhanced functionality.
Author:
CodeWithDennis
Larament
Kickstart your project and save time with Larament! This time-saving starter kit includes a Laravel project with FilamentPHP already installed and set up, along with extra features.
Author:
CodeWithDennis
Simple Alert
A plugin for adding straightforward alerts to your Filament pages.
Author:
CodeWithDennis
Simple Map
This package provides a simple and user-friendly map display action component for your Filament application.
Author:
CodeWithDennis
Featured Plugins
A selection of plugins curated by the Filament team
Custom Dashboards
Let your users build and share their own dashboards with a drag-and-drop interface. Define your data sources in PHP and let them do the rest.
Filament
Spotlight Pro
Browse your Filament Panel with ease. Filament Spotlight Pro adds a Spotlight/Raycast like Command Palette to your Filament Panel.
Dennis Koch
Custom Fields
Eliminate custom field migrations forever. Let your users create and manage form fields directly in Filament admin panels with 20+ built-in field types, validation, and zero database changes.
Relaticle