diff --git a/frontend/src/app/main/ui/ds/controls/numeric_input.cljs b/frontend/src/app/main/ui/ds/controls/numeric_input.cljs index 7595f8873c..9811013a39 100644 --- a/frontend/src/app/main/ui/ds/controls/numeric_input.cljs +++ b/frontend/src/app/main/ui/ds/controls/numeric_input.cljs @@ -167,6 +167,8 @@ [:on-focus {:optional true} fn?] [:on-detach {:optional true} fn?] [:property {:optional true} :string] + [:tooltip-class {:optional true} + [:maybe :string]] [:tooltip-placement {:optional true} [:maybe [:enum "top" "bottom" "left" "right" "top-right" "bottom-right" "bottom-left" "top-left"]]] [:align {:optional true} [:maybe [:enum :left :right]]]]) @@ -182,7 +184,7 @@ on-change on-change-start on-change-end on-blur on-focus on-detach property align ref name - tooltip-placement text-icon] + tooltip-class tooltip-placement text-icon] :rest props}] (let [;; NOTE: we use mfu/bean here for transparently handle @@ -760,7 +762,7 @@ (when (some? tokens) (mf/html [:> icon-button* {:variant "ghost" :icon i/tokens - :tooltip-class (stl/css :button-tooltip) + :tooltip-class (or tooltip-class (stl/css :button-tooltip)) :class (stl/css :invisible-button) :aria-label token-tooltip :ref open-dropdown-ref @@ -794,6 +796,7 @@ :class inner-class :property property :is-open is-open + :tooltip-class tooltip-class :tooltip-placement tooltip-placement :slot-start (when (or icon text-icon) (mf/html diff --git a/frontend/src/app/main/ui/ds/controls/utilities/token_field.cljs b/frontend/src/app/main/ui/ds/controls/utilities/token_field.cljs index befe593d16..c85735685f 100644 --- a/frontend/src/app/main/ui/ds/controls/utilities/token_field.cljs +++ b/frontend/src/app/main/ui/ds/controls/utilities/token_field.cljs @@ -32,6 +32,8 @@ [:on-token-key-down fn?] [:on-blur {:optional true} fn?] [:on-focus {:optional true} fn?] + [:tooltip-class {:optional true} + [:maybe :string]] [:tooltip-placement {:optional true} [:maybe [:enum "top" "bottom" "left" "right" "top-right" "bottom-right" "bottom-left" "top-left"]]] [:detach-token fn?]]) @@ -39,7 +41,7 @@ (mf/defc token-field* {::mf/schema schema:token-field} [{:keys [id label value slot-start disabled class - on-click on-token-key-down on-blur detach-token tooltip-placement + on-click on-token-key-down on-blur detach-token tooltip-class tooltip-placement token-wrapper-ref token-detach-btn-ref on-focus property is-open token-has-errors]}] (let [set-active? (some? id) @@ -113,7 +115,7 @@ [:> icon-button* {:variant "ghost" :class (stl/css-case :invisible-button true :invisible-btn-dropdown-open is-open) - :tooltip-class (stl/css :button-tooltip) + :tooltip-class (or tooltip-class (stl/css :button-tooltip)) :tooltip-placement tooltip-placement :icon i/broken-link :ref token-detach-btn-ref diff --git a/frontend/test/frontend_tests/ui/ds_controls_numeric_input_test.cljs b/frontend/test/frontend_tests/ui/ds_controls_numeric_input_test.cljs index 9d9a7cd1a3..c0a60be544 100644 --- a/frontend/test/frontend_tests/ui/ds_controls_numeric_input_test.cljs +++ b/frontend/test/frontend_tests/ui/ds_controls_numeric_input_test.cljs @@ -7,7 +7,9 @@ (ns frontend-tests.ui.ds-controls-numeric-input-test (:require [app.common.data :as d] - [app.main.ui.ds.controls.numeric-input :refer [next-focus-index parse-value token-shortcut]] + [app.common.schema :as sm] + [app.main.ui.ds.controls.numeric-input :as numeric-input :refer [next-focus-index parse-value token-shortcut]] + [app.main.ui.ds.controls.utilities.token-field :as token-field] [app.main.ui.formats :as fmt] [cljs.test :as t :include-macros true])) @@ -134,3 +136,37 @@ (t/testing "works with nil focused-id (no current selection)" (t/is (= 0 (next-focus-index sample-options nil :down))))) + +;; Regression pins for the React `tooltipClass` unknown-prop warning: +;; `numeric-input*` receives `:tooltip-class` from callers such as the +;; layout-item menus (via `numeric-input-wrapper*`). The prop must be +;; declared in the schema and destructured by the component, so it never +;; stays in the `:rest` props that are spread onto the inner `input-field*` +;; DOM ``. `:tooltip-placement` already follows this pattern; +;; `:tooltip-class` mirrors it. The same holds for `token-field*`, which +;; forwards the class to its detach-button `icon-button*`. + +(t/deftest test-numeric-input-schema-accepts-tooltip-class + (let [schema @#'numeric-input/schema:numeric-input] + (t/testing "absent tooltip-class stays valid" + (t/is (true? (sm/validate schema {})))) + (t/testing "string tooltip-class is accepted" + (t/is (true? (sm/validate schema {:tooltip-class "my-tooltip"})))) + (t/testing "nil tooltip-class is accepted" + (t/is (true? (sm/validate schema {:tooltip-class nil})))) + (t/testing "non-string tooltip-class is rejected" + (t/is (false? (sm/validate schema {:tooltip-class 42})))))) + +(t/deftest test-token-field-schema-accepts-tooltip-class + (let [schema @#'token-field/schema:token-field + base {:value "10" + :on-token-key-down (fn [_]) + :detach-token (fn [_])}] + (t/testing "absent tooltip-class stays valid" + (t/is (true? (sm/validate schema base)))) + (t/testing "string tooltip-class is accepted" + (t/is (true? (sm/validate schema (assoc base :tooltip-class "my-tooltip"))))) + (t/testing "nil tooltip-class is accepted" + (t/is (true? (sm/validate schema (assoc base :tooltip-class nil))))) + (t/testing "non-string tooltip-class is rejected" + (t/is (false? (sm/validate schema (assoc base :tooltip-class 42)))))))