Skip to content

Conversation

@flavorjones
Copy link
Member

@flavorjones flavorjones commented Jan 21, 2026

Note: this PR builds on #2416

Summary

Add "boost" reactions to cards, parallel to comment reactions. Users can now react to cards directly from the card
detail view, and boost counts appear on card previews in board columns.

Implementation

Polymorphic reactions: Migrated Reaction from belongs_to :comment to belongs_to :reactable, polymorphic: true. Migration backfills existing data and removes comment_id column.

Card reactions:

  • Card gets has_many :reactions, as: :reactable
  • New Cards::ReactionsController mirrors the existing Cards::Comments::ReactionsController
  • Routes: resources :reactions nested under cards

Consolidated views: Extracted shared reaction views to app/views/reactions/, eliminating duplication between
card and comment reactions. Added ReactionsHelper#reaction_path_prefix_for to handle nested route differences
with polymorphic paths.

UI:

  • Card detail footer shows reaction picker (absolute positioned when empty, flows inline when reactions exist)
  • Card preview shows boost count alongside comment count in .card__counts wrapper
  • Mobile: counts use absolute positioning to avoid conflicts with full-width meta grid

Screenshots

Perma shows the boost count:

image

Card detail before any boosts:

image

Card detail when adding a boost:

image

Card detail with boosts:

image image

ref: https://app.fizzy.do/5986089/cards/1280

@flavorjones
Copy link
Member Author

Ideally I'd like QA to kick this one around before we ship it.

@andyra
Copy link
Contributor

andyra commented Jan 22, 2026

Nice, @flavorjones! I'm going to try moving reactions around a bit, as I think they're kinda getting in the way of the footer. Not sure I'll be able to do much better, but I'll take a swing.

flavorjones and others added 17 commits January 23, 2026 13:22
Adds `has_many :reactions` to Card, matching the implementation in Comment.
This allows cards to be reacted to directly with emoji reactions.

The association:
- Orders reactions chronologically
- Uses polymorphic `:reactable` interface
- Deletes reactions when card is destroyed

Includes test coverage for the new association.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create Cards::ReactionsController with turbo stream responses
- Add card reactions views (reactions list, new form, menu partial)
- Position reaction button flush-right when no reactions exist
- Show reactions on bottom-left when present, with button inline
- Handle narrow viewports by flowing button below meta section
- Add controller tests for card reactions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Display reaction count alongside comment count on card tiles in board
columns. Introduces a .card__counts wrapper to group both counts with
proper positioning on all viewport sizes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Extract shared views to app/views/reactions/ using polymorphic routing.
Both card and comment reactions now render the same partials, with a
helper to compute the correct path prefix for nested routes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Override .card .popup { inline-size: 260px } for the reaction popup
so the emoji grid displays without horizontal scrollbar.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add .card__boosts alongside .card__comments in:
- Tray view (display: none)
- Cards with background images (opacity toggle on hover)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When a card has a background image, the footer contains both a reactions
button and a zoom button. Previously they would overlap because the
reactions button was absolutely positioned to the bottom-right.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes two issues:

1. Reactions were duplicated each time a card was assigned because the
   turbo stream replaced the meta div with the full perma/meta partial,
   which included reactions outside the replaced element.

2. Draft cards incorrectly showed the boost button because the meta
   partial was shared between published and draft containers.

Moving reactions to _container.html.erb (published cards only) fixes
both issues and keeps the meta partial focused on meta content.

Fixes https://app.fizzy.do/5986089/cards/3837
Fixes https://app.fizzy.do/5986089/cards/3835

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changed `card` to `@card` when rendering the stamp partial.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Include reactions and their reacters in the preloaded scope, matching
what we already do for comments.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Test that:
- Creating a card reaction touches the card's last_active_at
- Reactions are deleted when their parent comment is destroyed
- Reactions are deleted when their parent card is destroyed

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use size instead of count in boosts partial to avoid extra SQL query
  on already-loaded collection
- Add else clause to reaction_path_prefix_for to raise ArgumentError
  for unknown reactable types instead of silently returning nil

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@flavorjones flavorjones merged commit cb61b36 into main Jan 23, 2026
13 checks passed
@flavorjones flavorjones deleted the boost-card branch January 23, 2026 18:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants