From e658e719772877baa71227de96265b9f7e1473df Mon Sep 17 00:00:00 2001 From: Alexander Zaytsev Date: Tue, 13 Jan 2026 11:47:44 +0100 Subject: [PATCH 1/9] Remove hover styles from disabled menu items --- app/assets/stylesheets/popup.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/popup.css b/app/assets/stylesheets/popup.css index 02ae8969e..aecf71756 100644 --- a/app/assets/stylesheets/popup.css +++ b/app/assets/stylesheets/popup.css @@ -123,6 +123,10 @@ } } + &:has(.popup__btn[disabled]) { + pointer-events: none; + } + .checked { display: none; } From 671ce573c8b2e0fd0f61c04791c7f7071ab00db5 Mon Sep 17 00:00:00 2001 From: Alexander Zaytsev Date: Tue, 13 Jan 2026 11:48:04 +0100 Subject: [PATCH 2/9] Remove whitespace --- app/assets/stylesheets/popup.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/popup.css b/app/assets/stylesheets/popup.css index aecf71756..bfbefc87a 100644 --- a/app/assets/stylesheets/popup.css +++ b/app/assets/stylesheets/popup.css @@ -159,7 +159,7 @@ max-inline-size: 100%; padding: var(--inline-space-half) var(--popup-item-padding-inline); text-align: start; - + &:focus-visible { z-index: 1; } From 4321ed86aa16ba205258d31bdad90d32ce3cbd9f Mon Sep 17 00:00:00 2001 From: Rob Zolkos Date: Thu, 15 Jan 2026 21:09:23 -0500 Subject: [PATCH 3/9] Add Enable all/Disable all buttons to webhook event selection Makes it easier to quickly select or deselect all webhook event types when configuring a webhook. Uses the existing toggle-class Stimulus controller. --- app/views/webhooks/form/_actions.html.erb | 41 +++++++++++++---------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/app/views/webhooks/form/_actions.html.erb b/app/views/webhooks/form/_actions.html.erb index 95a287abe..e4126225e 100644 --- a/app/views/webhooks/form/_actions.html.erb +++ b/app/views/webhooks/form/_actions.html.erb @@ -1,17 +1,24 @@ -
    - <%= form.collection_check_boxes \ - :subscribed_actions, - webhook_action_options, - :first, - :last do |item| %> -
  • - -
  • - <% end %> -
+
+
+ <%= button_tag "Enable all", type: "button", class: "btn btn--plain txt-x-small txt-link font-weight-normal", data: { action: "click->toggle-class#checkAll" } %> + · + <%= button_tag "Disable all", type: "button", class: "btn btn--plain txt-x-small txt-link font-weight-normal", data: { action: "click->toggle-class#checkNone" } %> +
+
    + <%= form.collection_check_boxes \ + :subscribed_actions, + webhook_action_options, + :first, + :last do |item| %> +
  • + +
  • + <% end %> +
