yepsua/filament-rating-field
A Filament form field that adds interactive star ratings to your admin panels. Let users rate with a simple, customizable stars component for forms and tables.
1. Install and verify the version match. The package ships as a Filament form-field add-on, so the important compatibility axis is Filament v3 vs v4, not Laravel:
composer require yepsua/filament-rating-field
As of v0.7.0 the package dropped its illuminate/contracts requirement specifically so it can install against "any Laravel version". That removes the old transitive-constraint headache, but it is a permission to install, not a guarantee of testing — verify against your actual Laravel + Filament pair before rolling it across panels, and let Composer's lockfile be the record of what you validated.
If the package registers itself as a Filament plugin (check the README for a Plugin class), add it to your panel provider; if it is a pure form component, no registration is needed and you can use the field directly in any Resource form schema.
2. Where to look first.
README.md — the authoritative list of chainable options (stars, half-star support, colors/icons, size). Option names differ between rating packages, so read this before guessing.src/ — the field class extending Filament\Forms\Components\Field. Its setUp() tells you every default in one place.resources/views/ — the Blade view; this is where you learn whether the component is Alpine-driven or pure CSS, which matters for testing and theming.dist/ or resources/dist/ — compiled assets. If present, run php artisan filament:assets after install and after every upgrade.3. First use case: a review/feedback resource. Take the most boring CRUD you have — a Review model with rating (1–5) — and swap your Select::make('rating')->options([1..5]) for the rating field. Keep the DB column as unsignedTinyInteger (or decimal(2,1) if you use half-stars) and leave the rest of the resource untouched. That one swap is the whole integration; everything else is presentation.
Form field basics. The field is a standard Filament component, so all normal modifier chains still apply:
use Yepsua\FilamentRatingField\...\RatingField; // confirm namespace from README
RatingField::make('rating')
->label('Your score')
->required()
->minValue(1)
->maxValue(5) // or ->stars(5), depending on the package API
->columnSpanFull();
Reactive ratings. Because it is a Filament field, live() works — useful for showing a computed "sentiment" hint or gating a comment box:
RatingField::make('rating')
->live()
->afterStateUpdated(function (?string $state, Set $set) {
$set('is_negative', (int) $state <= 2);
}),
Read-only on view pages. Filament reuses the same schema for ViewRecord, so disable interaction there rather than building a separate infolist block:
->disabled(fn (string $operation) => $operation === 'view')
If the package exposes a display-only variant or a Blade partial, prefer that on ViewRecord — a disabled form control renders form chrome (labels, borders) you usually don't want in a read view.
Table display is not included. These packages are form-scoped. In table(), replicate the visual with a TextColumn using icons or a badge():
TextColumn::make('rating')
->formatStateUsing(fn ($state) => str_repeat('★', (int) $state) . str_repeat('☆', 5 - (int) $state))
->sortable(),
Keep the format string in one place (a model accessor or a small helper) so the form, table, and any API output stay consistent.
Shared field factory. If ratings appear in several resources, extract them:
// app/Filament/Fields/RatingInput.php
public static function make(string $name = 'rating'): RatingField
{
return RatingField::make($name)->required()->minValue(1)->maxValue(5);
}
This is also your migration seam if the package goes unmaintained — one file to rewrite.
Testing. The field is a Livewire-bound input, so standard Filament test helpers work:
livewire(CreateReview::class)
->fillForm(['rating' => 4])
->call('create')
->assertHasNoFormErrors();
$this->assertDatabaseHas('reviews', ['rating' => 4]);
Assert the stored value, not the rendered stars — DOM assertions on icon markup are brittle across minor releases.
Upgrade cadence. The v0.7.0 change is a Composer-constraint relaxation (dependency-only, no field API touched). Even so, treat every 0.x bump as potentially breaking: read the changelog, run the form tests, then re-run php artisan filament:assets. A dependency-only release is the cheapest possible upgrade, which makes it the easiest one to do properly and on time.
State type is a string until you cast it. Livewire form state arrives as a string/int mix. Without an explicit cast on the model ('rating' => 'integer' in $casts), you will eventually store "4" and break whereBetween comparisons or orderBy. Add the cast on day one.
null vs 0 is a real distinction. A nullable rating column plus a component that defaults to zero produces "unrated" records that look rated. Decide explicitly: either make the column non-nullable with a default and require the field, or keep it nullable and never let the component emit 0. Also verify whether the component emits null on deselect or leaves the previous value — that behavior is not uniform across rating packages.
Half-stars need a decimal column. If you enable fractional ratings, unsignedTinyInteger silently truncates. Switch to decimal(2,1) before you have data, and adjust validation to numeric|min:0.5|max:5.
"Supports any Laravel version" is not "tested on yours." Removing illuminate/contracts in v0.7.0 widens the install surface considerably — including Laravel majors the maintainer may never have run. Because Laravel/Filament pull that contract transitively anyway, the practical change is that Composer stops complaining, not that behaviour is verified. Keep your composer.lock committed and re-run the form tests after any Laravel or Filament bump, not just after this package's bumps.
Assets and upgrades. Filament caches compiled assets. After composer update on this package, run php artisan filament:assets and hard-refresh. A blank or unstyled star row is almost always a stale asset or a browser cache, not a code bug.
Custom Filament themes. If your panel uses a custom theme (->viteTheme()), the package's Tailwind classes may be purged from your build, because your tailwind.config.js content array doesn't scan vendor/. Add the package's resources/views path to content. This is the single most common "stars render as plain text" report.
Dark mode and theming. Colors are usually driven by CSS custom properties or Tailwind classes baked into the Blade view. If the stars are invisible on a dark panel, override via a published view (->view('filament.rating-field.custom')) rather than fighting the package CSS with !important — you keep the upgrade path open.
Debugging tip. When the value isn't persisting, dd($this->form->getState()) inside CreateRecord::handleRecordCreation() before the create() call. That isolates whether the problem is the component's state or your model/mutator layer.
Version pinning in practice. Stay on a ^0.7 style constraint with a committed lockfile rather than dev-main or a floating range. The package is pre-1.0: under semver, 0.x minors are the breaking-change slot, and v0.6 → v0.7 is exactly that class of release. A deliberate composer update yepsua/filament-rating-field followed by the test suite is the safe motion; a wildcard constraint is not.
Extension points to check, in order of preference: (1) published views via ->view(), (2) overriding the field class in your own app/Filament/Fields/ and extending the vendor one, (3) a Blade component override registered in a service provider. Avoid editing vendor/ — with a small star count, no third-party dependents, and a single-contributor release cadence, you are effectively the maintainer, so every local patch is one you own forever.
Risk note. Zero dependents and a small star count mean sparse community documentation and no third-party bug reports to lean on. v0.7.0's dependency relaxation widens your install options but doesn't add maintenance capacity behind the package — if anything, a looser constraint means fewer users hitting the same untested version matrix. Keep the fallback cheap: a plain Select with 1–5 options plus a TextColumn formatter reproduces 80% of the value in ten lines if you ever need to drop it.
How can I help you explore Laravel packages today?