Merge branch 'main' into comments-refactoring

* main:
  Show more of the summary before truncating
  Improve event summaries
  Add this for debugging empty event cards
  Some actions shouldn't be available to closed cards
  Nicer spacing when the large button isn't present
  Update `card-color` in a couple more places
  Don't show the engagement toggle on closed cards
  Show more of the summary before truncating
  Improve event summaries
  Remove shadows from notifications you can't see
  Add this for debugging empty event cards
  Some actions shouldn't be available to closed cards
  Nicer spacing when the large button isn't present
  Update `card-color` in a couple more places
  Don't show the engagement toggle on closed cards
  Style drafted cards
  Considering needs to include drafted cards or you'll never be able to see them
  This item makes no sense until it's saved
  Tighten engagement switch design, only display it for published cards
This commit is contained in:
David Heinemeier Hansson
2025-04-12 09:56:28 +02:00
15 changed files with 63 additions and 32 deletions
+6 -2
View File
@@ -201,15 +201,19 @@
}
:first-of-type .btn {
border-top-left-radius: 2em;
border-bottom-left-radius: 2em;
border-inline-end: 0;
border-top-left-radius: 2em;
flex: 1 0 50%;
padding-inline-end: 0.8em;
}
:last-of-type .btn {
border-top-right-radius: 2em;
border-bottom-right-radius: 2em;
border-inline-start: 0;
border-top-right-radius: 2em;
flex: 1 0 50%;
padding-inline-start: 0.8em;
}
span {
+9 -1
View File
@@ -50,6 +50,13 @@
.card__tags {
font-size: var(--text-small);
}
&:is(.card--drafted) {
--card-color: var(--color-subtle-dark) !important;
border-color: var(--card-color) !important;
border-style: dashed !important;
}
}
}
@@ -153,7 +160,8 @@
&.card__actions-container--top {
margin: calc(var(--block-space) * 1) auto calc(var(--block-space) * -0.66);
min-inline-size: 30ch;
min-inline-size: 28ch;
padding: 0;
#header:has(&) {
position: relative;
+2
View File
@@ -118,6 +118,8 @@
}
.event__title {
--lines: 4;
font-size: 1.1em;
line-height: 1.2;
}
+4
View File
@@ -41,6 +41,10 @@
&:nth-child(5) { --position: 5; }
&:nth-child(6) { --position: 6; }
&:nth-child(n+7) .notification__content {
box-shadow: none !important;
}
.tray[open] & {
--offset: calc((100% + var(--block-space-half)) * (var(--position) * -1));
--scale: 1;
+4 -4
View File
@@ -71,7 +71,7 @@ module EventsHelper
"#{ event.creator == Current.user ? "You" : event.creator.name } assigned #{ event.assignees.pluck(:name).to_sentence } to <span style='color: var(--card-color)'>#{ card_title(event.card) }</span>".html_safe
end
when "unassigned"
"#{ event.creator == Current.user ? "You" : event.creator.name } unassigned #{ event.assignees.pluck(:name).to_sentence } from <span style='color: var(--card-color)'>#{ card_title(event.card) }</span>".html_safe
"#{ event.creator == Current.user ? "You" : event.creator.name } unassigned #{ event.assignees.include?(Current.user) ? "yourself" : event.assignees.pluck(:name).to_sentence } from <span style='color: var(--card-color)'>#{ card_title(event.card) }</span>".html_safe
when "boosted"
"#{ event.creator == Current.user ? "You" : event.creator.name } boosted <span style='color: var(--card-color)'>#{ card_title(event.card) }</span>".html_safe
when "commented"
@@ -81,9 +81,9 @@ module EventsHelper
when "closed"
"#{ event.creator == Current.user ? "You" : event.creator.name } closed <span style='color: var(--card-color)'>#{ card_title(event.card) }</span>".html_safe
when "staged"
"#{event.creator == Current.user ? "You" : event.creator.name} changed the stage to #{event.stage_name} on <span style='color: var(--card-color)'>#{ card_title(event.card) }</span>".html_safe
"#{event.creator == Current.user ? "You" : event.creator.name} moved <span style='color: var(--card-color)'>#{ card_title(event.card) }</span> to the #{event.stage_name} stage".html_safe
when "unstaged"
"#{event.creator == Current.user ? "You" : event.creator.name} removed <span style='color: var(--card-color)'>#{ card_title(event.card) }</span> from the #{event.stage_name} stage".html_safe
"#{event.creator == Current.user ? "You" : event.creator.name} moved <span style='color: var(--card-color)'>#{ card_title(event.card) }</span> out ofthe #{event.stage_name} stage".html_safe
when "due_date_added"
"#{event.creator == Current.user ? "You" : event.creator.name} set the date to #{event.particulars.dig('particulars', 'due_date').to_date.strftime('%B %-d')} on <span style='color: var(--card-color)'>#{ card_title(event.card) }</span>".html_safe
when "due_date_changed"
@@ -91,7 +91,7 @@ module EventsHelper
when "due_date_removed"
"#{event.creator == Current.user ? "You" : event.creator.name} removed the date on <span style='color: var(--card-color)'>#{ card_title(event.card) }</span>"
when "title_changed"
"#{event.creator == Current.user ? "You" : event.creator.name} renamed on <span style='color: var(--card-color)'>#{ card_title(event.card) }</span> (was: '#{event.particulars.dig('particulars', 'old_title')})'".html_safe
"#{event.creator == Current.user ? "You" : event.creator.name} renamed <span style='color: var(--card-color)'>#{ card_title(event.card) }</span> (was: '#{event.particulars.dig('particulars', 'old_title')})'".html_safe
end
end
+1 -1
View File
@@ -7,7 +7,7 @@ module Card::Engageable
has_one :engagement, dependent: :destroy, class_name: "Card::Engagement"
scope :doing, -> { published.active.joins(:engagement) }
scope :considering, -> { published.active.where.missing(:engagement) }
scope :considering, -> { published_or_drafted_by(Current.user).active.where.missing(:engagement) }
scope :stagnated, -> { doing.where(last_active_at: ..STAGNATED_AFTER.ago) }
end
+3 -3
View File
@@ -1,8 +1,8 @@
<div class="card__actions-container center border-radius flex-inline align-center justify-center gap" style="--card-color: <%= @card.color %>">
<div class="card__actions-container center border-radius flex-inline align-center justify-center gap" id="<%= dom_id(@card, :card_closure_toggle) %>" style="--card-color: <%= @card.color %>">
<% if card.closed? %>
<span class="card__closure-message">Completed by <%= card.closed_by.name %> on <%= local_datetime_tag(card.closed_at, style: :shortdate) %>.</span>
<span class="card__closure-message pad-inline-start">Completed by <%= card.closed_by.name %> on <%= local_datetime_tag(card.closed_at, style: :shortdate) %>.</span>
<%= button_to card_closure_path(card), method: :delete, class: "btn btn--plain borderless fill-transparent" do %>
<span>Un-do</span>
<span class="pad-inline-end">Un-do</span>
<% end %>
<% else %>
<details class="expander" data-controller="details" data-details-target="details" data-action="keydown.esc->details#close click@document->details#closeOnClickOutside">
+1 -1
View File
@@ -3,7 +3,7 @@
<%= icon_tag "picture-remove" %>
<span class="for-screen-reader">Clear background image</span>
<% end %>
<% else %>
<% elsif !card.closed? %>
<%= form_with model: card, url: collection_card_path(card.collection, card), data: { controller: "form" } do |form| %>
<label class="btn">
<%= icon_tag "picture-add" %>
+3 -2
View File
@@ -1,4 +1,5 @@
<div class="card card--mini border flex flex-column gap position-relative txt-align-start full-width border-radius fill-white" style="--card-color: <%= card.color %>; view-transition-name: <%= dom_id(card, :ticket) %>;">
<%= tag.div class: ["card card--mini border flex flex-column gap position-relative txt-align-start full-width border-radius fill-white", { "card--drafted": card.drafted? }],
style: "--card-color: #{ card.color }; view-transition-name: #{ dom_id(card, :ticket) };" do %>
<header class="card__header flex align-center gap min-width">
<span class="card__collection txt-uppercase overflow-ellipsis txt-reversed">
<%= card.collection.name %>
@@ -20,4 +21,4 @@
<%= link_to collection_card_path(card.collection, card), class: "card__link" do %>
<span class="for-screen-reader"><%= card_title(card) %></span>
<% end %>
</div>
<% end %>
@@ -3,7 +3,7 @@
<%= avatar_tag assignee, class: "avatar" %>
<% end %>
<div class="position-relative" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
<div class="position-relative" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside" <%= "hidden" if card.closed? %>>
<button class="btn card__hide-on-index <%= card.creating? || card.drafted? ? "fill-highlight" : "fill-transparent" %>" data-action="click->dialog#open:stop">
<%= icon_tag "add" %>
<span class="for-screen-reader">Assign</span>
+10 -2
View File
@@ -4,6 +4,9 @@
<div class="flex flex-column gap txt-align-start">
<span class="pad-inline overflow-ellipsis">Added
<%= local_datetime_tag(card.created_at, style: :daysago) %>
<% if card.drafted? %>
<strong>(Draft)</strong>
<% end %>
</span>
<hr class="full-width separator--horizontal unpad margin-none">
@@ -16,8 +19,13 @@
<hr class="separator margin-none unpad">
<div class="flex flex-column gap txt-align-start overflow-ellipsis">
<span class="pad-inline overflow-ellipsis"><%= card.creating? ? "Created" : "Updated" %>
<%= local_datetime_tag(card.updated_at, style: :daysago) %>
<span class="pad-inline overflow-ellipsis">
<% if card.creating? %>
&nbsp;
<% else %>
Updated
<%= local_datetime_tag(card.updated_at, style: :daysago) %>
<% end %>
</span>
<hr class="full-width separator--horizontal unpad margin-none">
+1 -1
View File
@@ -11,7 +11,7 @@
<% end %>
</div>
<div class="position-relative" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
<div class="position-relative" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside" <%= "hidden" if card.closed? %>>
<button class="tag-picker__button btn card__hide-on-index <%= card.creating? || card.drafted? ? "fill-highlight" : "fill-transparent" %>" data-action="click->dialog#open:stop">
<%= icon_tag "tag" %>
<span class="for-screen-reader">Add a tag</span>
+15 -13
View File
@@ -24,23 +24,25 @@
<%= link_to_home %>
<%= link_to_back fallback_path: cards_path(collection_id: @card.collection) %>
<div class="card__actions-container card__actions-container--top center border-radius" style="--card-color: <%= @card.color %>;">
<div class="btn__group flex full-width">
<%= form_with url: card_engagement_path(@card), method: :delete, data: { controller: "form" } do |form| %>
<%= form.label :engagement, value: "considering", class: "btn", aria: { label: "Move to Doing"} do %>
<%= form.radio_button :engagement, "considering", checked: @card.considering?, class: "for-screen-reader", data: { action: "change->form#submit" } %>
<span>Considering</span>
<% if @card.published? && !@card.closed? %>
<div class="card__actions-container card__actions-container--top center border-radius" id="<%= dom_id(@card, :card_engagement_toggle) %>" style="--card-color: <%= @card.color %>;">
<div class="btn__group flex full-width txt-uppercase">
<%= form_with url: card_engagement_path(@card), method: :delete, data: { controller: "form" } do |form| %>
<%= form.label :engagement, value: "considering", class: "btn", aria: { label: "Move to Doing"} do %>
<%= form.radio_button :engagement, "considering", checked: @card.considering?, class: "for-screen-reader", data: { action: "change->form#submit" } %>
<span>Considering</span>
<% end %>
<% end %>
<% end %>
<%= form_with url: card_engagement_path(@card), method: :post, data: { controller: "form" } do |form| %>
<%= form.label :engagement, value: "doing", class: "btn", aria: { label: "Move back to Considering"} do %>
<%= form.radio_button :engagement, "doing", checked: @card.doing?, class: "for-screen-reader", data: { action: "change->form#submit" } %>
<span>Doing</span>
<%= form_with url: card_engagement_path(@card), method: :post, data: { controller: "form" } do |form| %>
<%= form.label :engagement, value: "doing", class: "btn", aria: { label: "Move back to Considering"} do %>
<%= form.radio_button :engagement, "doing", checked: @card.doing?, class: "for-screen-reader", data: { action: "change->form#submit" } %>
<span>Doing</span>
<% end %>
<% end %>
<% end %>
</div>
</div>
</div>
<% end %>
<div class="btn btn--placeholder flex-item-justify-end"></div>
<div class="btn btn--placeholder"></div>
@@ -2,5 +2,7 @@
<%= render partial: "cards/stagings/stages", locals: { card: @card } %>
<% end %>
<%= turbo_stream.set_css_variable dom_id(@card, :card_closure_toggle), name: "--card-color", value: @card.color %>
<%= turbo_stream.set_css_variable dom_id(@card, :card_container), name: "--card-color", value: @card.color %>
<%= turbo_stream.set_css_variable dom_id(@card, :card_engagement_toggle), name: "--card-color", value: @card.color %>
<%= turbo_stream.set_css_variable dom_id(@card, :ticket), name: "--card-color", value: @card.color %>
+1 -1
View File
@@ -2,7 +2,7 @@
<% link = event.action == "commented" ? collection_card_path(card.collection, card, anchor: dom_id(event.comment)) : collection_card_path(card.collection, card) %>
<%= link_to link,
class: "event panel center center-block flex-inline align-start justify-start gap position-relative",
class: "event event--#{ event.action } panel center center-block flex-inline align-start justify-start gap position-relative",
style: "--card-color: #{ card.color }; background-color: color-mix(in srgb, var(--card-color) 10%, var(--color-bg));
color: color-mix(in srgb, var(--card-color) 40%, var(--color-ink));",
data: { related_element_target: "related",