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 e09200febe..518d98a80c 100644 --- a/frontend/src/app/main/ui/ds/controls/numeric_input.cljs +++ b/frontend/src/app/main/ui/ds/controls/numeric_input.cljs @@ -25,6 +25,7 @@ [app.util.keyboard :as kbd] [app.util.object :as obj] [app.util.simple-math :as smt] + [app.util.timers :as ts] [cuerdas.core :as str] [goog.events :as events] [rumext.v2 :as mf] @@ -382,7 +383,11 @@ (reset! focused-id* nil) (reset! is-open* false) (reset! token-applied* name) - (apply-token value name))) + (apply-token value name) + (ts/schedule-on-idle + (fn [] + (when token-wrapper-ref + (dom/focus! (mf/ref-val token-wrapper-ref))))))) on-option-click (mf/use-fn @@ -416,14 +421,16 @@ (fn [event] (let [target (dom/get-related-target event) self-node (mf/ref-val wrapper-ref)] + (when-not (dom/is-child? self-node target) (reset! filter-id* "") (reset! focused-id* nil) (reset! is-open* false))) + (when (mf/ref-val dirty-ref) - (apply-value (mf/ref-val raw-value*)) - (when (fn? on-blur) - (on-blur event))))) + (apply-value (mf/ref-val raw-value*))) + (when (fn? on-blur) + (on-blur event)))) on-key-down (mf/use-fn @@ -560,9 +567,11 @@ (reset! token-applied* nil) (reset! selected-id* nil) (reset! focused-id* nil) - (dom/focus! (mf/ref-val ref)) (when on-detach - (on-detach token)))))) + (on-detach token)) + (ts/schedule-on-idle + (fn [] + (dom/focus! (mf/ref-val ref)))))))) on-token-key-down (mf/use-fn @@ -656,6 +665,7 @@ :label label :value token-value :on-click open-dropdown-token + :on-focus on-focus :on-token-key-down on-token-key-down :disabled disabled :on-blur on-blur 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 128bcb8397..b644899ea9 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 @@ -27,13 +27,14 @@ [:on-click {:optional true} fn?] [:on-token-key-down fn?] [:on-blur {:optional true} fn?] + [:on-focus {:optional true} fn?] [:detach-token fn?]]) (mf/defc token-field* {::mf/schema schema:token-field} [{:keys [id label value slot-start disabled on-click on-token-key-down on-blur detach-token - token-wrapper-ref token-detach-btn-ref]}] + token-wrapper-ref token-detach-btn-ref on-focus]}] (let [set-active? (some? id) content (if set-active? label @@ -60,6 +61,7 @@ :on-key-down on-token-key-down :ref token-wrapper-ref :on-blur on-blur + :on-focus on-focus :tab-index (if disabled -1 0)} (when (some? slot-start) slot-start) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options.cljs b/frontend/src/app/main/ui/workspace/sidebar/options.cljs index b5c0480773..944996a3d8 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options.cljs @@ -143,6 +143,7 @@ edit-grid? [:& layout-container/grid-layout-edition {:ids [edition] + :shapes shapes :values (get objects edition)}] (some? sp-panel) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs index bcc4f928ec..a7e8eb32c9 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs @@ -11,19 +11,24 @@ [app.common.data.macros :as dm] [app.common.math :as mth] [app.common.types.shape.layout :as ctl] + [app.common.types.token :as tk] [app.config :as cf] [app.main.data.event :as-alias ev] [app.main.data.workspace :as udw] [app.main.data.workspace.grid-layout.editor :as dwge] [app.main.data.workspace.shape-layout :as dwsl] + [app.main.data.workspace.tokens.application :as dwta] + [app.main.features :as features] [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.components.dropdown :refer [dropdown]] - [app.main.ui.components.numeric-input :refer [numeric-input*]] + [app.main.ui.components.numeric-input :as deprecated-input] [app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]] [app.main.ui.components.select :refer [select]] [app.main.ui.components.title-bar :refer [title-bar*]] + [app.main.ui.context :as muc] [app.main.ui.ds.buttons.icon-button :refer [icon-button*]] + [app.main.ui.ds.controls.numeric-input :refer [numeric-input*]] [app.main.ui.ds.foundations.assets.icon :as i] [app.main.ui.formats :as fmt] [app.main.ui.hooks :as h] @@ -42,6 +47,44 @@ :column deprecated-icon/column :column-reverse deprecated-icon/column-reverse)) + +(mf/defc numeric-input-wrapper* + {::mf/private true} + [{:keys [values name applied-tokens align on-detach] :rest props}] + (let [tokens (mf/use-ctx muc/active-tokens-by-type) + input-type (cond + (some #{:p2 :p4} [name]) + :horizontal-padding + + (some #{:p1 :p3} [name]) + :vertical-padding + :else + name) + + tokens (mf/with-memo [tokens input-type] + (delay + (-> (deref tokens) + (select-keys (get tk/tokens-by-input input-type)) + (not-empty)))) + on-detach-attr + (mf/use-fn + (mf/deps on-detach name) + #(on-detach % name)) + + props (mf/spread-props props + {:placeholder (if (or (= :multiple (:applied-tokens values)) + (= :multiple (get values name)) + (nil? (get values name))) + (tr "settings.multiple") + "--") + :class (stl/css :numeric-input-measures) + :applied-token (get applied-tokens name) + :tokens tokens + :align align + :on-detach on-detach-attr + :value (get values name)})] + [:> numeric-input* props])) + ;; FLEX COMPONENTS (def layout-container-flex-attrs @@ -296,10 +339,12 @@ [_event] (select-padding false false false false)) -(mf/defc simple-padding-selection - {::mf/props :obj} - [{:keys [value on-change]}] - (let [p1 (:p1 value) +(mf/defc simple-padding-selection* + [{:keys [value on-change shapes applied-tokens ids]}] + (let [token-numeric-inputs + (features/use-feature "tokens/numeric-input") + + p1 (:p1 value) p2 (:p2 value) p3 (:p3 value) p4 (:p4 value) @@ -314,150 +359,296 @@ p2 nil) + applied-to-p1 (:p1 applied-tokens) + applied-to-p2 (:p2 applied-tokens) + applied-to-p3 (:p3 applied-tokens) + applied-to-p4 (:p4 applied-tokens) + + applied-to-p1 (if (= applied-to-p1 applied-to-p3) + applied-to-p1 + nil) + + applied-to-p2 (if (= applied-to-p2 applied-to-p4) + applied-to-p2 + nil) on-change' (mf/use-fn - (mf/deps on-change) - (fn [value event] - (let [attr (-> (dom/get-current-target event) - (dom/get-data "attr") - (keyword))] - (on-change :simple attr value event)))) + (mf/deps on-change shapes) + (fn [value attr event] + (if (or (string? value) (int? value)) + (on-change :simple attr value event) + (do + (let [resolved-value (:resolved-value (first value))] + (st/emit! (dwta/toggle-token {:token (first value) + :attrs #{attr} + :shapes shapes})) + (on-change :simple attr resolved-value event)))))) + + on-detach-token + (mf/use-fn + (mf/deps ids) + (fn [token attr] + (st/emit! (dwta/unapply-token {:token (first token) + :attributes #{attr} + :shape-ids ids})))) on-focus (mf/use-fn - (fn [event] - (let [attr (-> (dom/get-current-target event) - (dom/get-data "attr") - (keyword))] + (mf/deps select-padding) + (fn [attr event] + (case attr + :p1 (select-padding true false true false) + :p2 (select-padding false true false true)) - (case attr - :p1 (select-padding true false true false) - :p2 (select-padding false true false true)) + (dom/select-target event))) - (dom/select-target event))))] + on-focus-p1 + (mf/use-fn (mf/deps on-focus) #(on-focus :p1)) + + on-focus-p2 + (mf/use-fn (mf/deps on-focus) #(on-focus :p2)) + + on-p1-change + (mf/use-fn (mf/deps on-change') #(on-change' % :p1)) + + on-p2-change + (mf/use-fn (mf/deps on-change') #(on-change' % :p2))] [:div {:class (stl/css :paddings-simple)} - [:div {:class (stl/css :padding-simple) - :title (tr "workspace.layout_grid.editor.padding.vertical")} - [:span {:class (stl/css :icon)} - deprecated-icon/padding-top-bottom] - [:> numeric-input* - {:class (stl/css :numeric-input) - :placeholder (tr "settings.multiple") - :aria-label (tr "workspace.layout_grid.editor.padding.vertical") - :data-attr "p1" - :on-change on-change' - :on-focus on-focus - :nillable true - :min 0 - :value p1}]] - [:div {:class (stl/css :padding-simple) - :title (tr "workspace.layout_grid.editor.padding.horizontal")} + (if token-numeric-inputs + [:> numeric-input-wrapper* + {:on-change on-p1-change + :on-detach on-detach-token + :on-blur on-padding-blur + :on-focus on-focus-p1 + :icon i/padding-top-bottom + :min 0 + :name :p1 + :property (tr "workspace.layout_grid.editor.padding.vertical") + :nillable true + :applied-tokens {:p1 applied-to-p1} + :values {:p1 p1}}] - [:span {:class (stl/css :icon)} - deprecated-icon/padding-left-right] - [:> numeric-input* - {:className (stl/css :numeric-input) - :placeholder (tr "settings.multiple") - :aria-label (tr "workspace.layout_grid.editor.padding.horizontal") - :data-attr "p2" - :on-change on-change' - :on-focus on-focus - :on-blur on-padding-blur - :min 0 - :nillable true - :value p2}]]])) + [:div {:class (stl/css :padding-simple) + :title (tr "workspace.layout_grid.editor.padding.vertical")} + [:span {:class (stl/css :icon)} + deprecated-icon/padding-top-bottom] + [:> deprecated-input/numeric-input* + {:class (stl/css :numeric-input) + :placeholder (tr "settings.multiple") + :aria-label (tr "workspace.layout_grid.editor.padding.vertical") + :on-change on-p1-change + :on-focus on-focus-p1 + :on-blur on-padding-blur + :nillable true + :min 0 + :value p1}]]) -(mf/defc multiple-padding-selection - {::mf/props :obj} - [{:keys [value on-change]}] - (let [p1 (:p1 value) + (if token-numeric-inputs + [:> numeric-input-wrapper* + {:on-change on-p2-change + :on-detach on-detach-token + :on-blur on-padding-blur + :on-focus on-focus-p2 + :icon i/padding-left-right + :min 0 + :name :p2 + :property (tr "workspace.layout_grid.editor.padding.horizontal") + :nillable true + :applied-tokens {:p2 applied-to-p2} + :values {:p2 p2}}] + + [:div {:class (stl/css :padding-simple) + :title (tr "workspace.layout_grid.editor.padding.horizontal")} + [:span {:class (stl/css :icon)} + deprecated-icon/padding-left-right] + [:> deprecated-input/numeric-input* + {:className (stl/css :numeric-input) + :placeholder (tr "settings.multiple") + :aria-label (tr "workspace.layout_grid.editor.padding.horizontal") + :on-change on-p2-change + :on-focus on-focus-p2 + :on-blur on-padding-blur + :min 0 + :nillable true + :value p2}]])])) + +(mf/defc multiple-padding-selection* + [{:keys [value on-change shapes applied-tokens ids]}] + (let [token-numeric-inputs + (features/use-feature "tokens/numeric-input") + + p1 (:p1 value) p2 (:p2 value) p3 (:p3 value) p4 (:p4 value) on-change' (mf/use-fn - (mf/deps on-change) - (fn [value event] - (let [attr (-> (dom/get-current-target event) - (dom/get-data "attr") - (keyword))] - (on-change :multiple attr value event)))) + (mf/deps on-change shapes) + (fn [value attr event] + (if (or (string? value) (int? value)) + (on-change :multiple attr value event) + (do + (let [resolved-value (:resolved-value (first value))] + (st/emit! (dwta/toggle-token {:token (first value) + :attrs #{attr} + :shapes shapes})) + (on-change :multiple attr resolved-value event)))))) on-focus (mf/use-fn - (fn [event] - (let [attr (-> (dom/get-current-target event) - (dom/get-data "attr") - (keyword))] + (mf/deps select-padding) + (fn [attr event] + (select-padding attr) + (dom/select-target event))) - (select-padding attr) - (dom/select-target event))))] + on-detach-token + (mf/use-fn + (mf/deps ids) + (fn [token attr] + (st/emit! (dwta/unapply-token {:token (first token) + :attributes #{attr} + :shape-ids ids})))) + + on-p1-change + (mf/use-fn (mf/deps on-change') #(on-change' % :p1)) + + on-p2-change + (mf/use-fn (mf/deps on-change') #(on-change' % :p2)) + + on-p3-change + (mf/use-fn (mf/deps on-change') #(on-change' % :p3)) + + on-p4-change + (mf/use-fn (mf/deps on-change') #(on-change' % :p4)) + + on-focus-p1 + (mf/use-fn (mf/deps on-focus) #(on-focus :p1)) + + on-focus-p2 + (mf/use-fn (mf/deps on-focus) #(on-focus :p2)) + + on-focus-p3 + (mf/use-fn (mf/deps on-focus) #(on-focus :p3)) + + on-focus-p4 + (mf/use-fn (mf/deps on-focus) #(on-focus :p4))] [:div {:class (stl/css :paddings-multiple)} - [:div {:class (stl/css :padding-multiple) - :title (tr "workspace.layout_grid.editor.padding.top")} - [:span {:class (stl/css :icon)} - deprecated-icon/padding-top] - [:> numeric-input* - {:class (stl/css :numeric-input) - :placeholder "--" - :aria-label (tr "workspace.layout_grid.editor.padding.top") - :data-attr "p1" - :on-change on-change' - :on-focus on-focus - :on-blur on-padding-blur - :min 0 - :value p1}]] + (if token-numeric-inputs + [:> numeric-input-wrapper* + {:on-change on-p1-change + :on-detach on-detach-token + :on-blur on-padding-blur + :on-focus on-focus-p1 + :icon i/padding-top + :min 0 + :name :p1 + :property (tr "workspace.layout_grid.editor.padding.top") + :applied-tokens applied-tokens + :values value}] - [:div {:class (stl/css :padding-multiple) - :title (tr "workspace.layout_grid.editor.padding.right")} - [:span {:class (stl/css :icon)} - deprecated-icon/padding-right] - [:> numeric-input* - {:class (stl/css :numeric-input) - :placeholder "--" - :aria-label (tr "workspace.layout_grid.editor.padding.right") - :data-attr "p2" - :on-change on-change' - :on-focus on-focus - :on-blur on-padding-blur - :min 0 - :value p2}]] + [:div {:class (stl/css :padding-multiple) + :title (tr "workspace.layout_grid.editor.padding.top")} + [:span {:class (stl/css :icon)} + deprecated-icon/padding-top] + [:> deprecated-input/numeric-input* + {:class (stl/css :numeric-input) + :placeholder "--" + :aria-label (tr "workspace.layout_grid.editor.padding.top") + :data-attr "p1" + :on-change on-p1-change + :on-focus on-focus-p1 + :on-blur on-padding-blur + :min 0 + :value p1}]]) - [:div {:class (stl/css :padding-multiple) - :title (tr "workspace.layout_grid.editor.padding.bottom")} - [:span {:class (stl/css :icon)} - deprecated-icon/padding-bottom] - [:> numeric-input* - {:class (stl/css :numeric-input) - :placeholder "--" - :aria-label (tr "workspace.layout_grid.editor.padding.bottom") - :data-attr "p3" - :on-change on-change' - :on-focus on-focus - :on-blur on-padding-blur - :min 0 - :value p3}]] + (if token-numeric-inputs + [:> numeric-input-wrapper* + {:on-change on-p2-change + :on-detach on-detach-token + :on-blur on-padding-blur + :on-focus on-focus-p2 + :icon i/padding-right + :min 0 + :name :p2 + :property (tr "workspace.layout_grid.editor.padding.right") + :applied-tokens applied-tokens + :values value}] - [:div {:class (stl/css :padding-multiple) - :title (tr "workspace.layout_grid.editor.padding.left")} - [:span {:class (stl/css :icon)} - deprecated-icon/padding-left] - [:> numeric-input* - {:class (stl/css :numeric-input) - :placeholder "--" - :aria-label (tr "workspace.layout_grid.editor.padding.left") - :data-attr "p4" - :on-change on-change' - :on-focus on-focus - :on-blur on-padding-blur - :min 0 - :value p4}]]])) + [:div {:class (stl/css :padding-multiple) + :title (tr "workspace.layout_grid.editor.padding.right")} + [:span {:class (stl/css :icon)} + deprecated-icon/padding-right] + [:> deprecated-input/numeric-input* + {:class (stl/css :numeric-input) + :placeholder "--" + :aria-label (tr "workspace.layout_grid.editor.padding.right") + :data-attr "p2" + :on-change on-p2-change + :on-focus on-focus-p2 + :on-blur on-padding-blur + :min 0 + :value p2}]]) -(mf/defc padding-section - {::mf/props :obj} + (if token-numeric-inputs + [:> numeric-input-wrapper* + {:on-change on-p3-change + :on-detach on-detach-token + :on-blur on-padding-blur + :on-focus on-focus-p3 + :icon i/padding-bottom + :min 0 + :name :p3 + :property (tr "workspace.layout_grid.editor.padding.bottom") + :applied-tokens applied-tokens + :values value}] + + [:div {:class (stl/css :padding-multiple) + :title (tr "workspace.layout_grid.editor.padding.bottom")} + [:span {:class (stl/css :icon)} + deprecated-icon/padding-bottom] + [:> deprecated-input/numeric-input* + {:class (stl/css :numeric-input) + :placeholder "--" + :aria-label (tr "workspace.layout_grid.editor.padding.bottom") + :data-attr "p3" + :on-change on-p3-change + :on-focus on-focus-p3 + :on-blur on-padding-blur + :min 0 + :value p3}]]) + + (if token-numeric-inputs + [:> numeric-input-wrapper* + {:on-change on-p4-change + :on-detach on-detach-token + :on-blur on-padding-blur + :on-focus on-focus-p4 + :icon i/padding-left + :min 0 + :name :p4 + :property (tr "workspace.layout_grid.editor.padding.left") + :applied-tokens applied-tokens + :values value}] + + [:div {:class (stl/css :padding-multiple) + :title (tr "workspace.layout_grid.editor.padding.left")} + [:span {:class (stl/css :icon)} + deprecated-icon/padding-left] + [:> deprecated-input/numeric-input* + {:class (stl/css :numeric-input) + :placeholder "--" + :aria-label (tr "workspace.layout_grid.editor.padding.left") + :data-attr "p4" + :on-change on-p4-change + :on-focus on-focus-p4 + :on-blur on-padding-blur + :min 0 + :value p4}]])])) + +(mf/defc padding-section* [{:keys [type on-type-change on-change] :as props}] (let [on-type-change' (mf/use-fn @@ -479,10 +670,10 @@ [:div {:class (stl/css :padding-inputs)} (cond (= type :simple) - [:> simple-padding-selection props] + [:> simple-padding-selection* props] (= type :multiple) - [:> multiple-padding-selection props])] + [:> multiple-padding-selection* props])] [:button {:class (stl/css-case :padding-toggle true @@ -502,23 +693,20 @@ (st/emit! (udw/set-gap-selected value))) (defn- on-gap-focus - [event] - (let [type (-> (dom/get-current-target event) - (dom/get-data "type") - (keyword))] - (select-gap! type) - (dom/select-target event))) + [type] + (select-gap! type)) (defn- on-gap-blur [_event] (select-gap! nil)) -(mf/defc gap-section - {::mf/props :obj} - [{:keys [is-column wrap-type on-change value] - :or {wrap-type :none} +(mf/defc gap-section* + [{:keys [is-column wrap-type on-change value applied-tokens shapes ids] :as props}] - (let [nowrap? (= :nowrap wrap-type) + (let [token-numeric-inputs + (features/use-feature "tokens/numeric-input") + + nowrap? (= :nowrap wrap-type) row-gap-disabled? (and ^boolean nowrap? @@ -530,12 +718,38 @@ on-change' (mf/use-fn - (mf/deps on-change) - (fn [value event] - (let [target (dom/get-current-target event) - wrap-type (dom/get-data target "wrap-type") - type (keyword (dom/get-data target "type"))] - (on-change (= "nowrap" wrap-type) type value event))))] + (mf/deps on-change wrap-type) + (fn [value attr event] + + (if (or (string? value) (int? value)) + (on-change (= "nowrap" wrap-type) attr value event) + (do + (let [resolved-value (:resolved-value (first value))] + (st/emit! (dwta/toggle-token {:token (first value) + :attrs #{attr} + :shapes shapes})) + (on-change (= "nowrap" wrap-type) attr resolved-value event)))))) + + on-detach-token + (mf/use-fn + (mf/deps ids) + (fn [token attr] + (prn ids) + (st/emit! (dwta/unapply-token {:token (first token) + :attributes #{attr} + :shape-ids ids})))) + + on-row-gap-change + (mf/use-fn (mf/deps on-change') #(on-change' % :row-gap)) + + on-column-gap-change + (mf/use-fn (mf/deps on-change') #(on-change' % :column-gap)) + + on-focus-row-gap + (mf/use-fn (mf/deps on-gap-focus) #(on-gap-focus :row-gap)) + + on-focus-column-gap + (mf/use-fn (mf/deps on-gap-focus) #(on-gap-focus :column-gap))] (mf/with-effect [] ;; on destroy component @@ -544,43 +758,73 @@ [:div {:class (stl/css :gap-group)} - [:div {:class (stl/css-case - :row-gap true - :disabled row-gap-disabled?) - :title "Row gap"} - [:span {:class (stl/css :icon)} deprecated-icon/gap-vertical] - [:> numeric-input* - {:class (stl/css :numeric-input true) - :no-validate true - :placeholder "--" - :data-type "row-gap" - :data-wrap-type (d/name wrap-type) - :on-focus on-gap-focus - :on-change on-change' - :on-blur on-gap-blur - :nillable true - :min 0 - :value (:row-gap value) - :disabled row-gap-disabled?}]] + (if token-numeric-inputs + [:> numeric-input-wrapper* + {:on-change on-row-gap-change + :on-detach on-detach-token + :on-focus on-focus-row-gap + :on-blur on-gap-blur + :icon i/gap-vertical + :nillable true + :min 0 + :name :row-gap + :applied-tokens applied-tokens + :property "Row gap" + :values {:row-gap (:row-gap value)} + :disabled row-gap-disabled?}] - [:div {:class (stl/css-case - :column-gap true - :disabled col-gap-disabled?) - :title "Column gap"} - [:span {:class (stl/css :icon)} deprecated-icon/gap-horizontal] - [:> numeric-input* - {:class (stl/css :numeric-input true) - :no-validate true - :placeholder "--" - :data-type "column-gap" - :data-wrap-type (d/name wrap-type) - :on-focus on-gap-focus - :on-change on-change' - :on-blur on-gap-blur - :nillable true - :min 0 - :value (:column-gap value) - :disabled col-gap-disabled?}]]])) + [:div {:class (stl/css-case + :row-gap true + :disabled row-gap-disabled?) + :title "Row gap"} + [:span {:class (stl/css :icon)} deprecated-icon/gap-vertical] + [:> deprecated-input/numeric-input* + {:class (stl/css :numeric-input true) + :no-validate true + :placeholder "--" + :data-type "row-gap" + :data-wrap-type (d/name wrap-type) + :on-focus on-focus-row-gap + :on-change on-change' + :on-blur on-gap-blur + :nillable true + :min 0 + :value (:row-gap value) + :disabled row-gap-disabled?}]]) + + (if token-numeric-inputs + [:> numeric-input-wrapper* + {:on-change on-column-gap-change + :on-detach on-detach-token + :on-focus on-focus-column-gap + :on-blur on-gap-blur + :icon i/gap-horizontal + :nillable true + :min 0 + :name :column-gap + :applied-tokens applied-tokens + :property "Column gap" + :values {:column-gap (:column-gap value)} + :disabled col-gap-disabled?}] + + [:div {:class (stl/css-case + :column-gap true + :disabled col-gap-disabled?) + :title "Column gap"} + [:span {:class (stl/css :icon)} deprecated-icon/gap-horizontal] + [:> deprecated-input/numeric-input* + {:class (stl/css :numeric-input true) + :no-validate true + :placeholder "--" + :data-type "column-gap" + :data-wrap-type (d/name wrap-type) + :on-focus on-focus-column-gap + :on-change on-change' + :on-blur on-gap-blur + :nillable true + :min 0 + :value (:column-gap value) + :disabled col-gap-disabled?}]])])) ;; GRID COMPONENTS @@ -760,12 +1004,12 @@ (if is-column deprecated-icon/flex-vertical deprecated-icon/flex-horizontal)] [:div {:class (stl/css :track-info-value)} - [:> numeric-input* {:no-validate true - :value (:value column) - :on-change #(set-column-value type index %) - :placeholder "--" - :min 0 - :disabled (= :auto (:type column))}]] + [:> deprecated-input/numeric-input* {:no-validate true + :value (:value column) + :on-change #(set-column-value type index %) + :placeholder "--" + :min 0 + :disabled (= :auto (:type column))}]] [:div {:class (stl/css :track-info-unit)} [:& select {:class (stl/css :track-info-unit-selector) @@ -838,9 +1082,8 @@ (st/emit! (dom/open-new-window cf/grid-help-uri))) (mf/defc layout-container-menu - {::mf/memo #{:ids :values :multiple} - ::mf/props :obj} - [{:keys [ids values multiple]}] + {::mf/memo #{:ids :values :multiple :shapes :applied-tokens}} + [{:keys [ids values multiple shapes applied-tokens]}] (let [;; Display layout-type (:layout values) has-layout? (some? layout-type) @@ -920,14 +1163,16 @@ ;; Gap on-gap-change - (fn [multiple? type val] - (let [val (mth/finite val 0)] - (cond - ^boolean multiple? - (st/emit! (dwsl/update-layout ids {:layout-gap {:row-gap val :column-gap val}})) + (mf/use-fn + (mf/deps ids) + (fn [multiple? type val] + (let [val (mth/finite val 0)] + (cond + ^boolean multiple? + (st/emit! (dwsl/update-layout ids {:layout-gap {:row-gap val :column-gap val}})) - (some? type) - (st/emit! (dwsl/update-layout ids {:layout-gap {type val}}))))) + (some? type) + (st/emit! (dwsl/update-layout ids {:layout-gap {type val}})))))) ;; Padding on-padding-type-change @@ -1091,15 +1336,20 @@ :value align-content :on-change on-align-content-change}]]) [:div {:class (stl/css :forth-row)} - [:& gap-section {:is-column is-column - :wrap-type wrap-type - :on-change on-gap-change - :value (:layout-gap values)}] - - [:& padding-section {:value (:layout-padding values) - :type (:layout-padding-type values) - :on-type-change on-padding-type-change - :on-change on-padding-change}]]] + [:> gap-section* {:is-column is-column + :wrap-type wrap-type + :on-change on-gap-change + :shapes shapes + :ids ids + :applied-tokens applied-tokens + :value (:layout-gap values)}] + [:> padding-section* {:value (:layout-padding values) + :type (:layout-padding-type values) + :on-type-change on-padding-type-change + :shapes shapes + :ids ids + :applied-tokens applied-tokens + :on-change on-padding-change}]]] :grid [:div {:class (stl/css :grid-layout-menu)} @@ -1133,20 +1383,24 @@ :on-change on-row-justify-change}]] [:div {:class (stl/css :gap-row)} - [:& gap-section {:on-change on-gap-change - :value (:layout-gap values)}]] + [:> gap-section* {:on-change on-gap-change + :shapes shapes + :ids ids + :applied-tokens applied-tokens + :value (:layout-gap values)}]] [:div {:class (stl/css :padding-row)} - [:& padding-section {:value (:layout-padding values) - :type (:layout-padding-type values) - :on-type-change on-padding-type-change - :on-change on-padding-change}]]] + [:> padding-section* {:value (:layout-padding values) + :type (:layout-padding-type values) + :shapes shapes + :applied-tokens applied-tokens + :on-type-change on-padding-type-change + :on-change on-padding-change}]]] nil))])) (mf/defc grid-layout-edition - {::mf/memo #{:ids :values} - ::mf/props :obj} - [{:keys [ids values]}] + {::mf/memo #{:ids :values :shapes :applied-tokens}} + [{:keys [ids values shapes applied-tokens]}] (let [;; Gap saved-grid-dir (:layout-grid-dir values) @@ -1329,14 +1583,17 @@ :icon i/locate}]] [:div {:class (stl/css :gap-row)} - [:& gap-section {:on-change on-gap-change - :value (:layout-gap values)}]] + [:> gap-section* {:on-change on-gap-change + :shapes shapes + :ids ids + :applied-tokens applied-tokens + :value (:layout-gap values)}]] [:div {:class (stl/css :padding-row :padding-section)} - [:& padding-section {:value (:layout-padding values) - :type (:layout-padding-type values) - :on-type-change on-padding-type-change - :on-change on-padding-change}]] + [:> padding-section* {:value (:layout-padding values) + :type (:layout-padding-type values) + :on-type-change on-padding-type-change + :on-change on-padding-change}]] [:div {:class (stl/css :grid-tracks-row)} [:& grid-columns-row {:is-column true diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.scss index 7fdf2dd4af..5c3ecf90d4 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.scss @@ -4,160 +4,180 @@ // // Copyright (c) KALEIDOS INC +// TODO: When button replace remove this @use @use "refactor/common-refactor.scss" as deprecated; +@use "ds/_utils.scss" as *; +@use "ds/_sizes.scss" as *; +@use "ds/_borders.scss" as *; +@use "ds/typography.scss" as t; +@use "ds/spacing.scss" as *; +@use "ds/mixins.scss" as *; .element-set { margin: 0; - .element-title { - .title-spacing-layout { - padding-left: deprecated.$s-2; - margin: 0; - } +} - .title-actions { - position: relative; - display: flex; - gap: deprecated.$s-4; - height: deprecated.$s-32; - padding: 0; - margin: 0; - .layout-options { - width: fit-content; - } - .layout-option { - white-space: nowrap; - } - } +.title-spacing-layout { + padding-inline-start: var(--sp-xxs); + margin: 0; +} + +.title-actions { + position: relative; + display: flex; + gap: var(--sp-xs); + block-size: $sz-32; + padding: 0; + margin: 0; +} + +.layout-options { + inline-size: fit-content; +} + +.layout-option { + white-space: nowrap; +} + +.flex-layout-menu { + display: grid; + grid-template-columns: repeat(8, var(--sp-xxxl)); + gap: var(--sp-xs); + margin-block-end: var(--sp-s); +} + +.first-row { + grid-column: 1 / -1; + display: grid; + grid-template-columns: subgrid; + margin-block-end: var(--sp-m); + margin-block-start: var(--sp-xs); +} + +.align-row { + grid-column: span 3; +} + +.direction-row-flex { + grid-column: span 4; +} + +// TODO: Replace this buttons with DS buttons +.wrap-button { + @extend .button-tertiary; + border-radius: $br-8; + block-size: $sz-32; + inline-size: $sz-32; + svg { + @extend .button-icon; + stroke: var(--color-foreground-secondary); } - .flex-layout-menu { - display: grid; - grid-template-columns: repeat(8, var(--sp-xxxl)); - gap: var(--sp-xs); - margin-bottom: deprecated.$s-8; - - .first-row { - grid-column: 1 / -1; - display: grid; - grid-template-columns: subgrid; - margin-bottom: deprecated.$s-12; - margin-top: deprecated.$s-4; - - .align-row { - grid-column: span 3; - } - - .direction-row-flex { - grid-column: span 4; - } - - .wrap-button { - @extend .button-tertiary; - border-radius: deprecated.$br-8; - height: deprecated.$s-32; - width: deprecated.$s-32; - svg { - @extend .button-icon; - stroke: var(--icon-foreground); - } - &.selected { - @extend .button-icon-selected; - } - } - } - .second-row, - .third-row { - grid-column: 1 / -1; - display: grid; - grid-template-columns: subgrid; - margin-bottom: deprecated.$s-12; - - .align-content-row, - .justify-content-row { - grid-column: span 6; - } - } - .forth-row { - display: grid; - --input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2); - grid-template-columns: var(--input-width) var(--input-width) var(--sp-xxxl); - gap: var(--sp-xs); - grid-column: 1 / -1; - } - .help-button-wrapper { - grid-column: 1 / -1; - display: flex; - flex-direction: row; - justify-content: space-between; - } + &.selected { + @extend .button-icon-selected; } } +.second-row, +.third-row { + grid-column: 1 / -1; + display: grid; + grid-template-columns: subgrid; + margin-block-end: var(--sp-m); +} + +.align-content-row, +.justify-content-row { + grid-column: span 6; +} + +.forth-row { + /* + This element do not match the 8 column grid of sidebar + + |___|-|___|-|___|-|___|-|___|-|___|-|___|-|___| -> 8 column grid, (--sp-xxxl) width each + + |__________________|-|__________________|-|___| -> 2 inputs blocks + 1 button. + + We need to calculate the total width of each input block: + - 3.5 columns of the the base grid (--sp-xxxl) + - plus 3 inter-column gaps (3 * --sp-xs) + - minus half a gap (--sp-xs / 2) because the last spacing is shared + with the next block, keeping the overall visual rhythm consistent. + */ + + --input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - (var(--sp-xs) / 2)); + + display: grid; + grid-template-columns: + var(--input-width) /* first input block */ + var(--input-width) /* second input block */ + var(--sp-xxxl); /* action button */ + gap: var(--sp-xs); + grid-column: 1 / -1; +} + +.help-button-wrapper { + grid-column: 1 / -1; + display: flex; + flex-direction: row; + justify-content: space-between; +} + .gap-group { grid-column: span 3; display: grid; grid-template-columns: subgrid; - .column-gap { - @extend .input-element; - @include deprecated.bodySmallTypography; - &.disabled { - @extend .disabled-input; - } - } - .row-gap { - @extend .input-element; - @include deprecated.bodySmallTypography; - &.disabled { - @extend .disabled-input; - } +} + +// TODO: Remove when activating token numeric inputs +.column-gap, +.row-gap { + @extend .input-element; + @include t.use-typography("body-small"); + &.disabled { + @extend .disabled-input; } } +// TODO: Remove when activating token numeric inputs +.padding-simple, +.padding-multiple { + @include t.use-typography("body-small"); + @extend .input-element; +} + .padding-group { display: grid; grid-column: span 3; grid-template-columns: subgrid; +} - .padding-inputs { - grid-column: span 2; - display: grid; - grid-template-columns: subgrid; +.padding-inputs, +.paddings-simple { + grid-column: span 2; + display: grid; + grid-template-columns: subgrid; +} + +.paddings-multiple { + display: grid; + grid-column: span 2; + grid-template-columns: subgrid; + gap: var(--sp-xs); +} + +// TODO: Replace this buttons with DS buttons +.padding-toggle { + @extend .button-tertiary; + block-size: $sz-32; + inline-size: $sz-32; + border-radius: $br-8; + svg { + @extend .button-icon; + stroke: var(--color-foreground-secondary); } - - .paddings-simple { - display: grid; - grid-column: span 2; - grid-template-columns: subgrid; - - .padding-simple { - @extend .input-element; - @include deprecated.bodySmallTypography; - } - } - - .paddings-multiple { - display: grid; - grid-column: span 2; - grid-template-columns: subgrid; - gap: var(--sp-xs); - - .padding-multiple { - @extend .input-element; - @include deprecated.bodySmallTypography; - } - } - - .padding-toggle { - @extend .button-tertiary; - height: deprecated.$s-32; - width: deprecated.$s-32; - border-radius: deprecated.$br-8; - svg { - @extend .button-icon; - stroke: var(--icon-foreground); - } - &.selected { - @extend .button-icon-selected; - } + &.selected { + @extend .button-icon-selected; } } @@ -165,78 +185,80 @@ display: grid; grid-template-columns: repeat(8, var(--sp-xxxl)); gap: var(--sp-xs); +} - .edit-grid-wrapper, - .first-row, - .grid-layout-align, - .gap-row, - .padding-row { - grid-column: 1 / -1; - } +.edit-grid-wrapper, +.first-row, +.grid-layout-align, +.gap-row, +.padding-row { + grid-column: 1 / -1; +} - .first-row { - margin-bottom: deprecated.$s-8; - display: grid; - grid-template-columns: subgrid; - } +.first-row { + margin-block-end: var(--sp-s); + display: grid; + grid-template-columns: subgrid; +} - .grid-layout-align { - display: grid; - grid-template-columns: subgrid; - align-items: flex-start; - position: relative; - gap: var(--sp-xs); +.grid-layout-align { + display: grid; + grid-template-columns: subgrid; + align-items: flex-start; + position: relative; + gap: var(--sp-xs); +} - .locate-button { - grid-row: 1; - grid-column: 8; - } - } +.locate-button { + grid-row: 1; + grid-column: 8; +} - .grid-layout-menu-title { - flex: 1; - font-size: deprecated.$fs-11; - color: var(--title-foreground-color-hover); - grid-column: span 5; - } +.grid-layout-menu-title { + @include t.use-typography("headline-small"); + flex: 1; + color: var(--color-foreground-primary); + grid-column: span 5; +} - .edit-mode-btn { - @extend .button-secondary; - @include deprecated.uppercaseTitleTipography; - width: 100%; - padding: deprecated.$s-8; - grid-column: span 7; - } +// TODO: Replace this buttons with DS buttons +.edit-mode-btn { + @extend .button-secondary; + @include t.use-typography("headline-small"); + inline-size: 100%; + padding: var(--sp-s); + grid-column: span 7; +} - .exit-btn { - @extend .button-secondary; - @include deprecated.uppercaseTitleTipography; - padding: deprecated.$s-8 deprecated.$s-20; - grid-column: span 2; - } +// TODO: Replace this buttons with DS buttons +.exit-btn { + @extend .button-secondary; + @include t.use-typography("headline-small"); + padding: var(--sp-s) var(--sp-xl); + grid-column: span 2; +} - .grid-tracks-info-container { - display: grid; - grid-template-columns: subgrid; - grid-column: 1 / -1; - gap: var(--sp-xs); - margin-top: deprecated.$s-4; - } +.grid-tracks-info-container { + display: grid; + grid-template-columns: subgrid; + grid-column: 1 / -1; + gap: var(--sp-xs); + margin-block-start: var(--sp-xs); +} - .padding-section { - margin-top: deprecated.$s-8; - } +.padding-section { + margin-block-start: var(--sp-s); +} - .grid-tracks-row { - display: grid; - grid-template-columns: subgrid; - grid-column: 1 / -1; - } +.grid-tracks-row { + display: grid; + grid-template-columns: subgrid; + grid-column: 1 / -1; +} - .edit-grid-wrapper { - display: grid; - grid-template-columns: subgrid; - } +.edit-grid-wrapper { + display: grid; + grid-template-columns: subgrid; } .track-info { @@ -245,127 +267,155 @@ grid-template-columns: subgrid; &.dnd-over-top { - border-top: deprecated.$s-2 solid var(--button-foreground-hover); + border-block-start: $b-2 solid var(--color-accent-primary); } &.dnd-over-bot { - border-bottom: deprecated.$s-2 solid var(--button-foreground-hover); + border-block-end: $b-2 solid var(--color-accent-primary); } +} - .track-info-container { - display: flex; - grid-column: 1 / span 7; - } +.track-info-container { + display: flex; + grid-column: 1 / span 7; +} - .track-info-dir-icon { - cursor: pointer; - border-radius: deprecated.$br-8 0 0 deprecated.$br-8; - background-color: var(--input-background-color); - padding: 0 deprecated.$s-8; - svg { - @extend .button-icon; - stroke: var(--icon-foreground); - height: 100%; - } - &:hover svg { - stroke: var(--icon-foreground-hover); - } +// TODO: Replace this buttons with DS buttons +.track-info-dir-icon { + cursor: pointer; + border-radius: $br-8 0 0 $br-8; + background-color: var(--color-background-tertiary); + padding: 0 var(--sp-s); + svg { + @extend .button-icon; + stroke: var(--color-foreground-secondary); + block-size: 100%; } + &:hover svg { + stroke: var(--color-foreground-primary); + } +} - .track-info-value { - @extend .input-element; - @include deprecated.bodySmallTypography; - border-radius: 0; - border-right: deprecated.$s-1 solid var(--panel-background-color); - } +.track-info-value { + @extend .input-element; + @include t.use-typography("body-small"); + border-radius: 0; + border-inline-end: $b-1 solid var(--color-background-primary); +} - .track-info-unit-selector { - border-radius: 0 deprecated.$br-8 deprecated.$br-8 0; - width: deprecated.$s-96; - } +.track-info-unit-selector { + border-radius: 0 $br-8 $br-8 0; + inline-size: px2rem(96); } .grid-tracks { display: grid; grid-template-columns: subgrid; grid-column: 1 / -1; - margin-top: deprecated.$s-8; + margin-block-start: var(--sp-s); +} - .grid-track-header { - @include deprecated.flexRow; - font-size: deprecated.$fs-12; - border-radius: deprecated.$br-8; - overflow: hidden; - background: var(--button-secondary-background-color-rest); - height: deprecated.$s-52; - grid-column: 1 / -1; +.grid-track-header { + @include t.use-typography("body-small"); + display: flex; + align-items: center; + gap: var(--sp-xs); + border-radius: $br-8; + overflow: hidden; + background: var(--color-background-tertiary); + block-size: px2rem(52); + grid-column: 1 / -1; +} + +.track-title { + display: grid; + flex-grow: 1; + padding: var(--sp-s); + gap: 0; + overflow: hidden; +} + +.track-name { + color: var(--color-foreground-primary); +} + +.track-detail { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + inline-size: 100%; + color: var(--color-foreground-secondary); +} + +// TODO: Replace this buttons with DS buttons +.expand-icon { + @extend .button-secondary; + block-size: px2rem(52); + + border-radius: $br-8 0 0 $br-8; + border-inline-end: $b-1 solid var(--color-background-primary); + svg { + @extend .button-icon; + stroke: var(--color-foreground-secondary); + fill: var(--color-foreground-secondary); } - - .track-title { - display: grid; - flex-grow: 1; - padding: deprecated.$s-8; - gap: 0; - overflow: hidden; - } - - .track-name { - color: var(--color-foreground-primary); - } - - .track-detail { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - width: 100%; - color: var(--color-foreground-secondary); - } - - .expand-icon { - @extend .button-secondary; - height: deprecated.$s-52; - - border-radius: deprecated.$s-8 0 0 deprecated.$s-8; - border-right: deprecated.$s-1 solid var(--panel-background-color); + &:hover, + &:active { svg { - @extend .button-icon; - stroke: var(--icon-foreground); - fill: var(--icon-foreground); - } - &:hover, - &:active { - svg { - stroke: var(--button-foreground-hover); - fill: var(--button-foreground-hover); - } - } - } - - .add-column { - @extend .button-tertiary; - height: deprecated.$s-52; - - svg { - @extend .button-icon; - height: deprecated.$s-12; - width: deprecated.$s-12; - stroke: var(--icon-foreground); - fill: var(--icon-foreground); + stroke: var(--color-accent-primary); + fill: var(--color-accent-primary); } } } +// TODO: Replace this buttons with DS buttons +.add-column { + @extend .button-tertiary; + block-size: px2rem(52); + + svg { + display: flex; + justify-content: center; + align-items: center; + color: transparent; + fill: none; + stroke-width: px2rem(1); + block-size: $sz-12; + inline-size: $sz-12; + stroke: var(--color-foreground-secondary); + fill: var(--color-foreground-secondary); + } +} + .layout-options { - @extend .dropdown-wrapper; - @include deprecated.flexColumn; - right: var(--sp-s); - left: initial; + box-shadow: 0px 0px $sz-12 0px var(--color-shadow-dark); + position: absolute; + display: flex; + flex-direction: column; + inset-block-start: $sz-32; + inset-inline-start: initial; + inset-inline-end: var(--sp-s); + inline-size: 100%; + max-block-size: var(--menu-max-height, px2rem(300)); + padding: var(--sp-xxs); + margin: 0; + margin-block-start: px2rem(1); + border-radius: $br-8; + z-index: var(--z-index-dropdown); + overflow-y: auto; + overflow-x: hidden; + background-color: var(--color-background-tertiary); + color: var(--color-foreground-primary); + border: $b-2 solid var(--color-background-quaternary); + gap: var(--sp-xs); button { - @include deprecated.buttonStyle; - padding: deprecated.$s-8; + border: none; + background: none; + cursor: pointer; + padding: var(--sp-s); color: var(--color-foreground-primary); - border-radius: deprecated.$br-6; + border-radius: $br-6; &:hover { background: var(--color-background-quaternary); @@ -387,9 +437,27 @@ .gap-row, .padding-row { + /* + This element do not match the 8 column grid of sidebar + + |___|-|___|-|___|-|___|-|___|-|___|-|___|-|___| -> 8 column grid, (--sp-xxxl) width each + + |__________________|-|__________________|-|___| -> 2 inputs blocks + 1 button. + + We need to calculate the total width of each input block: + - 3.5 columns of the the base grid (--sp-xxxl) + - plus 3 inter-column gaps (3 * --sp-xs) + - minus half a gap (--sp-xs / 2) because the last spacing is shared + with the next block, keeping the overall visual rhythm consistent. + */ + + --input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - (var(--sp-xs) / 2)); + display: grid; - --input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2); - grid-template-columns: var(--input-width) var(--input-width) var(--sp-xxxl); + grid-template-columns: + var(--input-width) /* first input block */ + var(--input-width) /* second input block */ + var(--sp-xxxl); /* action button */ gap: var(--sp-xs); } diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.scss index 511b7a4adc..80276a4d2e 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.scss @@ -62,10 +62,27 @@ } .margin-row { + /* + This element do not match the 8 column grid of sidebar + + |___|-|___|-|___|-|___|-|___|-|___|-|___|-|___| -> 8 column grid, (--sp-xxxl) width each + + |__________________|-|__________________|-|___| -> 2 inputs blocks + 1 button. + + We need to calculate the total width of each input block: + - 3.5 columns of the the base grid (--sp-xxxl) + - plus 3 inter-column gaps (3 * --sp-xs) + - minus half a gap (--sp-xs / 2) because the last spacing is shared + with the next block, keeping the overall visual rhythm consistent. + */ + + --input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - (var(--sp-xs) / 2)); + display: grid; - // NOTE: this does not follow the 8-column grid and the size is not normalized, - --input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2); - grid-template-columns: var(--input-width) var(--input-width) var(--sp-xxxl); + grid-template-columns: + var(--input-width) /* first input block */ + var(--input-width) /* second input block */ + var(--sp-xxxl); /* action button */ gap: var(--sp-xs); } @@ -133,9 +150,27 @@ } .advanced-options { + /* + This element do not match the 8 column grid of sidebar + + |___|-|___|-|___|-|___|-|___|-|___|-|___|-|___| -> 8 column grid, (--sp-xxxl) width each + + |__________________|-|__________________|-|___| -> 2 inputs blocks + 1 button. + + We need to calculate the total width of each input block: + - 3.5 columns of the the base grid (--sp-xxxl) + - plus 3 inter-column gaps (3 * --sp-xs) + - minus half a gap (--sp-xs / 2) because the last spacing is shared + with the next block, keeping the overall visual rhythm consistent. + */ + + --input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - (var(--sp-xs) / 2)); + display: grid; - --input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2); - grid-template-columns: var(--input-width) var(--input-width) var(--sp-xxxl); + grid-template-columns: + var(--input-width) /* first input block */ + var(--input-width) /* second input block */ + var(--sp-xxxl); /* action button */ gap: var(--sp-xs); } diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs index 94f2982ea5..e10063542a 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs @@ -301,7 +301,7 @@ on-size-change (mf/use-fn - (mf/deps ids) + (mf/deps ids shapes) (fn [value attr] (if (or (string? value) (int? value)) (do diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.scss index 96dee5fe7f..a5a34abec8 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.scss @@ -7,12 +7,29 @@ @use "refactor/common-refactor.scss" as deprecated; .element-set { + /* + This element do not match the 8 column grid of sidebar + + |___|-|___|-|___|-|___|-|___|-|___|-|___|-|___| -> 8 column grid, (--sp-xxxl) width each + + |__________________|-|__________________|-|___| -> 2 inputs blocks + 1 button. + + We need to calculate the total width of each input block: + - 3.5 columns of the the base grid (--sp-xxxl) + - plus 3 inter-column gaps (3 * --sp-xs) + - minus half a gap (--sp-xs / 2) because the last spacing is shared + with the next block, keeping the overall visual rhythm consistent. + */ + + --input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - (var(--sp-xs) / 2)); + display: grid; - margin-bottom: var(--sp-s); - // NOTE: this does not follow the 8-column grid and the size is not normalized, - --input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2); - grid-template-columns: var(--input-width) var(--input-width) var(--sp-xxxl); + grid-template-columns: + var(--input-width) /* first input block */ + var(--input-width) /* second input block */ + var(--sp-xxxl); /* action button */ gap: var(--sp-xs); + margin-bottom: var(--sp-s); } .presets { diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.scss b/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.scss index 76ff0d737a..f6f6090981 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.scss @@ -47,9 +47,27 @@ } } .stroke-caps-options { + /* + This element do not match the 8 column grid of sidebar + + |___|-|___|-|___|-|___|-|___|-|___|-|___|-|___| -> 8 column grid, (--sp-xxxl) width each + + |__________________|-|__________________|-|___| -> 2 inputs blocks + 1 button. + + We need to calculate the total width of each input block: + - 3.5 columns of the the base grid (--sp-xxxl) + - plus 3 inter-column gaps (3 * --sp-xs) + - minus half a gap (--sp-xs / 2) because the last spacing is shared + with the next block, keeping the overall visual rhythm consistent. + */ + + --input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - (var(--sp-xs) / 2)); + display: grid; - --input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2); - grid-template-columns: var(--input-width) var(--sp-xxxl) var(--input-width); + grid-template-columns: + var(--input-width) /* first input block */ + var(--input-width) /* second input block */ + var(--sp-xxxl); /* action button */ gap: var(--sp-xs); } diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/bool.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/bool.cljs index 8311104d68..bb06c3ac4b 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/bool.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/bool.cljs @@ -97,6 +97,8 @@ {:type type :ids [(:id shape)] :values layout-container-values + :applied-tokens applied-tokens + :shapes shapes :multiple false}] (when (and (= (count ids) 1) is-layout-child? is-grid-parent?) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/circle.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/circle.cljs index b21f0f4c5c..848e26ed7a 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/circle.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/circle.cljs @@ -96,6 +96,8 @@ {:type type :ids [(:id shape)] :values layout-container-values + :applied-tokens applied-tokens + :shapes shapes :multiple false}] (when (and (= (count ids) 1) is-layout-child? is-grid-parent?) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/frame.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/frame.cljs index e3103f2642..98594c68d4 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/frame.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/frame.cljs @@ -115,6 +115,8 @@ [:& layout-container-menu {:type shape-type :ids ids + :shapes shapes + :applied-tokens applied-tokens :values layout-container-values :multiple false}] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/group.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/group.cljs index e9d29affcc..507a73d03f 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/group.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/group.cljs @@ -122,6 +122,8 @@ {:type type :ids [(:id shape)] :values layout-container-values + :applied-tokens applied-tokens + :shapes shapes :multiple false}] (when (and (= (count ids) 1) is-layout-child? is-grid-parent?) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/multiple.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/multiple.cljs index efaaf22b0b..ca7e6d6a38 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/multiple.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/multiple.cljs @@ -408,7 +408,7 @@ [exports-ids exports-values] (get-attrs shapes objects :exports) - [layout-container-ids layout-container-values] + [layout-container-ids layout-container-values layout-contianer-tokens] (get-attrs shapes objects :layout-container) [layout-item-ids layout-item-values {}] @@ -461,6 +461,8 @@ {:type type :ids layout-container-ids :values layout-container-values + :applied-tokens layout-contianer-tokens + :shapes shapes :multiple true}] (when (or is-layout-child? has-flex-layout-container?) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/path.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/path.cljs index c1ef859746..433aa5f6c9 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/path.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/path.cljs @@ -96,6 +96,8 @@ {:type type :ids [(:id shape)] :values layout-container-values + :applied-tokens applied-tokens + :shapes shapes :multiple false}] (when (and (= (count ids) 1) is-layout-child? is-grid-parent?) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/rect.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/rect.cljs index 6019e37f7b..d22aecdcd8 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/rect.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/rect.cljs @@ -96,6 +96,8 @@ {:type type :ids ids :values layout-container-values + :applied-tokens applied-tokens + :shapes shapes :multiple false}] (when (and (= (count ids) 1) is-layout-child? is-grid-parent?) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/svg_raw.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/svg_raw.cljs index 0b85529c76..a2bafe0ed5 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/svg_raw.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/svg_raw.cljs @@ -164,6 +164,8 @@ {:type type :ids [(:id shape)] :values layout-container-values + :applied-tokens applied-tokens + :shapes shapes :multiple false}] (when (and (= (count ids) 1) is-layout-child? is-grid-parent?) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs index e267f63ce5..287e2327c6 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs @@ -129,14 +129,16 @@ [:> measures-menu* {:ids ids :type type - :applied-tokens applied-tokens :values measure-values + :applied-tokens applied-tokens :shapes shapes}] [:& layout-container-menu {:type type :ids ids :values layout-container-values + :applied-tokens applied-tokens + :shapes shapes :multiple false}] (when (and (= (count ids) 1) is-layout-child? is-grid-parent?)