Skip to content

Reactions

Reactions are a fixed set of six emotions — Like, Love, Laugh, Wow, Sad, Angry — that any model can receive, and any model can give. Both sides of the relationship are polymorphic, which is what makes it possible for both users and companies to react to something.

The reaction picker

The six reactions

app/Models/Reaction.php defines six constants: REACTION_LIKE, REACTION_LOVE, REACTION_LAUGH, REACTION_WOW, REACTION_SAD, REACTION_ANGRY (ids 1–6). This is a closed set by design — reactions are rows seeded once (Database\Preparers\ReactionPreparer) rather than something users create. If you need a different set of emotions, edit the preparer rather than allowing arbitrary reaction creation.

Doubly polymorphic

Most polymorphic features in Reshape are polymorphic on one side (the -able side). Reactions are polymorphic on both sides: the thing being reacted to (reactable), and the thing doing the reacting (responder):

Trait Methods (Reactable — the receiving side)

php
// Every reaction on this model, with the responder recorded on the pivot...
$reactable->reactions() : Illuminate\Database\Eloquent\Relations\MorphToMany

// Whether $responder (defaults to the authenticated user) has reacted at all...
$reactable->reacted(?Model $responder = null) : bool

Trait Methods (Reacts — the responding side)

php
// React to a reactable as this responder — the same reaction again removes it...
$user->reactTo(ReactableInterface $reactable, Reaction $reaction) : ?App\Models\Reaction

// Whether this responder has reacted to a given reactable...
$user->hasReaction(ReactableInterface $reactable) : bool

Comment and Announcement implement ReactableInterface; User uses Reacts to be able to react. Nothing stops you from making Company a responder too — responderMorphClass() works with any model, not just User.

Toggle semantics

Calling reactTo() twice with the same reaction removes it — there's no separate "unreact" call. Switching from one reaction to another replaces the pivot row rather than stacking two reactions from the same responder.

Getting a summary

php
// Reactions grouped by type, with a count and whether $responder reacted...
$reactable->getReactionsSummary(?Model $responder = null) : Illuminate\Support\Collection

Returns something like:

json
[
  { "id": 1, "name": "like", "count": 12, "reacted": true },
  { "id": 2, "name": "love", "count": 3, "reacted": false }
]

which is exactly the shape the frontend's reaction chips render.

In the frontend

composables/use-reactions.ts wraps the toggle call; components/reactions/* (reaction-chip, reaction-list, reaction-picker) render the fixed six-emoji set.