diff --git a/deps/shui/src/logseq/shui/shortcut.cljs b/deps/shui/src/logseq/shui/shortcut.cljs index 7b7211ac0c..4cf55d2c66 100644 --- a/deps/shui/src/logseq/shui/shortcut.cljs +++ b/deps/shui/src/logseq/shui/shortcut.cljs @@ -270,7 +270,8 @@ (rum/defc chord-sequence-keys "Renders a chord sequence (multi-step key combinations) with 'then' separators. E.g., [['⌘' 'c'] ['⌘' 'r']] renders as: [⌘ C] then [⌘ R]" - [groups binding {:keys [aria-label aria-hidden? glow?]}] + [groups binding {:keys [aria-label aria-hidden? glow? chord-separator] + :or {chord-separator "then"}}] (let [normalized-binding (normalize-binding binding) container-attrs (cond-> {:class "shui-shortcut-chord" :data-shortcut-binding normalized-binding @@ -288,7 +289,7 @@ {:key (str "chord-sep-" gi) :style {:font-size "10px" :opacity 0.45}} - "then"]) + chord-separator]) (let [key-elements (map print-shortcut-key group)] [:span {:key (str "chord-group-" gi) @@ -315,7 +316,7 @@ - :glow? - if true, adds inner glow effect to combo/separate keys (default: true) - :raw-binding - raw binding format for data-shortcut-binding (for animation matching). If not provided, will normalize from shortcut prop." - [shortcut & {:keys [style aria-label aria-hidden? glow? raw-binding] + [shortcut & {:keys [style aria-label aria-hidden? glow? raw-binding chord-separator] :or {style :auto aria-hidden? false glow? true}}] @@ -327,9 +328,10 @@ [shortcut] ; single shortcut string shortcut)) ; multiple shortcuts (parse-shortcuts shortcut)) - opts {:aria-label aria-label - :aria-hidden? aria-hidden? - :glow? glow?}] + opts (cond-> {:aria-label aria-label + :aria-hidden? aria-hidden? + :glow? glow?} + chord-separator (assoc :chord-separator chord-separator))] (for [[index binding] (map-indexed vector shortcuts)] (let [;; Chord sequence: multiple nested groups like [["⌘" "c"] ["⌘" "r"]] chord-sequence? (and (coll? binding) diff --git a/src/main/frontend/components/shortcut.cljs b/src/main/frontend/components/shortcut.cljs index c9dfa97308..f2fe6d96bd 100644 --- a/src/main/frontend/components/shortcut.cljs +++ b/src/main/frontend/components/shortcut.cljs @@ -102,7 +102,6 @@ ;; Esc: close the popup is-esc? (do (.stopPropagation e) - (clear!) (close-fn)) ;; Backspace during accumulation: remove last key from sequence @@ -178,23 +177,23 @@ (ui/icon "x" {:size 12})]]) ;; Placeholder (when-not has-keystroke? - [:span.shortcut-input-placeholder "Press keys to filter\u2026"])] + [:span.shortcut-input-placeholder (t :keymap/press-keys-to-filter)])] ;; SEPARATOR + TOOLBAR (shui/separator) [:div.shortcut-toolbar [:div (when has-keystroke? - [:button.shortcut-toolbar-action + [:button.shortcut-toolbar-action.shortcut-toolbar-reset {:on-click clear!} (ui/icon "rotate" {:size 12}) - [:span "Clear"]])] + [:span (t :keymap/clear)]])] [:div.flex.items-center (when has-keystroke? [:span.shortcut-toolbar-hint - "Remove " (shui/shortcut "backspace" {:style :compact})]) + (t :keymap/hint-remove) (shui/shortcut "backspace" {:style :compact})]) [:span.shortcut-toolbar-hint - "Close " (shui/shortcut "escape" {:style :compact})]]]])) + (t :keymap/hint-close) (shui/shortcut "escape" {:style :compact})]]]])) (rum/defc pane-controls [q set-q! filter-key set-filter-key! keystroke set-keystroke! toggle-categories-fn pill-counts] @@ -207,7 +206,7 @@ [:span.search-input-wrap [:span.search-icon (ui/icon "search" {:size 15})] [:input.form-input.is-small - {:placeholder "Search shortcuts..." + {:placeholder (t :keymap/search-placeholder) :ref *search-ref :value (or q "") :auto-focus true @@ -264,7 +263,7 @@ [:button.shortcut-keystroke-inactive {:on-click open-filter!} (ui/icon "keyboard" {:size 14}) - [:span "Search by keys"]]))] + [:span (t :keymap/search-by-keys)]]))] ;; Row 2: filter pills + fold + refresh [:div.shortcut-pills-row @@ -273,7 +272,12 @@ :let [active? (or (and (= k :All) (nil? filter-key)) (= filter-key k)) cnt (get pill-counts k 0) - title (if (= k :All) "All" (name k))]] + title (case k + :All (t :keymap/all) + :Custom (t :keymap/custom) + :Unset (t :keymap/unset) + :Disabled (t :keymap/disabled) + (name k))]] [:button.shortcut-filter-pill {:key (name k) :class (when active? "shortcut-filter-pill--active") @@ -653,7 +657,7 @@ (for [[idx x] (map-indexed vector current-binding) :when (string? x)] [:div.shortcut-input-binding {:key x} - (shui/shortcut x) + (shui/shortcut x {:chord-separator (t :keymap/chord-separator)}) (when (#{:idle :accepted :esc-hint :removed :reset} rec-state) [:button.shortcut-binding-remove {:aria-label "Remove binding" @@ -681,7 +685,7 @@ (ui/icon "x" {:size 12})])]) ;; Placeholder (when (#{:idle :recording :accepted :removed :reset} rec-state) - [:span.shortcut-input-placeholder "Press a shortcut\u2026"])] + [:span.shortcut-input-placeholder (t :keymap/press-a-shortcut)])] ;; FEEDBACK BANNER (conditional) (let [undo-link @@ -693,56 +697,56 @@ (set-current-binding! (:previous-binding own))) (set-undo-snapshot! nil) (set-rec-state! :idle))} - "Undo"])] + (t :keymap/undo)])] (case rec-state :conflict-cross [:div.shortcut-feedback.shortcut-feedback--error - [:span "Used by " + [:span (t :keymap/used-by) [:span.shortcut-feedback-name (str "\u201c" (conflict-action-names key-conflicts) "\u201d")]] (ui/tooltip (shui/button {:variant :destructive :size :xs :on-click override-fn!} - "Reassign") - "Remove from the other action and assign here")] + (t :keymap/reassign)) + (t :keymap/reassign-tooltip))] :conflict-same [:div.shortcut-feedback.shortcut-feedback--error - [:span "Already bound to this action"]] + [:span (t :keymap/already-bound)]] :accepted (cond (:cross-context? accepted-info) [:div.shortcut-feedback.shortcut-feedback--warning - [:span "Also used for " + [:span (t :keymap/also-used-for) [:span.shortcut-feedback-name (str "\u201c" (:cross-action-name accepted-info) "\u201d")] (when-let [ctx (:cross-context-label accepted-info)] - (str " in " ctx))]] + (str (t :keymap/in-context) ctx))]] (:from accepted-info) [:div.shortcut-feedback.shortcut-feedback--success - [:span "Reassigned from " + [:span (t :keymap/reassigned-from) [:span.shortcut-feedback-name (str "\u201c" (:from accepted-info) "\u201d")]] undo-link] :else [:div.shortcut-feedback.shortcut-feedback--success - [:span "Shortcut added"]]) + [:span (t :keymap/shortcut-added)]]) :removed [:div.shortcut-feedback.shortcut-feedback--muted - [:span "Shortcut removed"] + [:span (t :keymap/shortcut-removed)] undo-link] :reset [:div.shortcut-feedback.shortcut-feedback--muted - [:span "Reset to default"] + [:span (t :keymap/reset-to-default)] undo-link] :esc-hint [:div.shortcut-feedback.shortcut-feedback--muted - [:span "Esc is reserved"]] + [:span (t :keymap/esc-is-reserved)]] nil)) @@ -756,22 +760,22 @@ [:button.shortcut-toolbar-action.shortcut-toolbar-reset {:on-click reset-fn!} (ui/icon "rotate" {:size 12}) - [:span "Reset"]])] + [:span (t :keymap/reset)]])] [:div.shortcut-toolbar-right ;; Reassign hint (conflict-cross only) (when (= :conflict-cross rec-state) [:span.shortcut-toolbar-hint - "Reassign " + (t :keymap/hint-reassign) (shui/shortcut (if util/mac? "meta+enter" "ctrl+enter") {:style :compact})]) ;; Remove hint (idle/accepted/removed/reset with bindings, or conflict states) (when (or (and (#{:idle :accepted :removed :reset} rec-state) has-bindings?) (#{:conflict-cross :conflict-same} rec-state)) [:span.shortcut-toolbar-hint - "Remove " + (t :keymap/hint-remove) (shui/shortcut "backspace" {:style :compact})]) ;; Close/Cancel hint [:span.shortcut-toolbar-hint - (if (= :recording rec-state) "Cancel " "Close ") + (if (= :recording rec-state) (t :keymap/hint-cancel) (t :keymap/hint-close)) (shui/shortcut "escape" {:style :compact})]]]])) (defn- classify-shortcut @@ -913,7 +917,7 @@ (when (and ready? no-results?) [:div.shortcut-empty-state (ui/icon "list-search" {:size 24}) - [:span.text-sm "No matching shortcuts"]]) + [:span.text-sm (t :keymap/no-matching-shortcuts)]]) (when (and ready? (not no-results?)) [:ul.list-none.m-0.py-3 @@ -988,11 +992,12 @@ (for [b user-binding :when (string? b)] [:span {:key b :style {:display "contents"}} - (shui/shortcut b)]))] + (shui/shortcut b {:chord-separator (t :keymap/chord-separator)})]))] :else (for [b binding :when (string? b)] [:span {:key b :style {:display "contents"}} (shui/shortcut (dh/binding-for-display id b) - {:raw-binding [b]})]))]])))))])])]])) + {:raw-binding [b] + :chord-separator (t :keymap/chord-separator)})]))]])))))])])]])) diff --git a/src/resources/dicts/en.edn b/src/resources/dicts/en.edn index 07f433a4c0..bee499acc8 100644 --- a/src/resources/dicts/en.edn +++ b/src/resources/dicts/en.edn @@ -401,6 +401,30 @@ :keymap/restore-to-default "Restore to the default" :keymap/customize-for-label "Customize shortcuts" :keymap/conflicts-for-label "Keymap conflicts for" + :keymap/search-placeholder "Search shortcuts..." + :keymap/search-by-keys "Search by keys" + :keymap/press-keys-to-filter "Press keys to filter\u2026" + :keymap/press-a-shortcut "Press a shortcut\u2026" + :keymap/clear "Clear" + :keymap/reset "Reset" + :keymap/undo "Undo" + :keymap/reassign "Reassign" + :keymap/reassign-tooltip "Remove from the other action and assign here" + :keymap/used-by "Used by " + :keymap/already-bound "Already bound to this action" + :keymap/also-used-for "Also used for " + :keymap/in-context " in " + :keymap/reassigned-from "Reassigned from " + :keymap/shortcut-added "Shortcut added" + :keymap/shortcut-removed "Shortcut removed" + :keymap/reset-to-default "Reset to default" + :keymap/esc-is-reserved "Esc is reserved" + :keymap/no-matching-shortcuts "No matching shortcuts" + :keymap/chord-separator "then" + :keymap/hint-remove "Remove " + :keymap/hint-close "Close " + :keymap/hint-cancel "Cancel " + :keymap/hint-reassign "Reassign " :window/minimize "Minimize" :window/maximize "Maximize"