asignua/filament-rating
A Filament plugin that adds a customizable star rating field and table column to your admin panel. Let users rate records directly in forms and tables, with configurable icons, colors, and half-star support.
This is a Filament 5 form/table/infolist package, so there is nothing to wire up beyond Composer and the panel's normal asset pipeline.
composer require <vendor>/filament-rating
php artisan filament:assets # if styles don't show up after install
php artisan optimize:clear
Look first at three things: the Rating form component (namespace will be something like Vendor\Rating\Forms\Components\Rating), the RatingTheme enum (the only place where "star vs. heart vs. other glyph" is decided), and the lang/ directory — ten locales ship, so any label you hardcode is a locale regression waiting to happen.
The first real use case is a review or feedback resource: a nullable rating column on the model, a Rating field on the create/edit form, a RatingColumn in the table, and a RatingEntry on the view page.
use Vendor\Rating\Forms\Components\Rating;
Rating::make('rating')
->stars(5)
->allowZero()
->color('warning')
->required();
Because the API mirrors mokhosh/filament-rating, an existing field definition usually ports by changing the use statement only — treat that as a migration convenience, not a guarantee, and diff the builder methods before deleting the old package.
Decide whole stars vs. half stars before you write the migration. halfStars() changes the value domain and the validation step, and that decision leaks into the column type.
// Whole stars
$table->unsignedTinyInteger('rating')->nullable();
// Half stars
$table->decimal('rating', 2, 1)->nullable();
Standardize the scale once. Most apps want the same star count, colour, theme, and icon set everywhere. A tiny helper keeps tables, entries, and forms from drifting apart:
final class RatingScale
{
public static function stars(): int { return 5; }
public static function field(string $name): Rating
{
return Rating::make($name)
->stars(self::stars())
->theme(RatingTheme::Stars)
->color('warning')
->tooltips([
1 => __('ratings.terrible'),
2 => __('ratings.poor'),
3 => __('ratings.ok'),
4 => __('ratings.good'),
5 => __('ratings.excellent'),
]);
}
}
Tooltips are the cheapest accessibility win here — they turn "3 of 5" into something a user can actually act on.
Read-only display is a different component, not a disabled field. Use RatingColumn in tables and RatingEntry in infolists; both render role="img" with a proper label, which is exactly what you want for screen readers skimming a list.
RatingColumn::make('rating')
->stars(5)
->halfStars()
->color('warning')
->sortable();
RatingEntry::make('rating')
->stars(5)
->showValue(); // renders "4.5" next to the glyphs
allowZero() and clearable() solve different problems. allowZero() makes zero a legitimate, selectable rating ("rated it zero stars"). clearable() lets the user return the field to null ("haven't rated yet"). If you use clearable(), the column must be nullable and your application code must handle null distinctly from 0 — a ?? 0 anywhere in reporting will silently merge the two.
Theming and icon overrides belong in one place. theme(RatingTheme::...) gives you a coherent glyph set; icon() / emptyIcon() are for branded cases only. Mixing a theme with per-field icon overrides produces inconsistent empty states across pages.
Sizes and colours should come from Filament enums/colour names, not hex. Dark mode follows the panel automatically — hardcoded colours break that immediately.
Testing. The field is a Livewire component backed by a slider role, so assert on state rather than on clicks:
livewire(CreateReview::class)
->fillForm(['rating' => 3.5])
->call('create')
->assertHasNoFormErrors();
$this->assertDatabaseHas('reviews', ['rating' => 3.5]);
Also assert the validation boundary you care about (e.g. 4.3 must fail when halfStars() is on).
halfStars() makes 4.3 invalid. If the model casts rating to integer, a valid 3.5 gets truncated on save and the form round-trip looks broken. Cast to float/decimal:1 and keep the DB precision in sync.null vs. 0 is the most common reporting bug with this package. Decide semantics in writing before shipping: nullable + clearable() means "unrated", allowZero() means "rated zero". Aggregates (avg) silently treat both as 0 in some SQL dialects — filter explicitly.role="slider" supporting arrows, Home/End, and Delete, but Delete only clears when clearable() is enabled. Verify focus ring visibility against your panel's theme, and verify the aria-valuetext ("3 of 5 stars") is actually localized in your non-English panels — if you override the translation keys, keep the "X of Y" shape or you'll degrade the announcement..fi-rating*, so custom CSS can target it without collisions. If you compile a custom Filament theme with Tailwind, add the package's views to your content globs, otherwise your overrides may be purged or (more likely) the package classes may be stripped.mokhosh/filament-rating: the shared surface (stars(), allowZero(), color(), size(), theme()) ports cleanly. The newer additions (halfStars(), clearable(), tooltips(), showValue(), icon()/emptyIcon()) are where the two packages diverge in behaviour, even if the method names match — smoke-test those specifically rather than assuming parity.aria-valuetext will fall back to English inside an otherwise localized panel.How can I help you explore Laravel packages today?