From d3d7a25d07209b71fab12faba6dd3f27df4b35fd Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Tue, 6 May 2025 10:43:56 -0500 Subject: [PATCH 1/9] Stub out basic emoji presets --- app/assets/stylesheets/reactions.css | 33 ++++++++++++++++++- app/helpers/emoji_helper.rb | 12 +++++++ .../comments/reactions/_reactions.html.erb | 33 +++++++++++++++---- 3 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 app/helpers/emoji_helper.rb diff --git a/app/assets/stylesheets/reactions.css b/app/assets/stylesheets/reactions.css index 7414bbcd8..4ca08616f 100644 --- a/app/assets/stylesheets/reactions.css +++ b/app/assets/stylesheets/reactions.css @@ -4,6 +4,11 @@ --reaction-border-color: var(--color-ink-lighter); --row-gap: 0; + align-items: center; + display: flex; + flex-wrap: wrap; + gap: var(--inline-space-half); + inline-size: 100%; margin-block-start: calc(var(--block-space-half) / 2); margin-inline: calc(var(--column-gap) / -1); } @@ -48,7 +53,6 @@ --btn-border-color: var(--reaction-border-color); font-size: 0.74em; - margin-block-start: calc(var(--block-space-half) / 2); @media (any-hover: hover) { &:where(:not(:active):hover) { @@ -87,4 +91,31 @@ .reaction--deleting { animation: scale-fade-out 0.2s both; } + + .reaction__popup { + --panel-padding: 0.5ch; + --offset: calc(-1 * var(--panel-padding)); + + inset: var(--offset) auto auto var(--offset); + min-inline-size: auto; + transform: none; + } + + .reaction__quick-emojis { + display: grid; + grid-template-columns: repeat(3, 1fr); + + .btn { + --btn-icon-size: 1.5ch; + --btn-size: 1.75rem; + + position: relative; + + @media (any-hover: hover) { + &:hover { + z-index: 1; + } + } + } + } } diff --git a/app/helpers/emoji_helper.rb b/app/helpers/emoji_helper.rb new file mode 100644 index 000000000..fd959ce8a --- /dev/null +++ b/app/helpers/emoji_helper.rb @@ -0,0 +1,12 @@ +module EmojiHelper + REACTIONS = { + "👍" => "Thumbs up", + "👏" => "Clapping", + "👋" => "Waving hand", + "💪" => "Muscle", + "❤️" => "Red heart", + "😂" => "Face with tears of joy", + "🎉" => "Party popper", + "🔥" => "Fire" + } +end diff --git a/app/views/cards/comments/reactions/_reactions.html.erb b/app/views/cards/comments/reactions/_reactions.html.erb index 1998f31d3..22bc0c9fa 100644 --- a/app/views/cards/comments/reactions/_reactions.html.erb +++ b/app/views/cards/comments/reactions/_reactions.html.erb @@ -1,16 +1,37 @@ <%= turbo_frame_tag comment, :reacting do %> -
+
<%= render partial: "cards/comments/reactions/reaction", collection: comment.reactions.includes(:reacter).ordered %>
<%= turbo_frame_tag comment, :new_reaction do %> -
- <%= link_to new_card_comment_reaction_path(comment.card, comment), role: "button", - class: "btn reaction__action", action: "soft-keyboard#open" do %> - <%= icon_tag "reaction" %> Add a reaction - <% end %> +
+ + + +
+ <% EmojiHelper::REACTIONS.each do |character, title| %> + <%= form_with model: [ comment.card, comment, Reaction.new ], data: { turbo_frame: dom_id(comment, :new_reaction), action: "dialog#close"} do |form| %> + <%= hidden_field_tag "comment[content]", character %> + <%= form.button type: "submit", title: title, class: "reaction__quick-emoji-btn btn btn--circle borderless", data: { emoji: character } do %> + <%= character %> + <%= title %> + <% end %> + <% end %> + <% end %> + +
+ <%= link_to new_card_comment_reaction_path(comment.card, comment), role: "button", + class: "btn btn--circle borderless", action: "soft-keyboard#open" do %> + <%= icon_tag "reaction" %> Add a reaction + <% end %> +
+
+
<% end %> +
<% end %> From 9b49606246f740da47f960d1f3613052dd09b9ee Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Tue, 6 May 2025 16:37:01 -0500 Subject: [PATCH 2/9] Consistently align and size all elements --- app/assets/stylesheets/reactions.css | 56 ++++++++++++------- .../controllers/reaction_delete_controller.js | 3 +- .../comments/reactions/_reaction.html.erb | 9 ++- .../comments/reactions/_reactions.html.erb | 4 +- .../cards/comments/reactions/new.html.erb | 6 +- 5 files changed, 50 insertions(+), 28 deletions(-) diff --git a/app/assets/stylesheets/reactions.css b/app/assets/stylesheets/reactions.css index 4ca08616f..392b33f62 100644 --- a/app/assets/stylesheets/reactions.css +++ b/app/assets/stylesheets/reactions.css @@ -1,5 +1,6 @@ @layer components { .reactions { + --reaction-size: 2rem; --column-gap: 0.4ch; --reaction-border-color: var(--color-ink-lighter); --row-gap: 0; @@ -14,27 +15,32 @@ } .reaction { + --btn-size: 100%; + + align-items: center; + background-color: var(--color-canvas); + block-size: var(--reaction-size); border: 1px solid var(--reaction-border-color); border-radius: 4rem; - margin-block-start: calc(var(--block-space-half) / 2); + display: inline-flex; + gap: var(--column-gap); + max-inline-size: 100%; opacity: 1; padding: 0.1em 0.25em 0.1em 0.12em; - transition: opacity 100ms ease-in-out, box-shadow 150ms ease-in-out, transform 150ms ease-in-out; + postion: relative; + transition: opacity 100ms ease-in-out, transform 150ms ease-in-out; .btn { font-size: 0.6em; - - &:is(.reaction__delete) { - display: none; - - .expanded & { - display: flex; - } - } + inline-size: auto; } + } + + .reaction--deleteable { + cursor: pointer; @media (any-hover: hover) { - &:where(:not(:active):hover) { + &:not(:active):hover { --reaction-border-color: var(--color-ink-medium); box-shadow: 0 0 0 var(--hover-size) var(--hover-color); @@ -49,15 +55,18 @@ } } - .btn:is(.reaction__action) { - --btn-border-color: var(--reaction-border-color); + /* Make the avatar and delete buttons fit nicely within the reaction */ + .reaction__avatar, + .reaction__form-label, + .reaction form { + block-size: var(--btn-size); + } - font-size: 0.74em; + .reaction__delete { + display: none; - @media (any-hover: hover) { - &:where(:not(:active):hover) { - --reaction-border-color: var(--color-ink-medium); - } + .expanded & { + display: flex; } } @@ -92,7 +101,15 @@ animation: scale-fade-out 0.2s both; } + .reaction__action { + --btn-border-color: var(--reaction-border-color); + --btn-size: var(--reaction-size); + + font-size: 0.75em; + } + .reaction__popup { + --panel-border-radius: 1.2em; --panel-padding: 0.5ch; --offset: calc(-1 * var(--panel-padding)); @@ -107,7 +124,8 @@ .btn { --btn-icon-size: 1.5ch; - --btn-size: 1.75rem; + --btn-size: var(--reaction-size); + --btn-border-color: var(--color-canvas); position: relative; diff --git a/app/javascript/controllers/reaction_delete_controller.js b/app/javascript/controllers/reaction_delete_controller.js index 3c89ec00d..1e8144669 100644 --- a/app/javascript/controllers/reaction_delete_controller.js +++ b/app/javascript/controllers/reaction_delete_controller.js @@ -1,7 +1,7 @@ import { Controller } from "@hotwired/stimulus" export default class extends Controller { - static classes = [ "reveal", "perform" ] + static classes = [ "deleteable", "reveal", "perform" ] static targets = [ "button", "content" ] static values = { reacterId: Number } @@ -27,6 +27,7 @@ export default class extends Controller { this.contentTarget.role = "button" this.contentTarget.tabIndex = 0 this.contentTarget.ariaExpanded = false + this.element.classList.add(this.deleteableClass) } get #currentUserIsReacter() { diff --git a/app/views/cards/comments/reactions/_reaction.html.erb b/app/views/cards/comments/reactions/_reaction.html.erb index 2449ca997..8f5c121a6 100644 --- a/app/views/cards/comments/reactions/_reaction.html.erb +++ b/app/views/cards/comments/reactions/_reaction.html.erb @@ -1,9 +1,12 @@
+ data-controller="reaction-delete" + data-reaction-delete-perform-class="reaction--deleting" + data-reaction-delete-reveal-class="expanded" + data-reaction-delete-deleteable-class="reaction--deleteable" + data-reaction-delete-reacter-id-value="<%= reaction.reacter.id %>">
<%= avatar_tag reaction.reacter, aria: { label: "#{reaction.reacter.name} reacted #{reaction.content}" } %>
diff --git a/app/views/cards/comments/reactions/_reactions.html.erb b/app/views/cards/comments/reactions/_reactions.html.erb index 22bc0c9fa..2cb62739d 100644 --- a/app/views/cards/comments/reactions/_reactions.html.erb +++ b/app/views/cards/comments/reactions/_reactions.html.erb @@ -15,7 +15,7 @@ <% EmojiHelper::REACTIONS.each do |character, title| %> <%= form_with model: [ comment.card, comment, Reaction.new ], data: { turbo_frame: dom_id(comment, :new_reaction), action: "dialog#close"} do |form| %> <%= hidden_field_tag "comment[content]", character %> - <%= form.button type: "submit", title: title, class: "reaction__quick-emoji-btn btn btn--circle borderless", data: { emoji: character } do %> + <%= form.button type: "submit", title: title, class: "reaction__quick-emoji-btn btn btn--circle", data: { emoji: character } do %> <%= character %> <%= title %> <% end %> @@ -24,7 +24,7 @@
<%= link_to new_card_comment_reaction_path(comment.card, comment), role: "button", - class: "btn btn--circle borderless", action: "soft-keyboard#open" do %> + class: "btn btn--circle", action: "soft-keyboard#open" do %> <%= icon_tag "reaction" %> Add a reaction <% end %>
diff --git a/app/views/cards/comments/reactions/new.html.erb b/app/views/cards/comments/reactions/new.html.erb index e68a49179..ac15ca1df 100644 --- a/app/views/cards/comments/reactions/new.html.erb +++ b/app/views/cards/comments/reactions/new.html.erb @@ -1,6 +1,6 @@ <%= turbo_frame_tag @comment, :new_reaction do %> <%= form_with model: [ @comment.card, @comment, Reaction.new ], - class: "reaction reaction__form flex-inline postion--relative max-width align-center fill-white gap expanded", + class: "reaction reaction__form expanded", html: { aria: { label: "New reaction" } }, data: { controller: "form", turbo_frame: dom_id(@comment, :reacting), action: "keydown.esc->form#cancel" } do |form| %> - <%= form.button class: "btn btn--reversed", type: "submit" do %> + <%= form.button class: "btn btn--circle borderless btn--reversed", type: "submit" do %> <%= icon_tag "check" %> Submit <% end %> <%= link_to card_comment_reactions_path(@comment.card, @comment), role: "button", - data: { turbo_frame: dom_id(@comment, :reacting), form_target: "cancel" }, class: "btn btn--negative" do %> + data: { turbo_frame: dom_id(@comment, :reacting), form_target: "cancel" }, class: "btn btn--circle borderless btn--negative" do %> <%= icon_tag "minus" %> Cancel <% end %> <% end %> From 9034498f40e5592c8f2c3e632d8bd2138694e219 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Tue, 6 May 2025 16:49:14 -0500 Subject: [PATCH 3/9] Fix hidden field value --- app/views/cards/comments/reactions/_reactions.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/cards/comments/reactions/_reactions.html.erb b/app/views/cards/comments/reactions/_reactions.html.erb index 2cb62739d..e10205659 100644 --- a/app/views/cards/comments/reactions/_reactions.html.erb +++ b/app/views/cards/comments/reactions/_reactions.html.erb @@ -14,7 +14,7 @@
<% EmojiHelper::REACTIONS.each do |character, title| %> <%= form_with model: [ comment.card, comment, Reaction.new ], data: { turbo_frame: dom_id(comment, :new_reaction), action: "dialog#close"} do |form| %> - <%= hidden_field_tag "comment[content]", character %> + <%= hidden_field_tag "reaction[content]", character %> <%= form.button type: "submit", title: title, class: "reaction__quick-emoji-btn btn btn--circle", data: { emoji: character } do %> <%= character %> <%= title %> From 5b8f108316b0a8141a443599740343fc5a8283f2 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Tue, 6 May 2025 17:02:03 -0500 Subject: [PATCH 4/9] Gentler react animation --- app/assets/stylesheets/animation.css | 2 +- app/assets/stylesheets/reactions.css | 3 ++- app/views/cards/comments/reactions/new.html.erb | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/animation.css b/app/assets/stylesheets/animation.css index c99081856..d18419d47 100644 --- a/app/assets/stylesheets/animation.css +++ b/app/assets/stylesheets/animation.css @@ -10,7 +10,7 @@ /* Keyframes */ @keyframes react { - 0% { transform: scale(0.3); opacity: 0; } + 0% { transform: scale(0.85); opacity: 0; } 50% { transform: scale(1.15); opacity: 1; } 100% { transform: scale(1); } } diff --git a/app/assets/stylesheets/reactions.css b/app/assets/stylesheets/reactions.css index 392b33f62..68310d887 100644 --- a/app/assets/stylesheets/reactions.css +++ b/app/assets/stylesheets/reactions.css @@ -74,8 +74,9 @@ transition: none; &.expanded { - animation: react 0.2s both; + animation: react 300ms both; transform: translate3d(0, 0, 0); + transform-origin: left center; } .reaction__form-label:focus { diff --git a/app/views/cards/comments/reactions/new.html.erb b/app/views/cards/comments/reactions/new.html.erb index ac15ca1df..5f6f57b03 100644 --- a/app/views/cards/comments/reactions/new.html.erb +++ b/app/views/cards/comments/reactions/new.html.erb @@ -3,7 +3,7 @@ class: "reaction reaction__form expanded", html: { aria: { label: "New reaction" } }, data: { controller: "form", turbo_frame: dom_id(@comment, :reacting), action: "keydown.esc->form#cancel" } do |form| %> -
diff --git a/app/views/cards/comments/reactions/_quick_reaction.html.erb b/app/views/cards/comments/reactions/_quick_reaction.html.erb new file mode 100644 index 000000000..713cd91b7 --- /dev/null +++ b/app/views/cards/comments/reactions/_quick_reaction.html.erb @@ -0,0 +1,24 @@ +
+ <%= yield %> + + +
+ <% EmojiHelper::REACTIONS.each do |character, title| %> + <%= form_with model: [ comment.card, comment, Reaction.new ], data: { turbo_frame: dom_id(comment, :new_reaction), action: "dialog#close"} do |form| %> + <%= hidden_field_tag "reaction[content]", character %> + <%= form.button type: "submit", title: title, class: "reaction__quick-emoji-btn btn btn--circle", data: { emoji: character } do %> + <%= character %> + <%= title %> + <% end %> + <% end %> + <% end %> + +
+ <%= link_to new_card_comment_reaction_path(comment.card, comment), role: "button", + class: "btn btn--circle", action: "soft-keyboard#open" do %> + <%= icon_tag "reaction" %> Add a reaction + <% end %> +
+
+
+
diff --git a/app/views/cards/comments/reactions/_reactions.html.erb b/app/views/cards/comments/reactions/_reactions.html.erb index e10205659..ff179fa0c 100644 --- a/app/views/cards/comments/reactions/_reactions.html.erb +++ b/app/views/cards/comments/reactions/_reactions.html.erb @@ -5,33 +5,11 @@
<%= turbo_frame_tag comment, :new_reaction do %> -
+ <%= render "cards/comments/reactions/quick_reaction", comment: comment do %> - - -
- <% EmojiHelper::REACTIONS.each do |character, title| %> - <%= form_with model: [ comment.card, comment, Reaction.new ], data: { turbo_frame: dom_id(comment, :new_reaction), action: "dialog#close"} do |form| %> - <%= hidden_field_tag "reaction[content]", character %> - <%= form.button type: "submit", title: title, class: "reaction__quick-emoji-btn btn btn--circle", data: { emoji: character } do %> - <%= character %> - <%= title %> - <% end %> - <% end %> - <% end %> - -
- <%= link_to new_card_comment_reaction_path(comment.card, comment), role: "button", - class: "btn btn--circle", action: "soft-keyboard#open" do %> - <%= icon_tag "reaction" %> Add a reaction - <% end %> -
-
-
-
+ <% end %> <% end %> -
<% end %> From c69402a3005d3be3113049e11e0678cd4757fa13 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Wed, 7 May 2025 15:02:34 -0500 Subject: [PATCH 6/9] Get turboframes sorted out --- app/views/cards/comments/reactions/_quick_reaction.html.erb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/cards/comments/reactions/_quick_reaction.html.erb b/app/views/cards/comments/reactions/_quick_reaction.html.erb index 713cd91b7..b93931813 100644 --- a/app/views/cards/comments/reactions/_quick_reaction.html.erb +++ b/app/views/cards/comments/reactions/_quick_reaction.html.erb @@ -15,7 +15,8 @@
<%= link_to new_card_comment_reaction_path(comment.card, comment), role: "button", - class: "btn btn--circle", action: "soft-keyboard#open" do %> + class: "btn btn--circle", action: "soft-keyboard#open", + data: { turbo_frame: dom_id(comment, :new_reaction), action: "dialog#close" } do %> <%= icon_tag "reaction" %> Add a reaction <% end %>
From beda688d109cde1fa62b02ffbd0077b998404b18 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Wed, 7 May 2025 15:06:40 -0500 Subject: [PATCH 7/9] Show buttons depending on reaction presence --- app/assets/stylesheets/comments.css | 14 ++++++++++++++ app/assets/stylesheets/reactions.css | 4 ++++ app/views/cards/comments/_comment.html.erb | 4 ++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/comments.css b/app/assets/stylesheets/comments.css index d8c12c593..8f9b26172 100644 --- a/app/assets/stylesheets/comments.css +++ b/app/assets/stylesheets/comments.css @@ -81,6 +81,20 @@ } } + .comment__reaction { + opacity: 0.66; + + @media (any-hover: hover) { + .comment:not(:hover) & { + opacity: 0; + } + } + + .comment--mine & { + display: none; + } + } + .comment__event { max-inline-size: var(--comment-max); diff --git a/app/assets/stylesheets/reactions.css b/app/assets/stylesheets/reactions.css index cfc8f9b25..51f797456 100644 --- a/app/assets/stylesheets/reactions.css +++ b/app/assets/stylesheets/reactions.css @@ -108,6 +108,10 @@ --btn-size: var(--reaction-size); font-size: 0.75em; + + .reactions:not(:has(.reaction)) & { + display: none; + } } /* Quick reactions diff --git a/app/views/cards/comments/_comment.html.erb b/app/views/cards/comments/_comment.html.erb index b561ed0f9..9c41c81d6 100644 --- a/app/views/cards/comments/_comment.html.erb +++ b/app/views/cards/comments/_comment.html.erb @@ -22,8 +22,8 @@ <% end %> <%= render "cards/comments/reactions/quick_reaction", comment: comment do %> - <% end %>
From 8d1a4ec73a10ea4c0bc011f4ececadcb5a47e29a Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Wed, 7 May 2025 15:15:28 -0500 Subject: [PATCH 8/9] Close ghost space when no reactions exist --- app/assets/stylesheets/reactions.css | 10 ++++++++++ app/views/cards/comments/reactions/_reactions.html.erb | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/reactions.css b/app/assets/stylesheets/reactions.css index 51f797456..47f9471cb 100644 --- a/app/assets/stylesheets/reactions.css +++ b/app/assets/stylesheets/reactions.css @@ -13,6 +13,16 @@ margin-inline: calc(var(--column-gap) / -1); } + .reactions__list { + display: inline-flex; + flex-wrap: wrap; + gap: var(--column-gap); + + &:not(:has(.reaction)) { + display: none; + } + } + .reaction { --btn-size: 100%; diff --git a/app/views/cards/comments/reactions/_reactions.html.erb b/app/views/cards/comments/reactions/_reactions.html.erb index ff179fa0c..73a79812b 100644 --- a/app/views/cards/comments/reactions/_reactions.html.erb +++ b/app/views/cards/comments/reactions/_reactions.html.erb @@ -1,6 +1,6 @@ <%= turbo_frame_tag comment, :reacting do %>
-
+
<%= render partial: "cards/comments/reactions/reaction", collection: comment.reactions.includes(:reacter).ordered %>
From 0adc650132c8b7db1531adcd11d9ef19f258c304 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Wed, 7 May 2025 15:21:20 -0500 Subject: [PATCH 9/9] Correct icon sizes in new reaction form buttons --- app/assets/stylesheets/reactions.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/assets/stylesheets/reactions.css b/app/assets/stylesheets/reactions.css index 47f9471cb..e1ce33e77 100644 --- a/app/assets/stylesheets/reactions.css +++ b/app/assets/stylesheets/reactions.css @@ -1,5 +1,6 @@ @layer components { .reactions { + --btn-icon-size: 1.3em; --column-gap: 0.4ch; --reaction-border-color: var(--color-ink-lighter); --row-gap: 0; @@ -80,8 +81,6 @@ } .reaction__form { - --btn-icon-size: 1.3em; - transition: none; &.expanded {