A FilamentPHP v4 plugin for creating and managing interactive polls with Livewire-powered components.
composer require caresome/filament-pollphp artisan vendor:publish --tag="filament-poll-migrations"php artisan migrate
Register the plugin in your panel provider:
use Caresome\FilamentPoll\PollPlugin; public function panel(Panel $panel): Panel{ return $panel ->plugins([ PollPlugin::make(), ]);}
Display a poll on your frontend:
<x-caresome::filament-poll :poll-id="1" />
composer require caresome/filament-poll
php artisan vendor:publish --tag="filament-poll-migrations"php artisan migrate
Publish config file (for customizing table names):
php artisan vendor:publish --tag="filament-poll-config"
Publish views (for customization):
php artisan vendor:publish --tag="filament-poll-views"
Add the plugin to your Filament panel provider:
use Caresome\FilamentPoll\PollPlugin; public function panel(Panel $panel): Panel{ return $panel ->plugins([ PollPlugin::make(), ]);}
The plugin provides chainable methods to customize behavior:
PollPlugin::make() ->navigationIcon('heroicon-o-chart-bar') ->navigationSort(10)
| Method | Description | Default |
|---|---|---|
navigationIcon() |
Set navigation icon | heroicon-o-chart-bar |
navigationSort() |
Set navigation sort order | - |
PollPlugin::make() ->isActiveByDefault(true) ->allowGuestVotingByDefault(false) ->multipleChoiceByDefault(false) ->showResultsBeforeVotingByDefault(false) ->showVoteCountByDefault(true)
| Method | Description | Default |
|---|---|---|
isActiveByDefault() |
Polls are active by default | true |
allowGuestVotingByDefault() |
Allow guest voting | false |
multipleChoiceByDefault() |
Enable multiple choice | false |
showResultsBeforeVotingByDefault() |
Show results before voting | false |
showVoteCountByDefault() |
Display vote counts | true |
PollPlugin::make() ->maxPollOptions(20) ->maxOptionTextLength(255) ->pollingInterval('5s')
| Method | Description | Default |
|---|---|---|
maxPollOptions() |
Maximum poll options | 20 |
maxOptionTextLength() |
Max characters per option | 255 |
pollingInterval() |
Live update interval (null to disable) | 5s |
PollPlugin::make() ->authGuard('admin')
| Method | Description | Default |
|---|---|---|
authGuard() |
Set authentication guard | Auto-detect from panel |
useDefaultAuthGuard() |
Use Laravel's default guard | - |
How it works:
Example:
PollPlugin::make() ->authGuard('admin')
use Caresome\FilamentPoll\PollPlugin; public function panel(Panel $panel): Panel{ return $panel ->plugins([ PollPlugin::make() ->navigationIcon('heroicon-o-chart-bar') ->navigationSort(10) ->isActiveByDefault(true) ->allowGuestVotingByDefault(false) ->multipleChoiceByDefault(false) ->showResultsBeforeVotingByDefault(false) ->showVoteCountByDefault(true) ->maxPollOptions(20) ->maxOptionTextLength(255) ->pollingInterval('5s') ->authGuard('admin'), ]);}
Publish the config file and modify table names:
php artisan vendor:publish --tag="filament-poll-config"
return [ 'table_names' => [ 'polls' => 'custom_polls', 'poll_options' => 'custom_poll_options', 'poll_votes' => 'custom_poll_votes', ],];
Navigate to the Polls resource in your Filament admin panel:
By Poll ID:
<x-caresome::filament-poll :poll-id="1" />
By Poll Model:
<x-caresome::filament-poll :poll="$poll" />
@livewire('caresome::filament-poll', ['poll' => $poll])
In your controller:
use Caresome\FilamentPoll\Models\Poll; public function index(){ $poll = Poll::where('is_active', true)->first(); return view('welcome', compact('poll'));}
In your view:
@if($poll) <x-caresome::filament-poll :poll="$poll" />@endif
The package dispatches lifecycle events for custom integrations.
| Event | When Fired | Properties |
|---|---|---|
PollCreated |
New poll created | $event->poll |
PollVoted |
Vote is cast | $event->poll, $event->vote |
PollClosed |
Poll closes | $event->poll |
In EventServiceProvider:
use Caresome\FilamentPoll\Events\{PollCreated, PollVoted, PollClosed}; protected $listen = [ PollCreated::class => [ SendPollNotification::class, ], PollVoted::class => [ TrackAnalytics::class, ], PollClosed::class => [ SendResultsSummary::class, ],];
Using Event::listen():
use Illuminate\Support\Facades\Event;use Caresome\FilamentPoll\Events\PollVoted; Event::listen(PollVoted::class, function (PollVoted $event) { $poll = $event->poll; $vote = $event->vote; });
The package implements multiple security layers for vote tracking and prevention of abuse.
| User Type | Tracking Method | Duplicate Prevention |
|---|---|---|
| Authenticated | User ID | Database unique constraint |
| Guest | Session ID + IP Address | Database unique constraint |
Authenticated Users:
Guest Voting:
allowGuestVotingByDefault(false)The package includes built-in optimizations:
composer testcomposer test-coverage
The package provides factories for testing:
use Caresome\FilamentPoll\Models\{Poll, PollOption, PollVote}; $poll = Poll::factory()->active()->multipleChoice()->create(); $option = PollOption::factory()->forPoll($poll)->create(); $vote = PollVote::factory()->forOption($option)->authenticated(1)->create();$vote = PollVote::factory()->forOption($option)->guest()->create();
| Model | States |
|---|---|
| Poll | active(), inactive(), closed(), open(), neverCloses(), multipleChoice(), singleChoice(), allowGuestVoting(), requireAuth() |
| PollOption | forPoll($poll) |
| PollVote | forOption($option), authenticated($userId), guest() |
WCAG 2.1 AA compliant with full accessibility support:
| Feature | Implementation |
|---|---|
| ARIA Labels | All interactive elements labeled |
| Keyboard Navigation | Full keyboard support |
| Screen Readers | Comprehensive announcements |
| Focus Management | Visible indicators, logical tab order |
| Live Regions | Real-time updates announced |
| Semantic HTML | Proper use of fieldset, legend, etc. |
| Progress Bars | Accessible with ARIA attributes |
The MIT License (MIT). See LICENSE.md for details.