🎉 Inspect styles tab: layout element panel

This commit is contained in:
Xavier Julian 2025-09-11 16:57:37 +02:00 committed by Xaviju
parent 07d0062645
commit 55513b9ae5
8 changed files with 178 additions and 31 deletions

View File

@ -11,12 +11,32 @@
[app.main.refs :as refs]
[app.main.ui.inspect.styles.panels.geometry :refer [geometry-panel*]]
[app.main.ui.inspect.styles.panels.layout :refer [layout-panel*]]
[app.main.ui.inspect.styles.panels.layout-element :refer [layout-element-panel*]]
[app.main.ui.inspect.styles.panels.tokens-panel :refer [tokens-panel*]]
[app.main.ui.inspect.styles.panels.variants-panel :refer [variants-panel*]]
[app.main.ui.inspect.styles.style-box :refer [style-box*]]
[app.util.code-gen.style-css :as css]
[app.util.i18n :refer [tr]]
[rumext.v2 :as mf]))
(def layout-element-properties
[:margin-block-start
:margin-block-end
:margin-inline-start
:margin-inline-end
:max-block-size
:min-block-size
:max-inline-size
:min-inline-size
:align-self
:justify-self
:flex-shrink
:flex
;; Grid cell properties
:grid-column
:grid-row])
(def type->panel-group
{:multiple [:fill :stroke :text :shadow :blur :layout-element]
@ -43,8 +63,9 @@
(let [data (dm/get-in libraries [file-id :data])
first-shape (first shapes)
first-component (ctkl/get-component data (:component-id first-shape))
layout-shapes (->> shapes (filter ctl/any-layout?))
type (get-shape-type shapes first-shape first-component)
shape-type (get-shape-type shapes first-shape first-component)
panels (type->panel-group shape-type)
tokens-lib (mf/deref refs/tokens-lib)
active-themes (mf/deref refs/workspace-active-theme-paths-no-hidden)
active-sets
@ -56,31 +77,60 @@
(ctob/get-tokens-in-active-sets tokens-lib)
{}))
resolved-active-tokens
(sd/use-resolved-tokens* active-tokens)
panels (type->panel-group type)]
(sd/use-resolved-tokens* active-tokens)]
[:ol {:class (stl/css :styles-tab) :aria-label (tr "labels.styles")}
;; TOKENS PANEL
(when (or active-themes active-sets)
[:li
[:> style-box* {:panel :token}
[:> tokens-panel* {:theme-paths active-themes :set-names active-sets}]]])
(for [panel panels]
[:li {:key (d/name panel)}
(if (not (= panel :layout))
[:> style-box* {:panel panel}
(case panel
:variant [:> variants-panel* {:component first-component
:objects objects
:shape first-shape
:data data}]
:geometry [:> geometry-panel* {:shapes shapes
:objects objects
:resolved-tokens resolved-active-tokens}]
color-space)]
(when (seq layout-shapes)
[:> style-box* {:panel :layout}
[:> layout-panel* {:shapes layout-shapes
(case panel
;; VARIANTS PANEL
:variant
[:> style-box* {:panel :variant}
[:> variants-panel* {:component first-component
:objects objects
:resolved-tokens resolved-active-tokens}]]))])]))
:shape first-shape
:data data}]]
;; GEOMETRY PANEL
:geometry
[:> style-box* {:panel :geometry}
[:> geometry-panel* {:shapes shapes
:objects objects
:resolved-tokens resolved-active-tokens}]]
;; LAYOUT PANEL
:layout
(let [layout-shapes (->> shapes (filter ctl/any-layout?))]
(when (seq layout-shapes)
[:> style-box* {:panel :layout}
[:> layout-panel* {:shapes layout-shapes
:objects objects
:resolved-tokens resolved-active-tokens}]]))
;; LAYOUT ELEMENT PANEL
:layout-element
(let [shapes (->> shapes (filter #(ctl/any-layout-immediate-child? objects %)))
some-layout-prop? (->> shapes
(mapcat (fn [shape]
(keep #(css/get-css-value objects shape %) layout-element-properties)))
(seq))]
(when some-layout-prop?
(let [only-flex? (every? #(ctl/flex-layout-immediate-child? objects %) shapes)
only-grid? (every? #(ctl/grid-layout-immediate-child? objects %) shapes)
panel (if only-flex?
:flex-element
(if only-grid?
:grid-element
:layout-element))]
[:> style-box* {:panel panel}
[:> layout-element-panel* {:shapes shapes
:objects objects
:resolved-tokens resolved-active-tokens
:layout-element-properties layout-element-properties}]])))
;; DEFAULT WIP
[:> style-box* {:panel panel}
[:div color-space]])])]))
;; WIP

View File

@ -0,0 +1,51 @@
(ns app.main.ui.inspect.styles.panels.layout-element
(:require-macros [app.main.style :as stl])
(:require
[app.common.data.macros :as dm]
[app.common.types.shape.layout :as ctl]
[app.main.ui.inspect.attributes.common :as cmm]
[app.main.ui.inspect.styles.properties-row :refer [properties-row*]]
[app.util.code-gen.style-css :as css]
[rumext.v2 :as mf]))
(def ^:private shape-prop->margin-prop
{:margin-block-start :m1
:margin-inline-end :m2
:margin-block-end :m3
:margin-inline-start :m4
:max-block-size :layout-item-max-h ;; :max-height
:min-block-size :layout-item-min-h ;; :min-height
:max-inline-size :layout-item-max-w ;; :max-width
:min-inline-size :layout-item-min-w ;; :min-width
})
(defn- get-applied-margins-in-shape
[shape-tokens property]
(if-let [margin-prop (get shape-prop->margin-prop property)]
(get shape-tokens margin-prop)
(get shape-tokens property)))
(defn- get-resolved-tokens
[property shape resolved-tokens]
(when-let [shape-tokens (:applied-tokens shape)]
(let [applied-tokens-in-shape (get-applied-margins-in-shape shape-tokens property)
token (get resolved-tokens applied-tokens-in-shape)]
token)))
(mf/defc layout-element-panel*
[{:keys [shapes objects resolved-tokens layout-element-properties]}]
(let [shapes (->> shapes (filter #(ctl/any-layout-immediate-child? objects %)))]
[:div {:class (stl/css :layout-element-panel)}
(for [shape shapes]
[:div {:key (:id shape) :class "layout-element-shape"}
(for [property layout-element-properties]
(when-let [value (css/get-css-value objects shape property)]
(let [property-name (cmm/get-css-rule-humanized property)
resolved-token (get-resolved-tokens property shape resolved-tokens)
property-value (if (not resolved-token) (css/get-css-property objects shape property) "")]
[:> properties-row* {:key (dm/str "layout-element-property-" property)
:term property-name
:detail (str value)
:token resolved-token
:property property-value
:copiable true}])))])]))

View File

@ -20,7 +20,9 @@
:blur (tr "labels.blur")
:shadow (tr "labels.shadow")
:layout (tr "labels.layout")
:layout-element (tr "inspect.tabs.styles.panel.layout-element")
:flex-element "Flex element"
:grid-element "Grid element"
:layout-element "Layout Element"
:visibility (tr "labels.visibility")
:svg (tr "labels.svg")
nil))

View File

@ -113,10 +113,18 @@ body {
;; Flex/grid self properties
:flex-shrink
:margin
:margin-block-start
:margin-block-end
:margin-inline-start
:margin-inline-end
:max-height
:max-block-size
:min-height
:min-block-size
:max-width
:max-inline-size
:min-width
:min-inline-size
:align-self
:justify-self

View File

@ -18,10 +18,14 @@
:top :position
:width :size
:height :size
:min-width :size
:min-height :size
:max-width :size
:max-height :size
:max-block-size :size
:min-height :size
:min-block-size :size
:max-width :size
:max-inline-size :size
:min-width :size
:min-inline-size :size
:background :color
:border :border
:border-radius :string-or-size-array
@ -42,6 +46,10 @@
:padding-block-start :size-array
:padding-block-end :size-array
:margin :size-array
:margin-block-start :size-array
:margin-block-end :size-array
:margin-inline-start :size-array
:margin-inline-end :size-array
:grid-template-rows :tracks
:grid-template-columns :tracks})

View File

@ -410,6 +410,26 @@
(when (or (not= m1 0) (not= m2 0) (not= m3 0) (not= m4 0))
[m1 m2 m3 m4]))))
(defmethod get-value :margin-block-start
[_ {:keys [layout-item-margin] :as shape} objects _]
(when (and (ctl/any-layout-immediate-child? objects shape) (:m1 layout-item-margin) (not= (:m1 layout-item-margin) 0))
[(:m1 layout-item-margin)]))
(defmethod get-value :margin-inline-end
[_ {:keys [layout-item-margin] :as shape} objects _]
(when (and (ctl/any-layout-immediate-child? objects shape) (:m2 layout-item-margin) (not= (:m2 layout-item-margin) 0))
[(:m2 layout-item-margin)]))
(defmethod get-value :margin-block-end
[_ {:keys [layout-item-margin] :as shape} objects _]
(when (and (ctl/any-layout-immediate-child? objects shape) (:m3 layout-item-margin) (not= (:m3 layout-item-margin) 0))
[(:m3 layout-item-margin)]))
(defmethod get-value :margin-inline-start
[_ {:keys [layout-item-margin] :as shape} objects _]
(when (and (ctl/any-layout-immediate-child? objects shape) (:m4 layout-item-margin) (not= (:m4 layout-item-margin) 0))
[(:m4 layout-item-margin)]))
(defmethod get-value :z-index
[_ {:keys [layout-item-z-index] :as shape} objects _]
(cond
@ -425,6 +445,10 @@
(ctl/any-layout-immediate-child? objects shape)
(:layout-item-max-h shape)))
(defmethod get-value :max-block-size
[_ shape objects _]
(get-value :max-height shape objects))
(defmethod get-value :min-height
[_ shape objects _]
(cond
@ -434,12 +458,20 @@
(and (ctl/auto-height? shape) (cfh/frame-shape? shape) (not (:show-content shape)))
(-> shape :selrect :height)))
(defmethod get-value :min-block-size
[_ shape objects _]
(get-value :min-height shape objects))
(defmethod get-value :max-width
[_ shape objects _]
(cond
(ctl/any-layout-immediate-child? objects shape)
(:layout-item-max-w shape)))
(defmethod get-value :max-inline-size
[_ shape objects _]
(get-value :max-width shape objects))
(defmethod get-value :min-width
[_ shape objects _]
(cond
@ -449,6 +481,10 @@
(and (ctl/auto-width? shape) (cfh/frame-shape? shape) (not (:show-content shape)))
(-> shape :selrect :width)))
(defmethod get-value :min-inline-size
[_ shape objects _]
(get-value :min-width shape objects))
(defmethod get-value :align-self
[_ shape objects _]
(cond

View File

@ -1877,10 +1877,6 @@ msgstr "Active sets"
msgid "inspect.tabs.styles.panel.geometry"
msgstr "Size & Position"
#: src/app/main/ui/inspect/styles/style_box.cljs:12
msgid "inspect.tabs.styles.panel.layout-element"
msgstr "Layout Element"
#: src/app/main/ui/inspect/styles/style_box.cljs:12
msgid "inspect.tabs.styles.panel.toggle-style"
msgstr "Toggle panel %s"

View File

@ -1883,10 +1883,6 @@ msgstr "Sets activos"
msgid "inspect.tabs.styles.panel.geometry"
msgstr "Tamaño y posición"
#: src/app/main/ui/inspect/styles/style_box.cljs:12
msgid "inspect.tabs.styles.panel.layout-element"
msgstr "Layout de elemento"
#: src/app/main/ui/inspect/styles/style_box.cljs:12
msgid "inspect.tabs.styles.panel.toggle-style"
msgstr "Alternar panel %s"