packstub/filament-rating
A Filament plugin for adding star ratings to your admin panels. Render interactive or read-only star fields in forms, tables, and infolists, with configurable star counts, colors, sizes, and half-star support for flexible review and feedback workflows.
Install the package and register the plugin (or use the components directly if you prefer not to enable the full plugin):
composer require mokhosh/filament-rating
php artisan filament:install --plugins # or add to your PanelProvider manually
The quickest first use case is enabling ratings on an existing Eloquent model. Add the rating column to your migration (an integer or nullable integer is fine), then expose a RatingInputColumn in a Filament resource table:
use Mokhosh\FilamentRating\Columns\RatingInputColumn;
RatingInputColumn::make('rating')
->clearable()
->max(5);
This gives you clickable stars in the table row that persist immediately, which is usually the highest-value thing you can ship in a first PR — moderators/staff can rate rows without opening an edit form.
Look at the resource's table definition first; the new RatingFilter and RatingDistribution are the next things to add once the column is working.
Inline rating in tables. RatingInputColumn is the workhorse. Wire it to a real integer column, use disabled() for read-only views (e.g. an "index" page for users who shouldn't edit), and clearable() when un-rating is a valid action. The "usual state update hooks" mean it behaves like other Filament state-updating columns — you can react to changes with afterStateUpdated() and normal lifecycle callbacks, so validation (e.g. reject ratings from unauthorized users) belongs there rather than in the component itself.
Human-readable labels. Use labels() whenever the score has semantic meaning:
RatingInputColumn::make('rating')
->labels([
1 => 'Poor',
2 => 'Fair',
3 => 'Good',
4 => 'Great',
5 => 'Excellent',
])
->showLabel();
Labels are announced by screen readers on hover and shown in displays via showLabel() — this is worth adopting by default for any user-facing rating, since bare stars are an accessibility problem.
Colour scales. colors() maps rating value → Filament colour name:
->colors([1 => 'danger', 2 => 'danger', 3 => 'warning', 4 => 'success', 5 => 'success'])
In the interactive field the colour follows the hovered value, so users get a colour preview before committing. Use Filament's named colours (danger, warning, success, primary, gray, etc.) rather than hex codes.
Filtering. Add a RatingFilter to the table's filters for "4 stars & up" style filtering, or call exact() to force a single-value match. The "& up" default is usually what you want for "highly rated" dashboards; exact() is right for reporting screens where a 3 is genuinely a 3.
Distribution summaries. RatingDistribution renders one bar per rating with counts, or percentages() for a proportion view. Drop it onto a dashboard widget or a stats panel, and it inherits the column's labels() and colors() — so configure the labels/colours once on a shared configuration and reuse.
labels() is keyed by value; if your max is 5 but you only supply labels for 1–3, the rest render bare. Keep max()/scale and label keys in sync, ideally via a shared constant or config value.'#ff0000' will not behave as you expect; map to the built-in palette.clearable() + disabled() are mutually exclusive in intent. A disabled field should not also be clearable — decide which state applies per context (view vs edit pages).labels(); without it, ratings are visual-only. If you ship a rating UI to end users, add labels.RatingDistribution pulls labels()/colors() from the associated column — if you have multiple rating columns with different configs, double-check which one a summarizer is bound to.afterStateUpdated() (recalculating aggregates, firing events) will execute on every click — keep it lean and consider queuing expensive follow-ups.RatingFilter is "N stars & up" (inclusive); use exact() deliberately when you need equality, and name filters clearly in the UI so users aren't surprised.->configureUsing() in a service provider to set project-wide defaults (e.g. default labels and colours) rather than repeating them in every resource.How can I help you explore Laravel packages today?