From a96583fcacb514e07c47541a840a4d54ea9fcd51 Mon Sep 17 00:00:00 2001 From: William Idakwo <30729966+vixen24@users.noreply.github.com> Date: Tue, 23 Dec 2025 18:51:13 +0100 Subject: [PATCH 01/14] Add margin to details inside popup styles Allow focus indicator to display in full when navigating with the keyboard (using TAB) --- app/assets/stylesheets/popup.css | 1 + 1 file changed, 1 insertion(+) diff --git a/app/assets/stylesheets/popup.css b/app/assets/stylesheets/popup.css index 189cfef5b..d5b1e1e72 100644 --- a/app/assets/stylesheets/popup.css +++ b/app/assets/stylesheets/popup.css @@ -106,6 +106,7 @@ details & { margin-inline-start: 0.75ch; + margin-block-start: 0.35ch; } } From a93d8b4414493741ca52fb27604e5c1d1f56e025 Mon Sep 17 00:00:00 2001 From: user Date: Sat, 27 Dec 2025 20:44:02 +0900 Subject: [PATCH 02/14] Update --font-sans to include "Segoe UI Variable" for improved text rendering --- app/assets/stylesheets/_global.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/_global.css b/app/assets/stylesheets/_global.css index 47f29691a..8404a447c 100644 --- a/app/assets/stylesheets/_global.css +++ b/app/assets/stylesheets/_global.css @@ -10,7 +10,7 @@ --block-space-double: calc(var(--block-space) * 2); /* Text */ - --font-sans: "Adwaita Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; + --font-sans: "Adwaita Sans", -apple-system, BlinkMacSystemFont, "Segoe UI Variable", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; --font-serif: ui-serif, serif; --font-mono: ui-monospace, monospace; From 9dbc921c2ef0a7bcac6d16ee9e7cc4af89d2d4fa Mon Sep 17 00:00:00 2001 From: user Date: Sat, 27 Dec 2025 22:19:12 +0900 Subject: [PATCH 03/14] Add "Segoe UI fizzy" to --font-sans and define custom font faces --- app/assets/stylesheets/_global.css | 2 +- app/assets/stylesheets/segoe-ui.css | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 app/assets/stylesheets/segoe-ui.css diff --git a/app/assets/stylesheets/_global.css b/app/assets/stylesheets/_global.css index 8404a447c..03947f5fc 100644 --- a/app/assets/stylesheets/_global.css +++ b/app/assets/stylesheets/_global.css @@ -10,7 +10,7 @@ --block-space-double: calc(var(--block-space) * 2); /* Text */ - --font-sans: "Adwaita Sans", -apple-system, BlinkMacSystemFont, "Segoe UI Variable", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; + --font-sans: "Adwaita Sans", -apple-system, BlinkMacSystemFont, "Segoe UI fizzy", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; --font-serif: ui-serif, serif; --font-mono: ui-monospace, monospace; diff --git a/app/assets/stylesheets/segoe-ui.css b/app/assets/stylesheets/segoe-ui.css new file mode 100644 index 000000000..fde554c58 --- /dev/null +++ b/app/assets/stylesheets/segoe-ui.css @@ -0,0 +1,29 @@ +@layer reset { + @font-face { + font-family: "Segoe UI fizzy"; + src: local("Segoe UI Variable"); + font-weight: 100 700; + font-style: normal; + } + + @font-face { + font-family: "Segoe UI fizzy"; + src: local("Segoe UI Variable Italic"); + font-weight: 100 700; + font-style: italic; + } + + @font-face { + font-family: "Segoe UI fizzy"; + src: local("Segoe UI Black"); + font-weight: 900; + font-style: normal; + } + + @font-face { + font-family: "Segoe UI fizzy"; + src: local("Segoe UI Black Italic"); + font-weight: 900; + font-style: italic; + } +} From d7d2f92c293d0954e2a9caeac2459f9d7ed56f6f Mon Sep 17 00:00:00 2001 From: user Date: Sat, 27 Dec 2025 22:32:01 +0900 Subject: [PATCH 04/14] Update --font-sans and related font-face references to "Segoe UI Variable Fizzy" for consistency --- app/assets/stylesheets/_global.css | 2 +- .../{segoe-ui.css => segoe-ui-variable-fizzy.css} | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) rename app/assets/stylesheets/{segoe-ui.css => segoe-ui-variable-fizzy.css} (71%) diff --git a/app/assets/stylesheets/_global.css b/app/assets/stylesheets/_global.css index 03947f5fc..a14a3d29f 100644 --- a/app/assets/stylesheets/_global.css +++ b/app/assets/stylesheets/_global.css @@ -10,7 +10,7 @@ --block-space-double: calc(var(--block-space) * 2); /* Text */ - --font-sans: "Adwaita Sans", -apple-system, BlinkMacSystemFont, "Segoe UI fizzy", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; + --font-sans: "Adwaita Sans", -apple-system, BlinkMacSystemFont, "Segoe UI Variable Fizzy", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; --font-serif: ui-serif, serif; --font-mono: ui-monospace, monospace; diff --git a/app/assets/stylesheets/segoe-ui.css b/app/assets/stylesheets/segoe-ui-variable-fizzy.css similarity index 71% rename from app/assets/stylesheets/segoe-ui.css rename to app/assets/stylesheets/segoe-ui-variable-fizzy.css index fde554c58..4919463d1 100644 --- a/app/assets/stylesheets/segoe-ui.css +++ b/app/assets/stylesheets/segoe-ui-variable-fizzy.css @@ -1,27 +1,27 @@ @layer reset { @font-face { - font-family: "Segoe UI fizzy"; + font-family: "Segoe UI Variable Fizzy"; src: local("Segoe UI Variable"); font-weight: 100 700; font-style: normal; } @font-face { - font-family: "Segoe UI fizzy"; + font-family: "Segoe UI Variable Fizzy"; src: local("Segoe UI Variable Italic"); font-weight: 100 700; font-style: italic; } @font-face { - font-family: "Segoe UI fizzy"; + font-family: "Segoe UI Variable Fizzy"; src: local("Segoe UI Black"); font-weight: 900; font-style: normal; } @font-face { - font-family: "Segoe UI fizzy"; + font-family: "Segoe UI Variable Fizzy"; src: local("Segoe UI Black Italic"); font-weight: 900; font-style: italic; From 6d8536ddf8bf27cdd4de1e9e07a49160391dc4e8 Mon Sep 17 00:00:00 2001 From: user Date: Sat, 27 Dec 2025 22:54:30 +0900 Subject: [PATCH 05/14] Adjust font-weight range for "Segoe UI Variable Fizzy" to include 800-900 --- app/assets/stylesheets/segoe-ui-variable-fizzy.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/segoe-ui-variable-fizzy.css b/app/assets/stylesheets/segoe-ui-variable-fizzy.css index 4919463d1..bc4e9e626 100644 --- a/app/assets/stylesheets/segoe-ui-variable-fizzy.css +++ b/app/assets/stylesheets/segoe-ui-variable-fizzy.css @@ -16,14 +16,14 @@ @font-face { font-family: "Segoe UI Variable Fizzy"; src: local("Segoe UI Black"); - font-weight: 900; + font-weight: 800 900; font-style: normal; } @font-face { font-family: "Segoe UI Variable Fizzy"; src: local("Segoe UI Black Italic"); - font-weight: 900; + font-weight: 800 900; font-style: italic; } } From 085bb70a8cb4551d010c79c85333e00f885dc123 Mon Sep 17 00:00:00 2001 From: user Date: Sat, 27 Dec 2025 23:50:12 +0900 Subject: [PATCH 06/14] Fix font-face `src` reference for "Segoe UI Variable Fizzy" to correct local font lookup --- app/assets/stylesheets/segoe-ui-variable-fizzy.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/segoe-ui-variable-fizzy.css b/app/assets/stylesheets/segoe-ui-variable-fizzy.css index bc4e9e626..55b093755 100644 --- a/app/assets/stylesheets/segoe-ui-variable-fizzy.css +++ b/app/assets/stylesheets/segoe-ui-variable-fizzy.css @@ -8,7 +8,7 @@ @font-face { font-family: "Segoe UI Variable Fizzy"; - src: local("Segoe UI Variable Italic"); + src: local("Segoe UI Variable"); font-weight: 100 700; font-style: italic; } From 5c453952a84a41259396480b5b0546274b6f68d2 Mon Sep 17 00:00:00 2001 From: user Date: Thu, 8 Jan 2026 13:25:41 +0900 Subject: [PATCH 07/14] Update @layer name to `base` in font-face definition for "Segoe UI Variable Fizzy" --- .../stylesheets/{segoe-ui-variable-fizzy.css => font-face.css} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename app/assets/stylesheets/{segoe-ui-variable-fizzy.css => font-face.css} (97%) diff --git a/app/assets/stylesheets/segoe-ui-variable-fizzy.css b/app/assets/stylesheets/font-face.css similarity index 97% rename from app/assets/stylesheets/segoe-ui-variable-fizzy.css rename to app/assets/stylesheets/font-face.css index 55b093755..4563c0b52 100644 --- a/app/assets/stylesheets/segoe-ui-variable-fizzy.css +++ b/app/assets/stylesheets/font-face.css @@ -1,4 +1,4 @@ -@layer reset { +@layer base { @font-face { font-family: "Segoe UI Variable Fizzy"; src: local("Segoe UI Variable"); From cd9b38221437f4faaf47bbfd4abe7ff8ff063abd Mon Sep 17 00:00:00 2001 From: user Date: Thu, 8 Jan 2026 13:53:46 +0900 Subject: [PATCH 08/14] Add Segoe UI Variable Fizzy font face configuration comments --- app/assets/stylesheets/font-face.css | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/assets/stylesheets/font-face.css b/app/assets/stylesheets/font-face.css index 4563c0b52..086111ed4 100644 --- a/app/assets/stylesheets/font-face.css +++ b/app/assets/stylesheets/font-face.css @@ -1,4 +1,16 @@ @layer base { + /* + Segoe UI Variable Fizzy font face configuration. + + 1. Segoe UI Variable (Weights 100-700): + Leverages variable font features to: + - Automatically adjust Weight (wght) dynamically within the 100-700 range. + - Automatically manage Optical Size (opsz) based on font-size. + + 2. Segoe UI Black (Weights 800-900): + Used as a fallback because Segoe UI Variable does not natively support 900 weight. + This ensures a consistent bold experience across all weights. + */ @font-face { font-family: "Segoe UI Variable Fizzy"; src: local("Segoe UI Variable"); From 2992b53577fef38e6c2682dde497515c12073ca9 Mon Sep 17 00:00:00 2001 From: William Idakwo <30729966+vixen24@users.noreply.github.com> Date: Thu, 8 Jan 2026 08:45:58 +0100 Subject: [PATCH 09/14] Refactor popup.css styles for focus state Remove margin-block-start from details in popup styles and add focus-visible style to popup item. --- app/assets/stylesheets/popup.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/popup.css b/app/assets/stylesheets/popup.css index d5b1e1e72..02ae8969e 100644 --- a/app/assets/stylesheets/popup.css +++ b/app/assets/stylesheets/popup.css @@ -106,7 +106,6 @@ details & { margin-inline-start: 0.75ch; - margin-block-start: 0.35ch; } } @@ -156,6 +155,10 @@ max-inline-size: 100%; padding: var(--inline-space-half) var(--popup-item-padding-inline); text-align: start; + + &:focus-visible { + z-index: 1; + } } .popup__icon { From f58a1aeb319713feed2247af0841a506ce3bf877 Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Wed, 7 Jan 2026 11:29:40 +0100 Subject: [PATCH 10/14] Use a dedicated resource for showing cards in draft mode Mobile team needs this. Also, this lets us get rid from some conditionals for handling both modes with a single template. https://3.basecamp.com/2914079/buckets/44843469/messages/9437287330 --- app/controllers/cards/drafts_controller.rb | 13 +++++++ app/controllers/cards/publishes_controller.rb | 3 +- app/controllers/cards_controller.rb | 7 +++- app/views/cards/_container.html.erb | 6 ---- app/views/cards/drafts/_container.html.erb | 34 +++++++++++++++++++ app/views/cards/drafts/show.html.erb | 16 +++++++++ app/views/cards/show.html.erb | 2 +- config/routes.rb | 1 + .../subscriptions/card_creation_test.rb | 10 +++--- .../cards/drafts_controller_test.rb | 21 ++++++++++++ .../cards/publishes_controller_test.rb | 2 +- test/controllers/cards_controller_test.rb | 11 ++++-- 12 files changed, 109 insertions(+), 17 deletions(-) create mode 100644 app/controllers/cards/drafts_controller.rb create mode 100644 app/views/cards/drafts/_container.html.erb create mode 100644 app/views/cards/drafts/show.html.erb create mode 100644 test/controllers/cards/drafts_controller_test.rb diff --git a/app/controllers/cards/drafts_controller.rb b/app/controllers/cards/drafts_controller.rb new file mode 100644 index 000000000..a4e9388de --- /dev/null +++ b/app/controllers/cards/drafts_controller.rb @@ -0,0 +1,13 @@ +class Cards::DraftsController < ApplicationController + include CardScoped + + before_action :redirect_if_published + + def show + end + + private + def redirect_if_published + redirect_to @card unless @card.drafted? + end +end diff --git a/app/controllers/cards/publishes_controller.rb b/app/controllers/cards/publishes_controller.rb index 641f728cd..a0378eec3 100644 --- a/app/controllers/cards/publishes_controller.rb +++ b/app/controllers/cards/publishes_controller.rb @@ -5,7 +5,8 @@ class Cards::PublishesController < ApplicationController @card.publish if add_another_param? - redirect_to @board.cards.create!, notice: "Card added" + card = @board.cards.create!(status: :drafted) + redirect_to card_draft_path(card), notice: "Card added" else redirect_to @card.board end diff --git a/app/controllers/cards_controller.rb b/app/controllers/cards_controller.rb index e79eeb22b..e007527b8 100644 --- a/app/controllers/cards_controller.rb +++ b/app/controllers/cards_controller.rb @@ -3,6 +3,7 @@ class CardsController < ApplicationController before_action :set_board, only: %i[ create ] before_action :set_card, only: %i[ show edit update destroy ] + before_action :redirect_if_drafted, only: :show before_action :ensure_permission_to_administer_card, only: %i[ destroy ] def index @@ -13,7 +14,7 @@ class CardsController < ApplicationController respond_to do |format| format.html do card = Current.user.draft_new_card_in(@board) - redirect_to card + redirect_to card_draft_path(card) end format.json do @@ -56,6 +57,10 @@ class CardsController < ApplicationController @card = Current.user.accessible_cards.find_by!(number: params[:id]) end + def redirect_if_drafted + redirect_to card_draft_path(@card) if @card.drafted? + end + def ensure_permission_to_administer_card head :forbidden unless Current.user.can_administer_card?(@card) end diff --git a/app/views/cards/_container.html.erb b/app/views/cards/_container.html.erb index c85236683..d66996f96 100644 --- a/app/views/cards/_container.html.erb +++ b/app/views/cards/_container.html.erb @@ -37,11 +37,5 @@ <% if card.published? %> <%= render "cards/container/footer/published", card: card %> - <% elsif card.drafted? %> - <% if Fizzy.saas? %> - <%= render "cards/container/footer/saas/create", card: card %> - <% else %> - <%= render "cards/container/footer/create", card: card %> - <% end %> <% end %> diff --git a/app/views/cards/drafts/_container.html.erb b/app/views/cards/drafts/_container.html.erb new file mode 100644 index 000000000..c74326544 --- /dev/null +++ b/app/views/cards/drafts/_container.html.erb @@ -0,0 +1,34 @@ +
+ <% cache card do %> +
+ <%= render "cards/container/image", card: card %> +
+ +
+ <%= card_article_tag card, class: "card" do %> +
+ <%= render "cards/display/perma/board", card: card %> + <%= render "cards/display/perma/tags", card: card %> +
+ +
+
+ <%= render "cards/container/content", card: card %> + <%= render "cards/display/perma/steps", card: card %> +
+
+ +
+ <%= render "cards/display/perma/meta", card: card %> + <%= render "cards/display/perma/background", card: card %> +
+ <% end %> +
+ <% end %> + + <% if Fizzy.saas? %> + <%= render "cards/container/footer/saas/create", card: card %> + <% else %> + <%= render "cards/container/footer/create", card: card %> + <% end %> +
diff --git a/app/views/cards/drafts/show.html.erb b/app/views/cards/drafts/show.html.erb new file mode 100644 index 000000000..d670f4c2f --- /dev/null +++ b/app/views/cards/drafts/show.html.erb @@ -0,0 +1,16 @@ +<% @page_title = @card.title %> +<% @header_class = "header--card" %> + +<% content_for :header do %> +
+ <%= link_back_to_board(@card.board) %> +
+<% end %> + +
+ <%= render "cards/drafts/container", card: @card %> + + <%= render "layouts/lightbox" do %> + <%= button_to_remove_card_image(@card) if @card.image.attached? %> + <% end %> +
diff --git a/app/views/cards/show.html.erb b/app/views/cards/show.html.erb index 596006ce8..bfaa9c676 100644 --- a/app/views/cards/show.html.erb +++ b/app/views/cards/show.html.erb @@ -16,7 +16,7 @@
<%= render "cards/container", card: @card %> - <%= render "cards/messages", card: @card unless @card.drafted? %> + <%= render "cards/messages", card: @card %> <%= render "layouts/lightbox" do %> <%= button_to_remove_card_image(@card) if @card.image.attached? %> diff --git a/config/routes.rb b/config/routes.rb index d84fa06e3..0fd75fd98 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -71,6 +71,7 @@ Rails.application.routes.draw do resources :cards do scope module: :cards do + resource :draft, only: :show resource :board resource :closure resource :column diff --git a/saas/test/controllers/accounts/subscriptions/card_creation_test.rb b/saas/test/controllers/accounts/subscriptions/card_creation_test.rb index dd5e72826..1ddc4bc1c 100644 --- a/saas/test/controllers/accounts/subscriptions/card_creation_test.rb +++ b/saas/test/controllers/accounts/subscriptions/card_creation_test.rb @@ -10,7 +10,7 @@ class Account::Subscriptions::CardCreationTest < ActionDispatch::IntegrationTest test "admin sees nearing card limit notice" do accounts(:initech).update_column(:cards_count, 950) - get card_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug) + get card_draft_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug) assert_response :success assert_match /upgrade to unlimited/i, response.body @@ -19,7 +19,7 @@ class Account::Subscriptions::CardCreationTest < ActionDispatch::IntegrationTest test "admin sees nearing storage limit notice" do Account.any_instance.stubs(:bytes_used).returns(600.megabytes) - get card_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug) + get card_draft_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug) assert_response :success assert_match /upgrade to get more/i, response.body @@ -30,7 +30,7 @@ class Account::Subscriptions::CardCreationTest < ActionDispatch::IntegrationTest test "admin sees exceeding card limit notice" do accounts(:initech).update_column(:cards_count, 1001) - get card_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug) + get card_draft_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug) assert_response :success assert_match /you’ve used your.*free cards/i, response.body @@ -39,7 +39,7 @@ class Account::Subscriptions::CardCreationTest < ActionDispatch::IntegrationTest test "admin sees exceeding storage limit notice" do Account.any_instance.stubs(:bytes_used).returns(1.1.gigabytes) - get card_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug) + get card_draft_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug) assert_response :success assert_match /you’ve run out of.*free storage/i, response.body @@ -64,7 +64,7 @@ class Account::Subscriptions::CardCreationTest < ActionDispatch::IntegrationTest test "comped account under limits sees no notices" do accounts(:initech).comp - get card_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug) + get card_draft_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug) assert_response :success assert_no_match /upgrade/i, response.body diff --git a/test/controllers/cards/drafts_controller_test.rb b/test/controllers/cards/drafts_controller_test.rb new file mode 100644 index 000000000..8d14f3fff --- /dev/null +++ b/test/controllers/cards/drafts_controller_test.rb @@ -0,0 +1,21 @@ +require "test_helper" + +class Cards::DraftsControllerTest < ActionDispatch::IntegrationTest + setup do + sign_in_as :kevin + end + + test "show" do + card = boards(:writebook).cards.create!(creator: users(:kevin), status: :drafted) + + get card_draft_path(card) + assert_response :success + end + + test "show redirects to card when published" do + card = cards(:logo) + + get card_draft_path(card) + assert_redirected_to card + end +end diff --git a/test/controllers/cards/publishes_controller_test.rb b/test/controllers/cards/publishes_controller_test.rb index 4de6d20bb..537a6f73b 100644 --- a/test/controllers/cards/publishes_controller_test.rb +++ b/test/controllers/cards/publishes_controller_test.rb @@ -28,6 +28,6 @@ class Cards::PublishesControllerTest < ActionDispatch::IntegrationTest new_card = Card.last assert new_card.drafted? - assert_redirected_to new_card + assert_redirected_to card_draft_path(new_card) end end diff --git a/test/controllers/cards_controller_test.rb b/test/controllers/cards_controller_test.rb index d13affa96..11c4b62a5 100644 --- a/test/controllers/cards_controller_test.rb +++ b/test/controllers/cards_controller_test.rb @@ -21,7 +21,7 @@ class CardsControllerTest < ActionDispatch::IntegrationTest end card = Card.last - assert_redirected_to card + assert_redirected_to card_draft_path(card) assert card.drafted? end @@ -31,10 +31,17 @@ class CardsControllerTest < ActionDispatch::IntegrationTest assert_no_difference -> { Card.count } do post board_cards_path(boards(:writebook)) - assert_redirected_to draft + assert_redirected_to card_draft_path(draft) end end + test "show redirects to draft when card is drafted" do + card = boards(:writebook).cards.create!(creator: users(:kevin), status: :drafted) + + get card_path(card) + assert_redirected_to card_draft_path(card) + end + test "show" do get card_path(cards(:logo)) assert_response :success From 625940e41425bb5c0456f41a4eb417e8c99e38cc Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Thu, 8 Jan 2026 12:41:57 -0600 Subject: [PATCH 11/14] Bump filter z-index when filters are open --- app/assets/stylesheets/filters.css | 1 + 1 file changed, 1 insertion(+) diff --git a/app/assets/stylesheets/filters.css b/app/assets/stylesheets/filters.css index 082fcf2fc..efc04e21d 100644 --- a/app/assets/stylesheets/filters.css +++ b/app/assets/stylesheets/filters.css @@ -19,6 +19,7 @@ --input-background: var(--color-canvas); } + &:has(dialog[open]), &:has([data-controller~="tooltip"]:hover) { z-index: calc(var(--z-nav) + 1); } From 1802b45c8dd6091633477a3d0f4327ea5b536f86 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Thu, 8 Jan 2026 13:30:10 -0600 Subject: [PATCH 12/14] Account for new button sizes on mobile --- app/assets/stylesheets/comments.css | 6 +++++- app/assets/stylesheets/reactions.css | 7 +++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/comments.css b/app/assets/stylesheets/comments.css index c8453bc14..2ae664dcd 100644 --- a/app/assets/stylesheets/comments.css +++ b/app/assets/stylesheets/comments.css @@ -4,7 +4,7 @@ --comment-padding-block: var(--block-space-half); --comment-padding-inline: var(--inline-space-double); --comment-max: 70ch; - --reaction-size: 1.6875rem; + --reaction-size: 2rem; display: flex; flex-direction: column; @@ -15,6 +15,10 @@ @media (min-width: 160ch) { padding-inline: var(--tray-size); } + + @media (min-width: 640px) { + --reaction-size: 1.6875rem; + } } .comments__subscribers { diff --git a/app/assets/stylesheets/reactions.css b/app/assets/stylesheets/reactions.css index 5dea448cc..d1cd0a03f 100644 --- a/app/assets/stylesheets/reactions.css +++ b/app/assets/stylesheets/reactions.css @@ -10,7 +10,7 @@ flex-wrap: wrap; gap: var(--inline-space-half); inline-size: 100%; - margin-block-start: calc(var(--block-space-half) / 2); + margin-block-start: var(--block-space-half); margin-inline: calc(var(--column-gap) / -1); &:has([open]) { @@ -44,6 +44,7 @@ } .reactions__trigger { + --btn-size: var(--reaction-size); --btn-border-color: var(--reaction-border-color); img { @@ -115,11 +116,13 @@ /* Make the avatar and delete buttons fit nicely within the reaction */ .reaction__avatar, + .reaction__avatar .avatar, .reaction__form-label, .reaction form { - block-size: var(--btn-size); + block-size: 100%; } + .reaction__delete { display: none; From 3457c871e1a99457d41b03d15f103db8ad4a4e58 Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Thu, 8 Jan 2026 21:07:14 +0100 Subject: [PATCH 13/14] Revert "Add CJK (Chinese, Japanese, Korean) search support" --- app/models/search.rb | 2 - app/models/search/highlighter.rb | 10 +---- app/models/search/query.rb | 2 +- app/models/search/record/sqlite.rb | 8 +--- app/models/search/stemmer.rb | 36 +--------------- test/models/search/highlighter_test.rb | 28 ------------- test/models/search/query_test.rb | 57 -------------------------- test/models/search/stemmer_test.rb | 36 ---------------- 8 files changed, 5 insertions(+), 174 deletions(-) delete mode 100644 test/models/search/query_test.rb diff --git a/app/models/search.rb b/app/models/search.rb index 3b8127ef1..f81b9a9d8 100644 --- a/app/models/search.rb +++ b/app/models/search.rb @@ -1,6 +1,4 @@ module Search - CJK_PATTERN = /\p{Han}|\p{Hiragana}|\p{Katakana}|\p{Hangul}/ - def self.table_name_prefix "search_" end diff --git a/app/models/search/highlighter.rb b/app/models/search/highlighter.rb index 8672ed3c8..d2b53d772 100644 --- a/app/models/search/highlighter.rb +++ b/app/models/search/highlighter.rb @@ -13,14 +13,8 @@ class Search::Highlighter result = text.dup terms.each do |term| - if term.match?(Search::CJK_PATTERN) - result.gsub!(/(#{Regexp.escape(term)})/i) do |match| - "#{OPENING_MARK}#{match}#{CLOSING_MARK}" - end - else - result.gsub!(/\b(#{Regexp.escape(term)}\w*)\b/i) do |match| - "#{OPENING_MARK}#{match}#{CLOSING_MARK}" - end + result.gsub!(/\b(#{Regexp.escape(term)}\w*)\b/i) do |match| + "#{OPENING_MARK}#{match}#{CLOSING_MARK}" end end diff --git a/app/models/search/query.rb b/app/models/search/query.rb index 6bf06ef42..5fe0829e4 100644 --- a/app/models/search/query.rb +++ b/app/models/search/query.rb @@ -33,7 +33,7 @@ class Search::Query < ApplicationRecord end def remove_invalid_search_characters(terms) - terms.gsub(/[^\p{L}\p{N}_"]/, " ") + terms.gsub(/[^\w"]/, " ") end def remove_unbalanced_quotes(terms) diff --git a/app/models/search/record/sqlite.rb b/app/models/search/record/sqlite.rb index 73b3b675f..ae0d34281 100644 --- a/app/models/search/record/sqlite.rb +++ b/app/models/search/record/sqlite.rb @@ -8,10 +8,9 @@ module Search::Record::SQLite has_one :search_records_fts, -> { with_rowid }, class_name: "Search::Record::SQLite::Fts", foreign_key: :rowid, primary_key: :id, dependent: :destroy - before_save :stem_content after_save :upsert_to_fts5_table - scope :matching, ->(query, account_id) { joins(:search_records_fts).where("search_records_fts MATCH ?", Search::Stemmer.stem(query.to_s)) } + scope :matching, ->(query, account_id) { joins(:search_records_fts).where("search_records_fts MATCH ?", query) } end class_methods do @@ -43,11 +42,6 @@ module Search::Record::SQLite end private - def stem_content - self.title = Search::Stemmer.stem(title) if title_changed? - self.content = Search::Stemmer.stem(content) if content_changed? - end - def escape_fts_highlight(html) return nil unless html.present? diff --git a/app/models/search/stemmer.rb b/app/models/search/stemmer.rb index 2ae0e1bf1..f6a6c56d4 100644 --- a/app/models/search/stemmer.rb +++ b/app/models/search/stemmer.rb @@ -5,43 +5,9 @@ module Search::Stemmer def stem(value) if value.present? - tokenize(value).join(" ") + value.gsub(/[^\w\s]/, "").split(/\s+/).map { |word| STEMMER.stem(word.downcase) }.join(" ") else value end end - - private - def tokenize(value) - tokens = [] - current_word = +"" - - value.each_char do |char| - if cjk_character?(char) - if current_word.present? - tokens << stem_word(current_word) - current_word = +"" - end - tokens << char - elsif char =~ /[\p{L}\p{N}_]/ - current_word << char - else - if current_word.present? - tokens << stem_word(current_word) - current_word = +"" - end - end - end - - tokens << stem_word(current_word) if current_word.present? - tokens - end - - def cjk_character?(char) - char.match?(Search::CJK_PATTERN) - end - - def stem_word(word) - STEMMER.stem(word.downcase) - end end diff --git a/test/models/search/highlighter_test.rb b/test/models/search/highlighter_test.rb index 822e4913d..a065c4da1 100644 --- a/test/models/search/highlighter_test.rb +++ b/test/models/search/highlighter_test.rb @@ -82,34 +82,6 @@ class Search::HighlighterTest < ActiveSupport::TestCase assert_equal "<script>#{mark('test')}</script>", result end - test "highlight Chinese characters" do - highlighter = Search::Highlighter.new("测试") - result = highlighter.highlight("这是一个测试文本") - - assert_equal "这是一个#{mark('测试')}文本", result - end - - test "highlight Japanese characters" do - highlighter = Search::Highlighter.new("テスト") - result = highlighter.highlight("これはテストです") - - assert_equal "これは#{mark('テスト')}です", result - end - - test "highlight Korean characters" do - highlighter = Search::Highlighter.new("테스트") - result = highlighter.highlight("이것은 테스트입니다") - - assert_equal "이것은 #{mark('테스트')}입니다", result - end - - test "highlight mixed CJK and English" do - highlighter = Search::Highlighter.new("world 世界") - result = highlighter.highlight("hello world 你好世界") - - assert_equal "hello #{mark('world')} 你好#{mark('世界')}", result - end - private def mark(text) "#{Search::Highlighter::OPENING_MARK}#{text}#{Search::Highlighter::CLOSING_MARK}" diff --git a/test/models/search/query_test.rb b/test/models/search/query_test.rb deleted file mode 100644 index 628b9e69e..000000000 --- a/test/models/search/query_test.rb +++ /dev/null @@ -1,57 +0,0 @@ -require "test_helper" - -class Search::QueryTest < ActiveSupport::TestCase - setup do - @account = accounts(:"37s") - Current.account = @account - end - - test "sanitize preserves ASCII words" do - query = build_query("hello world") - - assert_equal "hello world", query.terms - end - - test "sanitize preserves Chinese characters" do - query = build_query("测试文本") - - assert_equal "测试文本", query.terms - end - - test "sanitize preserves Japanese characters" do - query = build_query("テスト") - - assert_equal "テスト", query.terms - end - - test "sanitize preserves Korean characters" do - query = build_query("테스트") - - assert_equal "테스트", query.terms - end - - test "sanitize preserves mixed CJK and English" do - query = build_query("hello 世界 test") - - assert_equal "hello 世界 test", query.terms - end - - test "sanitize removes special characters but preserves CJK" do - query = build_query("测试@文本") - - assert_equal "测试 文本", query.terms - end - - test "sanitize preserves quoted phrases with CJK" do - query = build_query('"你好世界"') - - assert_equal '"你好世界"', query.terms - end - - private - def build_query(terms) - query = Search::Query.wrap(terms) - query.validate - query - end -end diff --git a/test/models/search/stemmer_test.rb b/test/models/search/stemmer_test.rb index e2963ee10..858ed2dca 100644 --- a/test/models/search/stemmer_test.rb +++ b/test/models/search/stemmer_test.rb @@ -12,40 +12,4 @@ class Search::StemmerTest < ActiveSupport::TestCase assert_equal "test run jump walk", result end - - test "split Chinese characters for FTS indexing" do - result = Search::Stemmer.stem("测试") - - assert_equal "测 试", result - end - - test "split Japanese characters for FTS indexing" do - result = Search::Stemmer.stem("テスト") - - assert_equal "テ ス ト", result - end - - test "split Korean characters for FTS indexing" do - result = Search::Stemmer.stem("테스트") - - assert_equal "테 스 트", result - end - - test "mixed CJK and English" do - result = Search::Stemmer.stem("running 测试 test") - - assert_equal "run 测 试 test", result - end - - test "mixed CJK and English without spaces" do - result = Search::Stemmer.stem("hello世界test") - - assert_equal "hello 世 界 test", result - end - - test "CJK punctuation is treated as separator" do - result = Search::Stemmer.stem("你好。世界") - - assert_equal "你 好 世 界", result - end end From d913ef5b6a2cc4bd59e9f731988cdea6d8adb0a1 Mon Sep 17 00:00:00 2001 From: Jeremy Daer Date: Thu, 8 Jan 2026 12:26:10 -0800 Subject: [PATCH 14/14] Fix that caching should be disabled in dev by default. References 3cf841d4632e589dfe6fd6a205312fc3232c53d4. --- config/environments/development.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/environments/development.rb b/config/environments/development.rb index ace7b503d..05dc335c2 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -26,7 +26,7 @@ Rails.application.configure do config.cache_store = :memory_store config.public_file_server.headers = { "Cache-Control" => "public, max-age=#{2.days.to_i}" } else - config.action_controller.perform_caching = true + config.action_controller.perform_caching = false config.cache_store = :null_store end