mirror of
https://github.com/penpot/penpot.git
synced 2026-08-01 19:06:18 +00:00
🎉 Inspect tab layout switcher and computed feature (#7166)
This commit is contained in:
parent
3dd237002b
commit
4290bce718
@ -131,7 +131,8 @@
|
|||||||
:hide-release-modal
|
:hide-release-modal
|
||||||
:subscriptions
|
:subscriptions
|
||||||
:subscriptions-old
|
:subscriptions-old
|
||||||
:frontend-binary-fills})
|
:frontend-binary-fills
|
||||||
|
:inspect-styles})
|
||||||
|
|
||||||
(def all-flags
|
(def all-flags
|
||||||
(set/union email login varia))
|
(set/union email login varia))
|
||||||
|
|||||||
@ -8,15 +8,18 @@
|
|||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.common.types.component :as ctk]
|
[app.common.types.component :as ctk]
|
||||||
|
[app.config :as cf]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
|
[app.main.ui.ds.controls.select :refer [select*]]
|
||||||
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
|
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
|
||||||
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
|
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.main.ui.inspect.attributes :refer [attributes]]
|
[app.main.ui.inspect.attributes :refer [attributes]]
|
||||||
[app.main.ui.inspect.code :refer [code]]
|
[app.main.ui.inspect.code :refer [code]]
|
||||||
[app.main.ui.inspect.selection-feedback :refer [resolve-shapes]]
|
[app.main.ui.inspect.selection-feedback :refer [resolve-shapes]]
|
||||||
|
[app.main.ui.inspect.styles :refer [styles-tab*]]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :refer [tr]]
|
[app.util.i18n :refer [tr]]
|
||||||
[app.util.shape-icon :as usi]
|
[app.util.shape-icon :as usi]
|
||||||
@ -39,11 +42,13 @@
|
|||||||
(mf/defc right-sidebar
|
(mf/defc right-sidebar
|
||||||
[{:keys [frame page objects file selected shapes page-id file-id share-id from on-change-section on-expand]
|
[{:keys [frame page objects file selected shapes page-id file-id share-id from on-change-section on-expand]
|
||||||
:or {from :viewer}}]
|
:or {from :viewer}}]
|
||||||
(let [section (mf/use-state #(do :info))
|
(let [color-space* (mf/use-state "hex")
|
||||||
|
color-space (deref color-space*)
|
||||||
|
|
||||||
|
section (mf/use-state #(if (contains? cf/flags :inspect-styles) :styles :info))
|
||||||
objects (or objects (:objects page))
|
objects (or objects (:objects page))
|
||||||
shapes (or shapes
|
shapes (or shapes
|
||||||
(resolve-shapes objects selected))
|
(resolve-shapes objects selected))
|
||||||
|
|
||||||
first-shape (first shapes)
|
first-shape (first shapes)
|
||||||
page-id (or page-id (:id page))
|
page-id (or page-id (:id page))
|
||||||
file-id (or file-id (:id file))
|
file-id (or file-id (:id file))
|
||||||
@ -82,20 +87,42 @@
|
|||||||
(fn []
|
(fn []
|
||||||
(dom/open-new-window "https://help.penpot.app/user-guide/inspect/")))
|
(dom/open-new-window "https://help.penpot.app/user-guide/inspect/")))
|
||||||
|
|
||||||
|
handle-change-color-space
|
||||||
|
(mf/use-fn
|
||||||
|
(fn [color-space]
|
||||||
|
(reset! color-space* color-space)))
|
||||||
|
|
||||||
|
color-spaces
|
||||||
|
(mf/with-memo []
|
||||||
|
[{:label (tr "inspect.attributes.color.hex")
|
||||||
|
:id "hex"}
|
||||||
|
{:label (tr "inspect.attributes.color.rgba")
|
||||||
|
:id "rgba"}
|
||||||
|
{:label (tr "inspect.attributes.color.hsla")
|
||||||
|
:id "hsla"}])
|
||||||
|
|
||||||
tabs
|
tabs
|
||||||
(mf/with-memo []
|
(mf/with-memo []
|
||||||
[{:label (tr "inspect.tabs.info")
|
(if (contains? cf/flags :inspect-styles)
|
||||||
:id "info"}
|
[{:label (tr "inspect.tabs.styles")
|
||||||
{:label (tr "inspect.tabs.code")
|
:id "styles"}
|
||||||
:data-testid "code"
|
{:label (tr "inspect.tabs.computed")
|
||||||
:id "code"}])]
|
:id "computed"}
|
||||||
|
{:label (tr "inspect.tabs.code")
|
||||||
|
:data-testid "code"
|
||||||
|
:id "code"}]
|
||||||
|
[{:label (tr "inspect.tabs.info")
|
||||||
|
:id "info"}
|
||||||
|
{:label (tr "inspect.tabs.code")
|
||||||
|
:data-testid "code"
|
||||||
|
:id "code"}]))]
|
||||||
|
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
(mf/deps shapes handle-change-tab)
|
(mf/deps shapes handle-change-tab)
|
||||||
(fn []
|
(fn []
|
||||||
(if (seq shapes)
|
(if (seq shapes)
|
||||||
(st/emit! (ptk/event ::ev/event {::ev/name "inspect-mode-click-element"}))
|
(st/emit! (ptk/event ::ev/event {::ev/name "inspect-mode-click-element"}))
|
||||||
(handle-change-tab :info))))
|
(handle-change-tab (if (contains? cf/flags :inspect-styles) :styles :info)))))
|
||||||
|
|
||||||
[:aside {:class (stl/css-case :settings-bar-right true
|
[:aside {:class (stl/css-case :settings-bar-right true
|
||||||
:viewer-code (= from :viewer))}
|
:viewer-code (= from :viewer))}
|
||||||
@ -133,27 +160,63 @@
|
|||||||
[:div {:class (stl/css :layer-title)} (:name first-shape)]])]])]
|
[:div {:class (stl/css :layer-title)} (:name first-shape)]])]])]
|
||||||
|
|
||||||
[:div {:class (stl/css :inspect-content)}
|
[:div {:class (stl/css :inspect-content)}
|
||||||
|
(if (contains? cf/flags :inspect-styles)
|
||||||
|
[:div {:class (stl/css :inspect-tab-switcher)}
|
||||||
|
[:span {:class (stl/css :inspect-tab-switcher-label)} (tr "inspect.tabs.switcher.label")]
|
||||||
|
[:div {:class (stl/css :inspect-tab-switcher-controls)}
|
||||||
|
[:div {:class (stl/css :inspect-tab-switcher-controls-color-space)}
|
||||||
|
[:> select* {:options color-spaces
|
||||||
|
:default-selected "hex"
|
||||||
|
:on-change handle-change-color-space}]]
|
||||||
|
[:div {:class (stl/css :inspect-tab-switcher-controls-tab)}
|
||||||
|
[:> select* {:options tabs
|
||||||
|
:default-selected (name @section)
|
||||||
|
:on-change handle-change-tab}]]]]
|
||||||
|
nil)
|
||||||
|
|
||||||
[:> tab-switcher* {:tabs tabs
|
(if (contains? cf/flags :inspect-styles)
|
||||||
:selected (name @section)
|
[:div {:class (stl/css :inspect-tab :viewer-tab-switcher :viewer-tab-switcher-layout)}
|
||||||
:on-change handle-change-tab
|
(case @section
|
||||||
:class (stl/css :viewer-tab-switcher)}
|
:styles
|
||||||
(case @section
|
[:> styles-tab* {:color-space color-space
|
||||||
:info
|
:shapes shapes
|
||||||
[:& attributes {:page-id page-id
|
:libraries libraries
|
||||||
:objects objects
|
:file-id file-id}]
|
||||||
:file-id file-id
|
:computed
|
||||||
:frame frame
|
[:& attributes {:page-id page-id
|
||||||
:shapes shapes
|
:objects objects
|
||||||
:from from
|
:file-id file-id
|
||||||
:libraries libraries
|
:frame frame
|
||||||
:share-id share-id}]
|
:shapes shapes
|
||||||
|
:from from
|
||||||
|
:libraries libraries
|
||||||
|
:share-id share-id}]
|
||||||
|
|
||||||
:code
|
:code
|
||||||
[:& code {:frame frame
|
[:& code {:frame frame
|
||||||
:shapes shapes
|
:shapes shapes
|
||||||
:on-expand handle-expand
|
:on-expand handle-expand
|
||||||
:from from}])]]]
|
:from from}])]
|
||||||
|
[:> tab-switcher* {:tabs tabs
|
||||||
|
:selected (name @section)
|
||||||
|
:on-change handle-change-tab
|
||||||
|
:class (stl/css :viewer-tab-switcher)}
|
||||||
|
(case @section
|
||||||
|
:info
|
||||||
|
[:& attributes {:page-id page-id
|
||||||
|
:objects objects
|
||||||
|
:file-id file-id
|
||||||
|
:frame frame
|
||||||
|
:shapes shapes
|
||||||
|
:from from
|
||||||
|
:libraries libraries
|
||||||
|
:share-id share-id}]
|
||||||
|
|
||||||
|
:code
|
||||||
|
[:& code {:frame frame
|
||||||
|
:shapes shapes
|
||||||
|
:on-expand handle-expand
|
||||||
|
:from from}])])]]
|
||||||
[:div {:class (stl/css :empty)}
|
[:div {:class (stl/css :empty)}
|
||||||
[:div {:class (stl/css :code-info)}
|
[:div {:class (stl/css :code-info)}
|
||||||
[:span {:class (stl/css :placeholder-icon)}
|
[:span {:class (stl/css :placeholder-icon)}
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
//
|
//
|
||||||
// Copyright (c) KALEIDOS INC
|
// Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
@use "../ds/typography.scss" as *;
|
||||||
@import "refactor/common-refactor.scss";
|
@import "refactor/common-refactor.scss";
|
||||||
|
|
||||||
.settings-bar-right {
|
.settings-bar-right {
|
||||||
@ -106,6 +107,34 @@
|
|||||||
padding: $s-8 $s-24;
|
padding: $s-8 $s-24;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inspect-tab-switcher {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding-block: var(--sp-s);
|
||||||
|
padding-inline-end: var(--sp-m);
|
||||||
|
}
|
||||||
|
|
||||||
|
.inspect-tab-switcher-label {
|
||||||
|
@include use-typography("body-medium");
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inspect-tab-switcher-controls {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex: 2;
|
||||||
|
gap: var(--sp-s);
|
||||||
|
}
|
||||||
|
|
||||||
|
.inspect-tab-switcher-controls-color-space {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inspect-tab-switcher-controls-tab {
|
||||||
|
flex: 2;
|
||||||
|
}
|
||||||
|
|
||||||
.inspect-content {
|
.inspect-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -115,3 +144,7 @@
|
|||||||
--tabs-nav-padding-inline-start: 0;
|
--tabs-nav-padding-inline-start: 0;
|
||||||
--tabs-nav-padding-inline-end: var(--sp-m);
|
--tabs-nav-padding-inline-end: var(--sp-m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.viewer-tab-switcher-layout {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
|||||||
61
frontend/src/app/main/ui/inspect/styles.cljs
Normal file
61
frontend/src/app/main/ui/inspect/styles.cljs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
(ns app.main.ui.inspect.styles
|
||||||
|
(:require-macros [app.main.style :as stl])
|
||||||
|
(:require
|
||||||
|
[app.common.data.macros :as dm]
|
||||||
|
[app.common.types.component :as ctc]
|
||||||
|
[app.common.types.components-list :as ctkl]
|
||||||
|
[app.main.ui.inspect.styles.style-box :refer [style-box*]]
|
||||||
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
|
||||||
|
(def type->options
|
||||||
|
{:multiple [:fill :stroke :text :shadow :blur :layout-element]
|
||||||
|
:frame [:visibility :geometry :fill :stroke :shadow :blur :layout :layout-element]
|
||||||
|
:group [:visibility :geometry :svg :layout-element]
|
||||||
|
:rect [:visibility :geometry :fill :stroke :shadow :blur :svg :layout-element]
|
||||||
|
:circle [:visibility :geometry :fill :stroke :shadow :blur :svg :layout-element]
|
||||||
|
:path [:visibility :geometry :fill :stroke :shadow :blur :svg :layout-element]
|
||||||
|
:text [:visibility :geometry :text :shadow :blur :stroke :layout-element]
|
||||||
|
:variant [:variant :geometry :fill :stroke :shadow :blur :layout :layout-element]})
|
||||||
|
|
||||||
|
(defn- get-shape-type
|
||||||
|
[shapes first-shape first-component]
|
||||||
|
(cond
|
||||||
|
(and (= (count shapes) 1)
|
||||||
|
(or (ctc/is-variant-container? first-shape)
|
||||||
|
(ctc/is-variant? first-component)))
|
||||||
|
:variant
|
||||||
|
|
||||||
|
(= (count shapes) 1)
|
||||||
|
(:type first-shape)
|
||||||
|
|
||||||
|
:else
|
||||||
|
:multiple))
|
||||||
|
|
||||||
|
(mf/defc styles-tab*
|
||||||
|
[{:keys [color-space shapes libraries file-id]}]
|
||||||
|
(let [data (dm/get-in libraries [file-id :data])
|
||||||
|
first-shape (first shapes)
|
||||||
|
first-component (ctkl/get-component data (:component-id first-shape))
|
||||||
|
type (get-shape-type shapes first-shape first-component)
|
||||||
|
options (type->options type)]
|
||||||
|
|
||||||
|
[:div {:class (stl/css :element-options)}
|
||||||
|
(for [[idx option] (map-indexed vector options)]
|
||||||
|
[:> style-box* {:key idx :attribute option} color-space])]))
|
||||||
|
|
||||||
|
|
||||||
|
;; WIP
|
||||||
|
;; Panel list as stylebox children
|
||||||
|
#_(case option
|
||||||
|
:geometry [:> geometry-panel {}]
|
||||||
|
:layout [:> layout-panel {}]
|
||||||
|
:layout-element [:> layout-element-panel {}]
|
||||||
|
:fill [:> fill-panel {:color-space color-space}]
|
||||||
|
:stroke [:> stroke-panel {:color-space color-space}]
|
||||||
|
:text [:> text-panel {:color-space color-space}]
|
||||||
|
:shadow [:> shadow-panel {}]
|
||||||
|
:blur [:> blur-panel {}]
|
||||||
|
:svg [:> svg-panel {}]
|
||||||
|
:variant [:> variant-panel* {}]
|
||||||
|
:visibility [:> visibility-panel* {}])
|
||||||
26
frontend/src/app/main/ui/inspect/styles/style_box.cljs
Normal file
26
frontend/src/app/main/ui/inspect/styles/style_box.cljs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
(ns app.main.ui.inspect.styles.style-box
|
||||||
|
(:require-macros [app.main.style :as stl])
|
||||||
|
(:require
|
||||||
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
(defn- attribute->title
|
||||||
|
[type]
|
||||||
|
(case type
|
||||||
|
:variant "Variant properties"
|
||||||
|
:token "Token Sets & Themes"
|
||||||
|
:geometry "Size & Position"
|
||||||
|
:fill "Fill"
|
||||||
|
:stroke "Stroke"
|
||||||
|
:text "Text"
|
||||||
|
:shadow "Shadow"
|
||||||
|
:layout "Layout"
|
||||||
|
:layout-element "Layout Element"
|
||||||
|
:visibility "Visibility"
|
||||||
|
:svg "SVG"
|
||||||
|
nil))
|
||||||
|
|
||||||
|
(mf/defc style-box*
|
||||||
|
[{:keys [attribute children]}]
|
||||||
|
[:div {:class (stl/css :style-box)}
|
||||||
|
[:h3 {:class (stl/css :style-box-header)} (attribute->title attribute)]
|
||||||
|
[:div {:class (stl/css :style-box-content)} children]])
|
||||||
@ -1761,8 +1761,12 @@ msgid "inspect.subtitle.main"
|
|||||||
msgstr "Main component"
|
msgstr "Main component"
|
||||||
|
|
||||||
#: src/app/main/ui/inspect/right_sidebar.cljs:59
|
#: src/app/main/ui/inspect/right_sidebar.cljs:59
|
||||||
msgid "inspect.subtitle.variant"
|
msgid "inspect.tabs.switcher.label"
|
||||||
msgstr "Variant"
|
msgstr "Layer info"
|
||||||
|
|
||||||
|
#: src/app/main/ui/inspect/right_sidebar.cljs:101
|
||||||
|
msgid "inspect.tabs.computed"
|
||||||
|
msgstr "Computed"
|
||||||
|
|
||||||
#: src/app/main/ui/inspect/right_sidebar.cljs:105
|
#: src/app/main/ui/inspect/right_sidebar.cljs:105
|
||||||
msgid "inspect.tabs.code"
|
msgid "inspect.tabs.code"
|
||||||
@ -1820,6 +1824,10 @@ msgstr "Text"
|
|||||||
msgid "inspect.tabs.info"
|
msgid "inspect.tabs.info"
|
||||||
msgstr "Info"
|
msgstr "Info"
|
||||||
|
|
||||||
|
#: src/app/main/ui/inspect/right_sidebar.cljs:101
|
||||||
|
msgid "inspect.tabs.styles"
|
||||||
|
msgstr "Styles"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/comments.cljs:95
|
#: src/app/main/ui/dashboard/comments.cljs:95
|
||||||
msgid "label.mark-all-as-read"
|
msgid "label.mark-all-as-read"
|
||||||
msgstr "Mark all as read"
|
msgstr "Mark all as read"
|
||||||
|
|||||||
@ -1768,6 +1768,14 @@ msgstr "Componente principal"
|
|||||||
msgid "inspect.subtitle.variant"
|
msgid "inspect.subtitle.variant"
|
||||||
msgstr "Variante"
|
msgstr "Variante"
|
||||||
|
|
||||||
|
#: src/app/main/ui/inspect/right_sidebar.cljs:59
|
||||||
|
msgid "inspect.tabs.switcher.label"
|
||||||
|
msgstr "Información sobre la capa"
|
||||||
|
|
||||||
|
#: src/app/main/ui/inspect/right_sidebar.cljs:101
|
||||||
|
msgid "inspect.tabs.computed"
|
||||||
|
msgstr "Calculado"
|
||||||
|
|
||||||
#: src/app/main/ui/inspect/right_sidebar.cljs:105
|
#: src/app/main/ui/inspect/right_sidebar.cljs:105
|
||||||
msgid "inspect.tabs.code"
|
msgid "inspect.tabs.code"
|
||||||
msgstr "Código"
|
msgstr "Código"
|
||||||
@ -1824,6 +1832,10 @@ msgstr "Texto"
|
|||||||
msgid "inspect.tabs.info"
|
msgid "inspect.tabs.info"
|
||||||
msgstr "Información"
|
msgstr "Información"
|
||||||
|
|
||||||
|
#: src/app/main/ui/inspect/right_sidebar.cljs:101
|
||||||
|
msgid "inspect.tabs.styles"
|
||||||
|
msgstr "Estilos"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/comments.cljs:95
|
#: src/app/main/ui/dashboard/comments.cljs:95
|
||||||
msgid "label.mark-all-as-read"
|
msgid "label.mark-all-as-read"
|
||||||
msgstr "Marcar todo como leído"
|
msgstr "Marcar todo como leído"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user