diff --git a/app/javascript/controllers/form_controller.js b/app/javascript/controllers/form_controller.js
index f917bd092..beca1f08f 100644
--- a/app/javascript/controllers/form_controller.js
+++ b/app/javascript/controllers/form_controller.js
@@ -8,10 +8,21 @@ export default class extends Controller {
debounceTimeout: { type: Number, default: 300 }
}
+ #isComposing = false
+
initialize() {
this.debouncedSubmit = debounce(this.debouncedSubmit.bind(this), this.debounceTimeoutValue)
}
+ // IME Composition tracking
+ compositionStart() {
+ this.#isComposing = true
+ }
+
+ compositionEnd() {
+ this.#isComposing = false
+ }
+
submit() {
this.element.requestSubmit()
}
@@ -32,6 +43,12 @@ export default class extends Controller {
}
}
+ preventComposingSubmit(event) {
+ if (this.#isComposing) {
+ event.preventDefault()
+ }
+ }
+
debouncedSubmit(event) {
this.submit(event)
}
diff --git a/app/javascript/controllers/navigable_list_controller.js b/app/javascript/controllers/navigable_list_controller.js
index 4af794c4b..bd5e87665 100644
--- a/app/javascript/controllers/navigable_list_controller.js
+++ b/app/javascript/controllers/navigable_list_controller.js
@@ -245,6 +245,9 @@ export default class extends Controller {
}
},
Enter(event) {
+ // Skip handling during IME composition (e.g., Japanese input)
+ if (event.isComposing) { return }
+
if (event.shiftKey) {
this.#toggleCurrentItem(event)
} else {
diff --git a/app/views/cards/comments/reactions/new.html.erb b/app/views/cards/comments/reactions/new.html.erb
index 38c6daf98..8cc5dda73 100644
--- a/app/views/cards/comments/reactions/new.html.erb
+++ b/app/views/cards/comments/reactions/new.html.erb
@@ -2,14 +2,14 @@
<%= form_with model: [ @comment.card, @comment, Reaction.new ],
class: "reaction reaction__form expanded",
html: { aria: { label: "New reaction" } },
- data: { controller: "form reaction-emoji", turbo_frame: dom_id(@comment, :reacting), action: "keydown.esc->form#cancel submit->form#preventEmptySubmit" } do |form| %>
+ data: { controller: "form reaction-emoji", turbo_frame: dom_id(@comment, :reacting), action: "keydown.esc->form#cancel submit->form#preventEmptySubmit submit->form#preventComposingSubmit" } do |form| %>
<%= render "cards/comments/reactions/menu", comment: @comment %>
diff --git a/app/views/cards/display/perma/_steps.html.erb b/app/views/cards/display/perma/_steps.html.erb
index 36ce68fc5..9f65dec2a 100644
--- a/app/views/cards/display/perma/_steps.html.erb
+++ b/app/views/cards/display/perma/_steps.html.erb
@@ -4,8 +4,8 @@
<% unless card.closed? %>
- <%= form_with model: [card, Step.new], url: card_steps_path(card), class: "min-width", data: { controller: "form", action: "submit->form#preventEmptySubmit turbo:submit-end->form#reset" } do |form| %>
- <%= form.text_field :content, class: "input step__content hide-focus-ring", placeholder: "Add a step…", autocomplete: "off", data: { form_target: "input", "1p-ignore": "true" }, aria: { label: "Add a step" } %>
+ <%= form_with model: [card, Step.new], url: card_steps_path(card), class: "min-width", data: { controller: "form", action: "submit->form#preventEmptySubmit submit->form#preventComposingSubmit turbo:submit-end->form#reset" } do |form| %>
+ <%= form.text_field :content, class: "input step__content hide-focus-ring", placeholder: "Add a step…", autocomplete: "off", data: { form_target: "input", "1p-ignore": "true", action: "compositionstart->form#compositionStart compositionend->form#compositionEnd" }, aria: { label: "Add a step" } %>
<% end %>
<% end %>
diff --git a/app/views/cards/taggings/new.html.erb b/app/views/cards/taggings/new.html.erb
index 644b29d2b..b8ff47df6 100644
--- a/app/views/cards/taggings/new.html.erb
+++ b/app/views/cards/taggings/new.html.erb
@@ -11,10 +11,10 @@
<%= form_with url: card_taggings_path(@card),
id: dom_id(@card, :tags_form),
- data: { controller: "form", action: "submit->form#preventEmptySubmit" },
+ data: { controller: "form", action: "submit->form#preventEmptySubmit submit->form#preventComposingSubmit" },
class: "flex flex-column gap-half full-width margin-block-half" do |form| %>
<%= form.text_field :tag_title, placeholder: @tags.any? ? "Add a new tag or filter…" : "Name this tag…", class: "input txt-small full-width",
- autocomplete: "off", autofocus: true, data: { filter_target: "input", form_target: "input", action: "input->filter#filter" } %>
+ autocomplete: "off", autofocus: true, data: { filter_target: "input", form_target: "input", action: "input->filter#filter compositionstart->form#compositionStart compositionend->form#compositionEnd" } %>
<% end %>