0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-01 11:59:17 -05:00

Merge pull request #146 from tokens-studio/135-flex-row--gap-token-updating-from-the-right-sidebar

135 flex row  gap token updating from the right sidebar
This commit is contained in:
Florian Schrödl 2024-05-29 13:20:44 +02:00 committed by GitHub
commit 420b8cf524
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 123 additions and 74 deletions

View file

@ -27,6 +27,8 @@
[app.main.ui.formats :as fmt] [app.main.ui.formats :as fmt]
[app.main.ui.hooks :as h] [app.main.ui.hooks :as h]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.main.ui.workspace.tokens.core :as wtc]
[app.main.ui.workspace.tokens.editable-select :refer [editable-select]]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as kbd] [app.util.keyboard :as kbd]
@ -507,7 +509,7 @@
(mf/defc gap-section (mf/defc gap-section
{::mf/props :obj} {::mf/props :obj}
[{:keys [is-column wrap-type on-change value] [{:keys [is-column wrap-type on-change value spacing-column-options spacing-row-options]
:or {wrap-type :none} :or {wrap-type :none}
:as props}] :as props}]
(let [nowrap? (= :nowrap wrap-type) (let [nowrap? (= :nowrap wrap-type)
@ -541,38 +543,45 @@
:disabled row-gap-disabled?) :disabled row-gap-disabled?)
:title "Row gap"} :title "Row gap"}
[:span {:class (stl/css :icon)} i/gap-vertical] [:span {:class (stl/css :icon)} i/gap-vertical]
[:> numeric-input* [:& editable-select
{:class (stl/css :numeric-input true) {:disabled row-gap-disabled?
:no-validate true
:placeholder "--" :placeholder "--"
:data-type "row-gap"
:data-wrap-type (d/name wrap-type)
:on-focus on-gap-focus
:on-change on-change' :on-change on-change'
:on-blur on-gap-blur :on-blur on-gap-blur
:nillable true :on-token-remove js/console.log
:min 0 :options spacing-column-options
:position :left
:value (:row-gap value) :value (:row-gap value)
:disabled row-gap-disabled?}]] :input-props {:type "number"
:data-type "row-gap"
:data-wrap-type (d/name wrap-type)
:no-validate true
:nillable true
:min 0
:class (stl/css :numeric-input)}}]]
[:div {:class (stl/css-case [:div {:class (stl/css-case
:column-gap true :column-gap true
:disabled col-gap-disabled?) :disabled col-gap-disabled?)
:title "Column gap"} :title "Column gap"}
[:span {:class (stl/css :icon)} i/gap-horizontal] [:span {:class (stl/css :icon)} i/gap-horizontal]
[:> numeric-input* [:& editable-select
{:class (stl/css :numeric-input true) {:disabled col-gap-disabled?
:no-validate true
:placeholder "--" :placeholder "--"
:data-type "column-gap"
:data-wrap-type (d/name wrap-type)
:on-focus on-gap-focus
:on-change on-change' :on-change on-change'
:on-blur on-gap-blur :on-blur on-gap-blur
:nillable true :on-token-remove js/console.log
:min 0 :options spacing-row-options
:position :right
:value (:column-gap value) :value (:column-gap value)
:disabled col-gap-disabled?}]]])) :input-props {:type "number"
:data-type "column-gap"
:data-wrap-type (d/name wrap-type)
:no-validate true
:onFocus on-gap-focus
:nillable true
:min 0
:class (stl/css :numeric-input)}}]]]))
;; GRID COMPONENTS ;; GRID COMPONENTS
@ -823,9 +832,9 @@
(st/emit! (dom/open-new-window cf/grid-help-uri))) (st/emit! (dom/open-new-window cf/grid-help-uri)))
(mf/defc layout-container-menu (mf/defc layout-container-menu
{::mf/memo #{:ids :values :multiple} {::mf/memo #{:ids :values :multiple :shape}
::mf/props :obj} ::mf/props :obj}
[{:keys [ids values multiple]}] [{:keys [ids values multiple] :as props}]
(let [;; Display (let [;; Display
layout-type (:layout values) layout-type (:layout values)
has-layout? (some? layout-type) has-layout? (some? layout-type)
@ -839,6 +848,29 @@
on-toggle-visibility on-toggle-visibility
(mf/use-fn #(swap! open* not)) (mf/use-fn #(swap! open* not))
shape (when-not multiple
(first (deref (refs/objects-by-id ids))))
tokens (mf/deref refs/workspace-tokens)
spacing-tokens (mf/use-memo (mf/deps tokens) #(:spacing (wtc/group-tokens-by-type tokens)))
spacing-column-options (mf/use-memo
(mf/deps shape spacing-tokens)
#(when shape
(wtc/tokens-name-map->select-options
{:shape shape
:tokens spacing-tokens
:attributes (wtc/token-attributes :spacing)
:selected-attributes #{:spacing-column}})))
spacing-row-options (mf/use-memo
(mf/deps shape spacing-tokens)
#(when shape
(wtc/tokens-name-map->select-options
{:shape shape
:tokens spacing-tokens
:attributes (wtc/token-attributes :spacing)
:selected-attributes #{:spacing-row}})))
on-add-layout on-add-layout
(mf/use-fn (mf/use-fn
(fn [event] (fn [event]
@ -1084,7 +1116,9 @@
[:& gap-section {:is-column is-column [:& gap-section {:is-column is-column
:wrap-type wrap-type :wrap-type wrap-type
:on-change on-gap-change :on-change on-gap-change
:value (:layout-gap values)}] :value (:layout-gap values)
:spacing-column-options spacing-column-options
:spacing-row-options spacing-row-options}]
[:& padding-section {:value (:layout-padding values) [:& padding-section {:value (:layout-padding values)
:type (:layout-padding-type values) :type (:layout-padding-type values)

View file

@ -84,6 +84,7 @@
gap: $s-4; gap: $s-4;
.column-gap { .column-gap {
@extend .input-element; @extend .input-element;
position: relative;
width: $s-108; width: $s-108;
&.disabled { &.disabled {
@extend .disabled-input; @extend .disabled-input;
@ -91,6 +92,7 @@
} }
.row-gap { .row-gap {
@extend .input-element; @extend .input-element;
position: relative;
width: $s-108; width: $s-108;
&.disabled { &.disabled {
@extend .disabled-input; @extend .disabled-input;

View file

@ -237,15 +237,18 @@
(mf/use-fn (mf/use-fn
(mf/deps ids) (mf/deps ids)
(fn [value attr] (fn [value attr]
(let [token-value (wtc/maybe-resolve-token-value value)] (let [token-value (wtc/maybe-resolve-token-value value)
undo-id (js/Symbol)]
(st/emit! (udw/trigger-bounding-box-cloaking ids) (st/emit! (udw/trigger-bounding-box-cloaking ids)
(dwu/start-undo-transaction undo-id)
(dch/update-shapes ids (dch/update-shapes ids
(if token-value (if token-value
#(assoc-in % [:applied-tokens attr] (:id value)) #(assoc-in % [:applied-tokens attr] (:id value))
#(d/dissoc-in % [:applied-tokens attr])) #(d/dissoc-in % [:applied-tokens attr]))
{:reg-objects? true {:reg-objects? true
:attrs [:applied-tokens]}) :attrs [:applied-tokens]})
(udw/update-dimensions ids attr (or token-value value)))))) (udw/update-dimensions ids attr (or token-value value))
(dwu/commit-undo-transaction undo-id)))))
@ -450,34 +453,32 @@
[:span {:class (stl/css :icon-text)} "W"] [:span {:class (stl/css :icon-text)} "W"]
[:& editable-select [:& editable-select
{:placeholder (if (= :multiple (:rx values)) (tr "settings.multiple") "--") {:placeholder (if (= :multiple (:rx values)) (tr "settings.multiple") "--")
:no-validate true
:min 0.01
:class (stl/css :token-select) :class (stl/css :token-select)
:disabled disabled-width-sizing? :disabled disabled-width-sizing?
:input-class (stl/css :numeric-input)
:on-change on-width-change :on-change on-width-change
:on-token-remove #(on-width-change (wtc/maybe-resolve-token-value %)) :on-token-remove #(on-width-change (wtc/maybe-resolve-token-value %))
:options width-options :options width-options
:position :left :position :left
:type "number" :value (:width values)
:value (:width values)}]] :input-props {:type "number"
:no-validate true
:min 0.01}}]]
[:div {:class (stl/css-case :height true [:div {:class (stl/css-case :height true
:disabled disabled-height-sizing?) :disabled disabled-height-sizing?)
:title (tr "workspace.options.height")} :title (tr "workspace.options.height")}
[:span {:class (stl/css :icon-text)} "H"] [:span {:class (stl/css :icon-text)} "H"]
[:& editable-select [:& editable-select
{:placeholder (if (= :multiple (:rx values)) (tr "settings.multiple") "--") {:placeholder (if (= :multiple (:rx values)) (tr "settings.multiple") "--")
:no-validate true
:min 0.01
:class (stl/css :token-select) :class (stl/css :token-select)
:disabled disabled-height-sizing? :disabled disabled-height-sizing?
:input-class (stl/css :numeric-input)
:on-change on-height-change :on-change on-height-change
:on-token-remove #(on-height-change (wtc/maybe-resolve-token-value %)) :on-token-remove #(on-height-change (wtc/maybe-resolve-token-value %))
:options height-options :options height-options
:position :right :position :right
:type "number" :value (:height values)
:value (:height values)}]] :input-props {:type "number"
:no-validate true
:min 0.01}}]]
[:button {:class (stl/css-case [:button {:class (stl/css-case
:lock-size-btn true :lock-size-btn true
:selected (true? proportion-lock) :selected (true? proportion-lock)
@ -536,15 +537,14 @@
[:span {:class (stl/css :icon)} i/corner-radius] [:span {:class (stl/css :icon)} i/corner-radius]
[:& editable-select [:& editable-select
{:placeholder (if (= :multiple (:rx values)) (tr "settings.multiple") "--") {:placeholder (if (= :multiple (:rx values)) (tr "settings.multiple") "--")
:min 0
:class (stl/css :token-select) :class (stl/css :token-select)
:input-class (stl/css :numeric-input)
:on-change on-radius-1-change :on-change on-radius-1-change
:on-token-remove on-border-radius-token-unapply :on-token-remove on-border-radius-token-unapply
:options border-radius-options :options border-radius-options
:position :right :position :right
:type "number" :value (:rx values)
:value (:rx values)}]] :input-props {:type "number"
:min 0}}]]
@radius-multi? @radius-multi?
[:div {:class (stl/css :radius-1) [:div {:class (stl/css :radius-1)

View file

@ -238,10 +238,3 @@
.checkbox-button { .checkbox-button {
@extend .button-icon; @extend .button-icon;
} }
.token-select {
li > span {
display: flex;
align-content: center;
}
}

View file

@ -62,8 +62,10 @@
[:span {:class (stl/css :check-icon)} i/tick]])))]]]) [:span {:class (stl/css :check-icon)} i/tick]])))]]])
(mf/defc editable-select (mf/defc editable-select
[{:keys [value type options class on-change placeholder on-blur input-class on-token-remove position] :as params}] [{:keys [value options disabled class on-change placeholder on-blur on-token-remove position input-props] :as params}]
(let [state* (mf/use-state {:id (uuid/next) (let [{:keys [type]} input-props
input-class (:class input-props)
state* (mf/use-state {:id (uuid/next)
:is-open? false :is-open? false
:current-value value :current-value value
:token-value nil :token-value nil
@ -107,11 +109,11 @@
(swap! state* assoc :token-value value)) (swap! state* assoc :token-value value))
set-value set-value
(fn [value] (fn [value event]
(swap! state* assoc (swap! state* assoc
:current-value value :current-value value
:token-value value) :token-value value)
(when on-change (on-change value))) (when on-change (on-change value event)))
select-item select-item
(mf/use-fn (mf/use-fn
@ -133,7 +135,7 @@
(fn [event] (fn [event]
(let [value (-> event dom/get-target dom/get-value) (let [value (-> event dom/get-target dom/get-value)
value (or (d/parse-double value) value)] value (or (d/parse-double value) value)]
(set-value value))) (set-value value event)))
handle-token-change-input handle-token-change-input
(fn [event] (fn [event]
@ -153,6 +155,7 @@
no-text-selected? (str/empty? (.toString (js/document.getSelection))) no-text-selected? (str/empty? (.toString (js/document.getSelection)))
delete-token? (and backspace? caret-at-beginning? no-text-selected?) delete-token? (and backspace? caret-at-beginning? no-text-selected?)
replace-token-with-value? (and enter? (seq (str/trim value)))] replace-token-with-value? (and enter? (seq (str/trim value)))]
(js/console.log "key-down" token delete-token?)
(cond (cond
delete-token? (do delete-token? (do
(dom/prevent-default event) (dom/prevent-default event)
@ -212,37 +215,42 @@
(mf/set-ref-val! emit-blur? (not is-open?))) (mf/set-ref-val! emit-blur? (not is-open?)))
[:div {:class (dm/str class " " (stl/css :editable-select))} [:div {:class (dm/str class " " (stl/css-case :editable-select true
:editable-select-disabled disabled))}
(when-let [{:keys [label value]} token] (when-let [{:keys [label value]} token]
[:div {:title (str label ": " value) [:div {:title (str label ": " value)
:class (stl/css :token-pill)} :class (stl/css :token-pill)}
value]) value])
(cond (cond
token [:input {:value (or (:token-value state) "") token [:& :input (merge input-props
:class input-class {:value (or (:token-value state) "")
:on-change handle-token-change-input :type "text"
:on-key-down handle-key-down :class input-class
:on-focus handle-focus :onChange handle-token-change-input
:on-blur handle-blur}] :onKeyDown handle-key-down
(= type "number") [:> numeric-input* {:autoFocus refocus? :onFocus handle-focus
:value (or current-value "") :onBlur handle-blur})]
:className input-class (= type "number") [:& numeric-input* (merge input-props
:on-change set-value {:autoFocus refocus?
:on-focus handle-focus :value (or current-value "")
:on-blur handle-blur :className input-class
:placeholder placeholder}] :onChange set-value
:else [:input {:value (or current-value "") :onFocus handle-focus
:class input-class :onBlur handle-blur
:on-change handle-change-input :placeholder placeholder})]
:on-key-down handle-key-down :else [:& :input (merge input-props
:on-focus handle-focus {:value (or current-value "")
:on-blur handle-blur :class input-class
:placeholder placeholder :onChange handle-change-input
:type type}]) :onKeyDown handle-key-down
:onFocus handle-focus
:onBlur handle-blur
:placeholder placeholder
:type type})])
(when (seq options) (when (seq options)
[:span {:class (stl/css :dropdown-button) [:div {:class (stl/css :dropdown-button)
:on-click toggle-dropdown} :on-click toggle-dropdown}
i/arrow]) i/arrow])
(when (and is-open? (seq options)) (when (and is-open? (seq options))

View file

@ -30,6 +30,7 @@
.dropdown-button { .dropdown-button {
@include flexCenter; @include flexCenter;
margin-right: -$s-8; margin-right: -$s-8;
padding-right: $s-8;
padding-left: 0; padding-left: 0;
aspect-ratio: 0.8 / 1; aspect-ratio: 0.8 / 1;
width: auto; width: auto;
@ -88,6 +89,12 @@
padding: 0; padding: 0;
display: flex; display: flex;
& > span {
display: flex;
justify-content: flex-start;
align-content: center;
}
.label, .label,
.value { .value {
width: fit-content; width: fit-content;
@ -100,6 +107,7 @@
.value { .value {
text-align: right; text-align: right;
justify-content: flex-end;
flex: 0.6; flex: 0.6;
} }
@ -130,3 +138,7 @@
} }
} }
} }
.editable-select-disabled {
pointer-events: none;
}