tapp/filament-timezone-field
Filament Timezone Field adds a timezone select component to Filament forms. Supports Filament 3/4/5, localized timezone labels, UTC or GMT display, and filtering options by country codes or region for cleaner, relevant timezone lists.
Installation:
composer require tapp/filament-timezone-field:"^3.0"
Ensure your filament/filament package is compatible (3.x/4.x/5.x).
First Use Case: Add the field to a Filament resource form:
use Tapp\FilamentTimezoneField\Forms\Components\TimezoneSelect;
public static function form(Form $form): Form
{
return $form->schema([
TimezoneSelect::make('timezone'),
]);
}
This renders a dropdown with all timezones (default: UTC).
src/Forms/Components/TimezoneSelect.php for customization hooks.User-Specific Timezone Selection:
TimezoneSelect::make('timezone')
->getTimezoneFromBrowser() // Auto-populate from browser (non-overriding)
->required();
Regional Filtering:
use Tapp\FilamentTimezoneField\Enums\Region;
TimezoneSelect::make('timezone')
->byRegion([Region::Europe, Region::Asia])
->searchable();
Table Integration:
use Tapp\FilamentTimezoneField\Tables\Columns\TimezoneColumn;
TimezoneColumn::make('timezone')
->formattedOffsetAndTimezone()
->timezoneType('GMT');
Filtering Records:
use Tapp\FilamentTimezoneField\Tables\Filters\TimezoneSelectFilter;
TimezoneSelectFilter::make('timezone')
->byCountry('US')
->language('es');
->rules(['required'])).->language('fr')) for multilingual apps.byCountry()).getTimezoneFromBrowser() if users aren’t authenticated (fixed in v3.0.13).Browser Timezone Override:
getTimezoneFromBrowser() may fail on SPA/auth pages (fixed in v3.0.13). Test in production-like environments.Empty Values in Columns:
timezone was null. Always ensure your model has a default or nullable field.Symfony Intl Dependency:
symfony/intl is installed:
composer require symfony/intl
Region Enums:
Region enums (e.g., Region::Australia) may not cover all edge cases. Fall back to DateTimeZone constants if needed.Timezone Display Issues:
DateTimeZone instance. Use:
$timezone = new DateTimeZone($record->timezone);
dd($this->getState()) in a custom field extension.Performance:
getOptions() in a custom field class.Custom Field Logic:
Extend TimezoneSelect to add logic (e.g., dynamic country filtering):
class CustomTimezoneSelect extends TimezoneSelect
{
public function getOptions(): array
{
return parent::getOptions()->filter(fn ($option) => str_contains($option['label'], 'Europe'));
}
}
Table Column Formatting:
Override getFormattedValue() to customize display:
TimezoneColumn::make('timezone')
->modifyQueryUsing(fn (Builder $query) => $query->whereNotNull('timezone'))
->formatStateUsing(fn ($state) => "Custom: $state");
Filter Logic:
Extend TimezoneSelectFilter to add custom queries:
class CustomTimezoneFilter extends TimezoneSelectFilter
{
protected function setUp(): void
{
parent::setUp();
$this->query(fn (Builder $query) => $query->where('active', true));
}
}
Default Timezone: Set a default in your model’s $casts:
protected $casts = [
'timezone' => 'string',
];
Or use default() on the field:
TimezoneSelect::make('timezone')->default('America/New_York');
Testing: Mock browser timezone in tests:
$this->actingAs($user)->withHeaders(['X-Timezone' => 'Europe/London']);
Accessibility:
Combine with Filament’s ->label() and ->helperText() for clarity:
TimezoneSelect::make('timezone')
->label('User Timezone')
->helperText('Select the timezone for scheduling.');
How can I help you explore Laravel packages today?