+
From 2527f07365112893885953d819e07cc28f4c073b Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Fri, 16 Jan 2026 13:41:30 -0500 Subject: [PATCH 4/9] Fix "M" hotkey using stale user from fragment cache Add a SelfAssignmentsController to resolve the current user at request time, avoiding the use of an incorrect user id baked into a cached URL. ref: #2211 originally added the "M" hotkey ref: https://app.fizzy.do/5986089/cards/3722 --- .../cards/self_assignments_controller.rb | 17 +++++++ .../controllers/card_hotkeys_controller.js | 2 +- app/views/cards/display/_preview.html.erb | 4 +- config/routes.rb | 1 + .../cards/self_assignments_controller_test.rb | 44 +++++++++++++++++++ 5 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 app/controllers/cards/self_assignments_controller.rb create mode 100644 test/controllers/cards/self_assignments_controller_test.rb diff --git a/app/controllers/cards/self_assignments_controller.rb b/app/controllers/cards/self_assignments_controller.rb new file mode 100644 index 000000000..a38c99cf0 --- /dev/null +++ b/app/controllers/cards/self_assignments_controller.rb @@ -0,0 +1,17 @@ +class Cards::SelfAssignmentsController < ApplicationController + include CardScoped + + def create + if @card.toggle_assignment(Current.user) + respond_to do |format| + format.turbo_stream { render "cards/assignments/create" } + format.json { head :no_content } + end + else + respond_to do |format| + format.turbo_stream { render "cards/assignments/create" } + format.json { head :unprocessable_entity } + end + end + end +end diff --git a/app/javascript/controllers/card_hotkeys_controller.js b/app/javascript/controllers/card_hotkeys_controller.js index 564c076ad..62d02288d 100644 --- a/app/javascript/controllers/card_hotkeys_controller.js +++ b/app/javascript/controllers/card_hotkeys_controller.js @@ -79,7 +79,7 @@ export default class extends Controller { const selection = this.#selectedCard if (!selection) return - const url = selection.card.dataset.cardAssignToMeUrl + const url = selection.card.dataset.cardAssignToSelfUrl if (url) { event.preventDefault() await post(url, { responseKind: "turbo-stream" }) diff --git a/app/views/cards/display/_preview.html.erb b/app/views/cards/display/_preview.html.erb index c1fc67914..c7f157f1c 100644 --- a/app/views/cards/display/_preview.html.erb +++ b/app/views/cards/display/_preview.html.erb @@ -11,9 +11,7 @@ <% card_data[:card_not_now_url] = card_not_now_path(card) %> <% card_data[:card_closure_url] = card_closure_path(card) %> <% card_data[:action] = "mouseenter->navigable-list#hoverSelect" %> - <% if Current.user %> - <% card_data[:card_assign_to_me_url] = card_assignments_path(card, params: { assignee_id: Current.user.id }) %> - <% end %> + <% card_data[:card_assign_to_self_url] = card_self_assignment_path(card) %> <% end %> <%= card_article_tag card, class: "card", draggable: draggable, data: card_data, tabindex: 0 do %> diff --git a/config/routes.rb b/config/routes.rb index 97e34290c..3a76e8b7a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -87,6 +87,7 @@ Rails.application.routes.draw do resource :reading resources :assignments + resource :self_assignment, only: :create resources :steps resources :taggings diff --git a/test/controllers/cards/self_assignments_controller_test.rb b/test/controllers/cards/self_assignments_controller_test.rb new file mode 100644 index 000000000..3edde8fec --- /dev/null +++ b/test/controllers/cards/self_assignments_controller_test.rb @@ -0,0 +1,44 @@ +require "test_helper" + +class Cards::SelfAssignmentsControllerTest < ActionDispatch::IntegrationTest + setup do + sign_in_as :kevin + end + + test "create assigns to current user" do + card = cards(:layout) + + assert_not card.assigned_to?(users(:kevin)) + + post card_self_assignment_path(card), as: :turbo_stream + assert_response :success + assert_meta_replaced(card) + assert card.reload.assigned_to?(users(:kevin)) + end + + test "create toggles off when already assigned" do + card = cards(:logo) + + assert card.assigned_to?(users(:kevin)) + + post card_self_assignment_path(card), as: :turbo_stream + assert_response :success + assert_meta_replaced(card) + assert_not card.reload.assigned_to?(users(:kevin)) + end + + test "create as JSON" do + card = cards(:layout) + + assert_not card.assigned_to?(users(:kevin)) + + post card_self_assignment_path(card), as: :json + assert_response :no_content + assert card.reload.assigned_to?(users(:kevin)) + end + + private + def assert_meta_replaced(card) + assert_turbo_stream action: :replace, target: dom_id(card, :meta) + end +end From e5eb1080f658dd73dfe1108a0ff60a51852cda23 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 16 Jan 2026 13:24:23 -0600 Subject: [PATCH 5/9] Add dialog manager to card perma --- app/views/cards/_container.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/cards/_container.html.erb b/app/views/cards/_container.html.erb index d66996f96..85e08bfd0 100644 --- a/app/views/cards/_container.html.erb +++ b/app/views/cards/_container.html.erb @@ -1,4 +1,4 @@ -
+
<% cache card do %>
<%= render "cards/container/gild", card: card if card.published? && !card.closed? %> From 19ce79965b6df4f1b4ba37c8fd5a9f79044ddc6e Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 16 Jan 2026 14:00:04 -0600 Subject: [PATCH 6/9] Align board and tag picker dialogs without using math --- app/assets/stylesheets/card-perma.css | 11 ---- app/assets/stylesheets/cards.css | 63 ++++++++++++++++--- app/assets/stylesheets/print.css | 4 +- app/assets/stylesheets/tags.css | 33 ---------- .../cards/display/common/_board.html.erb | 16 +++-- app/views/cards/display/perma/_board.html.erb | 23 +++---- app/views/cards/display/perma/_tags.html.erb | 4 +- .../cards/display/preview/_board.html.erb | 4 +- 8 files changed, 77 insertions(+), 81 deletions(-) delete mode 100644 app/assets/stylesheets/tags.css diff --git a/app/assets/stylesheets/card-perma.css b/app/assets/stylesheets/card-perma.css index 8d1340c23..073508bff 100644 --- a/app/assets/stylesheets/card-perma.css +++ b/app/assets/stylesheets/card-perma.css @@ -119,17 +119,6 @@ } } - .board-picker__button { - --btn-border-size: 0; - - font-size: 0.5em; - margin-inline-start: 1ch; - - + .panel { - --panel-size: 18ch; - } - } - .bubble { --bubble-number-max: 42px; --bubble-size: 6rem; diff --git a/app/assets/stylesheets/cards.css b/app/assets/stylesheets/cards.css index 3fb0a7f4d..646f060a7 100644 --- a/app/assets/stylesheets/cards.css +++ b/app/assets/stylesheets/cards.css @@ -71,21 +71,19 @@ min-inline-size: 0; padding-block: 0.25lh; padding-inline: var(--card-padding-inline) 1ch; + position: relative; + transition: background-color 100ms ease-out; - &:has(.board-picker__button) { - cursor: pointer; - transition: background-color 100ms ease-out; - + &:has(.btn) { @media (any-hover: hover) { &:hover { background-color: color-mix(in srgb, var(--card-color) 90%, var(--color-ink)); } } + } - &:has(.btn:focus-visible) { - outline: var(--focus-ring-size) solid var(--focus-ring-color); - outline-offset: var(--focus-ring-offset); - } + dialog { + inset: 100% auto auto 0; } } @@ -99,9 +97,11 @@ } .card__board-name { + align-items: center; border-inline-start: 1px solid color-mix(in hsl, transparent 75%, currentColor); color: currentColor; display: flex; + gap: 0.25ch; margin-inline-start: var(--card-header-space); max-inline-size: 100%; min-inline-size: 0; @@ -109,14 +109,59 @@ text-transform: uppercase; } + .card__board-picker-btn { + inset: 0; + position: absolute; + } + .card__tags { --btn-color: var(--card-color); align-items: center; + align-self: stretch; color: var(--card-text-color); display: flex; - gap: var(--card-header-space); + gap: 0.5ch; min-inline-size: 0; + + [data-controller="dialog"] { + align-items: center; + align-self: stretch; + display: flex; + position: relative; + } + + .popup { + --panel-size: 18ch; + + inset-block-start: 100%; + } + } + + .card__tag-picker { + --panel-border-radius: 2em; + --panel-padding: 0.5em 0.7em; + --panel-size: max-content; + + inline-size: auto !important; + inset: 0 auto auto 0; + max-inline-size: var(--panel-size) !important; + position: absolute; + z-index: 2; + + &[open] { + display: flex; + } + + .input { + --input-padding: 0.2em 0.5em; + + inline-size: 18ch; + } + } + + .card__tag-picker-button { + font-size: 0.6em; } .card__tag { diff --git a/app/assets/stylesheets/print.css b/app/assets/stylesheets/print.css index 5ed9c3fdf..cd55b5196 100644 --- a/app/assets/stylesheets/print.css +++ b/app/assets/stylesheets/print.css @@ -164,8 +164,8 @@ .comments__subscribers, .card__meta-avatars--assignees > div > div:last-child, .steps > .step:last-child, - div:has(> .tag-picker__button), - div:has(> .board-picker__button), + .card__board-name .icon, + div:has(> .card__tag-picker-button), .delete-card, .header--card .header__title { display: none; diff --git a/app/assets/stylesheets/tags.css b/app/assets/stylesheets/tags.css deleted file mode 100644 index 90d51e011..000000000 --- a/app/assets/stylesheets/tags.css +++ /dev/null @@ -1,33 +0,0 @@ -@layer components { - .tag-picker { - --panel-border-radius: 2em; - --panel-padding: 0.5em 0.7em; - --panel-size: max-content; - - inline-size: auto !important; - inset: 0 auto auto 0; - max-inline-size: var(--panel-size) !important; - position: absolute; - z-index: 2; - - &[open] { - display: flex; - } - - .input { - --input-padding: 0.2em 0.5em; - - inline-size: 18ch; - } - } - - .tag-picker__button { - font-size: 0.6em; - margin-block-start: 0.1em; - margin-inline-start: 0.2em; - - + .panel { - --panel-size: 18ch; - } - } -} diff --git a/app/views/cards/display/common/_board.html.erb b/app/views/cards/display/common/_board.html.erb index 3e91a0d78..e5595ab39 100644 --- a/app/views/cards/display/common/_board.html.erb +++ b/app/views/cards/display/common/_board.html.erb @@ -1,10 +1,8 @@ -