Enable single color-space selector for styles and computed… (#7525)

*  Enable single color-space selector for styles and computed tab
This commit is contained in:
Xaviju 2025-10-29 09:53:37 +01:00 committed by GitHub
parent 7565bb8d24
commit 93fb54c116
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 187 additions and 127 deletions

View File

@ -783,7 +783,7 @@
.attr-row { .attr-row {
display: grid; display: grid;
grid-template-areas: "name content"; grid-template-areas: "name content";
grid-template-columns: $s-92 1fr; grid-template-columns: 1fr 3fr;
gap: $s-4; gap: $s-4;
height: $s-32; height: $s-32;
:global(.attr-label) { :global(.attr-label) {

View File

@ -314,7 +314,7 @@
--modal-button-foreground-color-error: var(--color-foreground-primary); --modal-button-foreground-color-error: var(--color-foreground-primary);
--modal-link-foreground-color: var(--color-accent-primary); --modal-link-foreground-color: var(--color-accent-primary);
--modal-border-color: var(--color-background-quaternary); --modal-border-color: var(--color-background-quaternary);
--modal-separator-backogrund-color: var(--color-background-quaternary); --modal-separator-background-color: var(--color-background-quaternary);
--modal-navigator-foreground-color-rest: var(--color-background-quaternary); --modal-navigator-foreground-color-rest: var(--color-background-quaternary);
--modal-navigator-foreground-color-active: var(--color-accent-primary); --modal-navigator-foreground-color-active: var(--color-accent-primary);

View File

@ -27,7 +27,7 @@
} }
.separator { .separator {
border-color: var(--modal-separator-backogrund-color); border-color: var(--modal-separator-background-color);
margin: 0; margin: 0;
} }

View File

@ -13,12 +13,12 @@
[app.main.ui.hooks :as hooks] [app.main.ui.hooks :as hooks]
[app.main.ui.inspect.annotation :refer [annotation]] [app.main.ui.inspect.annotation :refer [annotation]]
[app.main.ui.inspect.attributes.blur :refer [blur-panel]] [app.main.ui.inspect.attributes.blur :refer [blur-panel]]
[app.main.ui.inspect.attributes.fill :refer [fill-panel]] [app.main.ui.inspect.attributes.fill :refer [fill-panel*]]
[app.main.ui.inspect.attributes.geometry :refer [geometry-panel]] [app.main.ui.inspect.attributes.geometry :refer [geometry-panel]]
[app.main.ui.inspect.attributes.layout :refer [layout-panel]] [app.main.ui.inspect.attributes.layout :refer [layout-panel]]
[app.main.ui.inspect.attributes.layout-element :refer [layout-element-panel]] [app.main.ui.inspect.attributes.layout-element :refer [layout-element-panel]]
[app.main.ui.inspect.attributes.shadow :refer [shadow-panel]] [app.main.ui.inspect.attributes.shadow :refer [shadow-panel]]
[app.main.ui.inspect.attributes.stroke :refer [stroke-panel]] [app.main.ui.inspect.attributes.stroke :refer [stroke-panel*]]
[app.main.ui.inspect.attributes.svg :refer [svg-panel]] [app.main.ui.inspect.attributes.svg :refer [svg-panel]]
[app.main.ui.inspect.attributes.text :refer [text-panel]] [app.main.ui.inspect.attributes.text :refer [text-panel]]
[app.main.ui.inspect.attributes.variant :refer [variant-panel*]] [app.main.ui.inspect.attributes.variant :refer [variant-panel*]]
@ -37,7 +37,7 @@
:variant [:variant :geometry :fill :stroke :shadow :blur :layout :layout-element]}) :variant [:variant :geometry :fill :stroke :shadow :blur :layout :layout-element]})
(mf/defc attributes (mf/defc attributes
[{:keys [page-id file-id shapes frame from libraries share-id objects]}] [{:keys [page-id file-id shapes frame from libraries share-id objects color-space]}]
(let [shapes (hooks/use-equal-memo shapes) (let [shapes (hooks/use-equal-memo shapes)
first-shape (first shapes) first-shape (first shapes)
data (dm/get-in libraries [file-id :data]) data (dm/get-in libraries [file-id :data])
@ -64,8 +64,8 @@
:geometry geometry-panel :geometry geometry-panel
:layout layout-panel :layout layout-panel
:layout-element layout-element-panel :layout-element layout-element-panel
:fill fill-panel :fill fill-panel*
:stroke stroke-panel :stroke stroke-panel*
:shadow shadow-panel :shadow shadow-panel
:blur blur-panel :blur blur-panel
:visibility visibility-panel* :visibility visibility-panel*
@ -74,6 +74,7 @@
:variant variant-panel*) :variant variant-panel*)
{:key idx {:key idx
:shapes shapes :shapes shapes
:color-space color-space
:objects objects :objects objects
:frame frame :frame frame
:from from :from from

View File

@ -9,13 +9,13 @@
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.media :as cm]
[app.common.types.color :as cc] [app.common.types.color :as cc]
[app.config :as cf] [app.config :as cf]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.ui.components.color-bullet :as cb] [app.main.ui.components.color-bullet :as cb]
[app.main.ui.components.copy-button :refer [copy-button*]] [app.main.ui.components.copy-button :refer [copy-button*]]
[app.main.ui.components.select :refer [select]] [app.main.ui.components.select :refer [select]]
[app.main.ui.ds.buttons.button :refer [button*]]
[app.main.ui.formats :as fmt] [app.main.ui.formats :as fmt]
[app.main.ui.inspect.common.colors :as isc] [app.main.ui.inspect.common.colors :as isc]
[app.util.i18n :refer [tr]] [app.util.i18n :refer [tr]]
@ -29,7 +29,7 @@
(str/join " " $) (str/join " " $)
(str/capital $))) (str/capital $)))
(mf/defc color-row [{:keys [color format copy-data on-change-format]}] (mf/defc color-row [{:keys [color format copy-data property on-change-format]}]
(let [colors-library (isc/use-colors-library color) (let [colors-library (isc/use-colors-library color)
file-colors-ref (mf/deref isc/file-colors-ref) file-colors-ref (mf/deref isc/file-colors-ref)
file-colors-wokspace (mf/deref refs/workspace-file-colors) file-colors-wokspace (mf/deref refs/workspace-file-colors)
@ -40,9 +40,7 @@
(if image (if image
(let [mtype (-> image :mtype) (let [name (or (:name image) (tr "media.image"))]
name (or (:name image) (tr "media.image"))
extension (cm/mtype->extension mtype)]
[:div {:class (stl/css :attributes-image-as-color-row)} [:div {:class (stl/css :attributes-image-as-color-row)}
[:div {:class (stl/css :attributes-color-row)} [:div {:class (stl/css :attributes-color-row)}
[:div {:class (stl/css :bullet-wrapper) [:div {:class (stl/css :bullet-wrapper)
@ -69,12 +67,13 @@
[:div {:class (stl/css :image-download)} [:div {:class (stl/css :image-download)}
[:div {:class (stl/css :image-wrapper)} [:div {:class (stl/css :image-wrapper)}
[:img {:src (cf/resolve-file-media image)}]] [:img {:class (stl/css :resolved-image) :src (cf/resolve-file-media image)}]]
[:a {:class (stl/css :download-button) [:> button* {:class (stl/css :download-button)
:target "_blank" :variant "secondary"
:download (cond-> name extension (str/concat extension)) :target "_blank"
:href (cf/resolve-file-media image)} :download name
:to (cf/resolve-file-media image)}
(tr "inspect.attributes.image.download")]]]]) (tr "inspect.attributes.image.download")]]]])
[:div {:class (stl/css :attributes-color-row)} [:div {:class (stl/css :attributes-color-row)}
@ -82,18 +81,20 @@
:style #js {"--bullet-size" "16px"}} :style #js {"--bullet-size" "16px"}}
[:& cb/color-bullet {:color color [:& cb/color-bullet {:color color
:mini true}]] :mini true}]]
;; REMOVE this conditional when :inspect-styles flag is removed
[:div {:class (stl/css :format-wrapper)} (if (contains? cf/flags :inspect-styles)
(when-not (and on-change-format (or (:gradient color) image)) [:div {:class (stl/css :global/attr-label)} property]
[:& select [:div {:class (stl/css :format-wrapper)}
{:default-value format (when-not (and on-change-format (or (:gradient color) image))
:class (stl/css :select-format-wrapper) [:& select
:options [{:value :hex :label (tr "inspect.attributes.color.hex")} {:default-value format
{:value :rgba :label (tr "inspect.attributes.color.rgba")} :class (stl/css :select-format-wrapper)
{:value :hsla :label (tr "inspect.attributes.color.hsla")}] :options [{:value :hex :label (tr "inspect.attributes.color.hex")}
:on-change on-change-format}]) {:value :rgba :label (tr "inspect.attributes.color.rgba")}
(when (:gradient color) {:value :hsla :label (tr "inspect.attributes.color.hsla")}]
[:div {:class (stl/css :format-info)} "rgba"])] :on-change on-change-format}])
(when (:gradient color)
[:div {:class (stl/css :format-info)} "rgba"])])
[:> copy-button* {:data copy-data [:> copy-button* {:data copy-data
:aria-label (tr "labels.copy-color") :aria-label (tr "labels.copy-color")

View File

@ -6,65 +6,69 @@
@use "refactor/common-refactor.scss" as deprecated; @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 *;
@use "ds/mixins.scss" as *;
.attributes-image-as-color-row { .attributes-image-as-color-row {
max-width: deprecated.$s-240; max-inline-size: px2rem(240);
} }
.attributes-color-row { .attributes-color-row {
display: grid; display: grid;
grid-template-columns: deprecated.$s-16 deprecated.$s-72 deprecated.$s-144; grid-template-columns: auto auto 1fr;
gap: deprecated.$s-4; gap: var(--sp-xs);
align-items: center;
}
.attributes-color-row {
@extend .attr-row;
} }
.bullet-wrapper { .bullet-wrapper {
@include deprecated.flexCenter; display: flex;
height: deprecated.$s-32; justify-content: center;
align-items: center;
block-size: $sz-32;
} }
.format-wrapper { .format-wrapper {
width: deprecated.$s-72; inline-size: px2rem(72);
height: deprecated.$s-32; block-size: $sz-32;
} }
.image-format { .image-format {
@include deprecated.uppercaseTitleTipography; @include use-typography("headline-small");
height: deprecated.$s-32; block-size: $sz-32;
padding: deprecated.$s-8 0; padding: var(--sp-s) 0;
color: var(--menu-foreground-color-rest); color: var(--color-foreground-secondary);
} }
.select-format-wrapper { .select-format-wrapper {
width: 100%; inline-size: 100%;
padding: deprecated.$s-8 deprecated.$s-2; padding: var(--sp-s) var(--sp-xxs);
background-color: transparent; background-color: transparent;
border-color: transparent; border-color: transparent;
color: var(--menu-foreground-color-rest); color: var(--color-foreground-secondary);
} }
.format-info { .format-info {
@include deprecated.uppercaseTitleTipography; @include use-typography("body-small");
display: flex; padding-left: var(--sp-xxs);
align-items: center; color: var(--color-foreground-secondary);
width: 100%;
height: 100%;
padding-left: deprecated.$s-2;
font-size: deprecated.$fs-12;
color: var(--menu-foreground-color-rest);
}
.color-row-copy-btn {
max-width: deprecated.$s-144;
} }
.color-info { .color-info {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
gap: deprecated.$s-4; gap: var(--sp-xs);
flex-grow: 1; flex-grow: 1;
max-width: deprecated.$s-144; max-inline-size: px2rem(144);
button { button {
visibility: hidden; visibility: hidden;
min-width: deprecated.$s-28; min-inline-size: px2rem(28);
} }
&:hover button { &:hover button {
visibility: visible; visibility: visible;
@ -72,73 +76,67 @@
} }
.one-line { .one-line {
max-height: deprecated.$s-32; max-block-size: $sz-32;
} }
.two-line { .two-line {
display: grid; display: grid;
grid-template-rows: auto 1fr; grid-template-rows: auto 1fr;
gap: deprecated.$s-4; gap: var(--sp-xs);
} }
.color-name-wrapper { .color-name-wrapper {
@include deprecated.bodySmallTypography; @include use-typography("body-small");
@include deprecated.flexColumn; display: flex;
padding: deprecated.$s-8 deprecated.$s-4 deprecated.$s-8 deprecated.$s-8; flex-direction: column;
height: deprecated.$s-32; gap: var(--sp-xs);
max-width: deprecated.$s-80; padding: var(--sp-s);
} padding-inline-end: var(--sp-xs);
block-size: $sz-32;
.opacity-info { max-inline-size: px2rem(80);
@include deprecated.bodySmallTypography;
color: var(--menu-foreground-color);
padding: deprecated.$s-8 0;
} }
.first-row { .first-row {
display: grid; display: grid;
grid-template-columns: 1fr deprecated.$s-28; grid-template-columns: 1fr px2rem(28);
height: fit-content;
width: 100%;
padding: 0;
margin: 0;
} }
.name-opacity { .name-opacity {
height: fit-content; line-height: $sz-16;
width: 100%;
line-height: deprecated.$s-16;
display: grid; display: grid;
grid-template-columns: 1fr auto; grid-template-columns: 1fr auto;
} }
.color-value-wrapper { .color-value-wrapper {
@include deprecated.textEllipsis; @include use-typography("body-small");
@include deprecated.inspectValue; @include textEllipsis;
color: var(--menu-foreground-color);
text-transform: uppercase; text-transform: uppercase;
&.gradient-name { }
text-transform: none;
} .gradient-name {
text-transform: none;
} }
.opacity-info { .opacity-info {
@include deprecated.inspectValue; @include use-typography("body-small");
color: var(--menu-foreground-color);
text-transform: uppercase; text-transform: uppercase;
width: 100%; inline-size: 100%;
} }
.second-row { .second-row {
min-height: deprecated.$s-16; min-block-size: $sz-16;
padding-right: deprecated.$s-8; padding-right: var(--sp-s);
width: 100%; inline-size: 100%;
text-align: left; text-align: left;
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
.color-name-library { .color-name-library {
@include deprecated.inspectValue; @include use-typography("body-small");
color: var(--menu-foreground-color-rest); color: var(--color-foreground-secondary);
word-break: break-word; word-break: break-word;
} }
@ -147,27 +145,27 @@
} }
.download-button { .download-button {
@extend .button-secondary; justify-content: center;
@include deprecated.uppercaseTitleTipography; inline-size: 100%;
height: deprecated.$s-32; margin-block-start: var(--sp-xs);
width: 100%;
margin-top: deprecated.$s-4;
} }
.image-wrapper { .image-wrapper {
background-color: var(--menu-background-color); background-color: var(--menu-background-color);
position: relative; position: relative;
@include deprecated.flexCenter; display: flex;
width: deprecated.$s-240; justify-content: center;
height: deprecated.$s-160; align-items: center;
max-height: deprecated.$s-160; inline-size: px2rem(248);
max-width: deprecated.$s-248; block-size: px2rem(160);
margin: deprecated.$s-8 0; max-block-size: px2rem(160);
border-radius: deprecated.$br-8; max-inline-size: px2rem(248);
margin: var(--sp-s) 0;
img { border-radius: $br-8;
height: 100%; }
width: 100%;
object-fit: contain; .resolved-image {
} block-size: 100%;
inline-size: 100%;
object-fit: contain;
} }

View File

@ -7,7 +7,9 @@
(ns app.main.ui.inspect.attributes.fill (ns app.main.ui.inspect.attributes.fill
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.common.data :as d]
[app.common.types.fills :as types.fills] [app.common.types.fills :as types.fills]
[app.config :as cf]
[app.main.ui.components.title-bar :refer [inspect-title-bar*]] [app.main.ui.components.title-bar :refer [inspect-title-bar*]]
[app.main.ui.inspect.attributes.common :refer [color-row]] [app.main.ui.inspect.attributes.common :refer [color-row]]
[app.util.code-gen.style-css :as css] [app.util.code-gen.style-css :as css]
@ -23,6 +25,8 @@
(:fill-color-gradient shape) (:fill-color-gradient shape)
(seq (:fills shape))))) (seq (:fills shape)))))
;; DEPRECATED, use fill-block-styles* instead.
;; This component is kept for backward compatibility
(mf/defc fill-block (mf/defc fill-block
{::mf/wrap-props false} {::mf/wrap-props false}
[{:keys [objects shape]}] [{:keys [objects shape]}]
@ -40,12 +44,25 @@
[:& color-row [:& color-row
{:color color {:color color
:format format :format format
:property "Background"
:on-change-format on-change :on-change-format on-change
:copy-data (css/get-shape-properties-css objects {:fills [shape]} properties {:format format})}]])) :copy-data (css/get-shape-properties-css objects {:fills [shape]} properties {:format format})}]]))
(mf/defc fill-panel ;; New implementation of fill-block using the new color format selector
{::mf/wrap-props false} ;; This component is used when the flag :inspect-styles is enabled. Update when flag no longer needed.
[{:keys [shapes]}] (mf/defc fill-block-styles*
[{:keys [objects shape color-space]}]
(let [color (types.fills/fill->color shape)]
[:div {:class (stl/css :attributes-fill-block)}
[:& color-row
{:color color
:property "Background"
:format (d/nilv (keyword color-space) :hex)
:copy-data (css/get-shape-properties-css objects {:fills [shape]} properties {:format (keyword color-space)})}]]))
(mf/defc fill-panel*
[{:keys [shapes color-space]}]
(let [shapes (filter has-fill? shapes)] (let [shapes (filter has-fill? shapes)]
(when (seq shapes) (when (seq shapes)
[:div {:class (stl/css :attributes-block)} [:div {:class (stl/css :attributes-block)}
@ -55,9 +72,18 @@
[:div {:class (stl/css :attributes-content)} [:div {:class (stl/css :attributes-content)}
(for [shape shapes] (for [shape shapes]
(if (seq (:fills shape)) (if (contains? cf/flags :inspect-styles)
(for [value (:fills shape [])] (if (seq (:fills shape))
[:& fill-block {:key (str "fill-block-" (:id shape) value) (for [value (:fills shape [])]
:shape value}]) [:> fill-block-styles* {:key (str "fill-block-" (:id shape) value)
[:& fill-block {:key (str "fill-block-only" (:id shape)) :color-space color-space
:shape shape}]))]]))) :shape value}])
[:> fill-block-styles* {:key (str "fill-block-only" (:id shape))
:color-space color-space
:shape shape}])
(if (seq (:fills shape))
(for [value (:fills shape [])]
[:& fill-block {:key (str "fill-block-" (:id shape) value)
:shape value}])
[:& fill-block {:key (str "fill-block-only" (:id shape))
:shape shape}])))]])))

View File

@ -7,6 +7,8 @@
(ns app.main.ui.inspect.attributes.stroke (ns app.main.ui.inspect.attributes.stroke
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.common.data :as d]
[app.config :as cf]
[app.main.ui.components.copy-button :refer [copy-button*]] [app.main.ui.components.copy-button :refer [copy-button*]]
[app.main.ui.components.title-bar :refer [inspect-title-bar*]] [app.main.ui.components.title-bar :refer [inspect-title-bar*]]
[app.main.ui.inspect.attributes.common :as cmm] [app.main.ui.inspect.attributes.common :as cmm]
@ -27,6 +29,8 @@
(defn- has-stroke? [shape] (defn- has-stroke? [shape]
(seq (:strokes shape))) (seq (:strokes shape)))
;; DEPRECATED, use stroke-block-styles* instead.
;; This component is kept for backward compatibility
(mf/defc stroke-block (mf/defc stroke-block
{::mf/wrap-props false} {::mf/wrap-props false}
[{:keys [objects shape stroke]}] [{:keys [objects shape stroke]}]
@ -50,12 +54,35 @@
[:div {:class (stl/css :button-children)} property-value]]]])) [:div {:class (stl/css :button-children)} property-value]]]]))
[:& cmm/color-row [:& cmm/color-row
{:color color {:color color
:property "Border color"
:format format :format format
:on-change-format on-change :on-change-format on-change
:copy-data (css/get-shape-properties-css objects {:strokes [shape]} properties)}]])) :copy-data (css/get-shape-properties-css objects {:strokes [shape]} properties)}]]))
(mf/defc stroke-panel ;; New implementation of stroke-block using the new color format selector
[{:keys [shapes]}] ;; This component is used when the flag :inspect-styles is enabled. Update when flag no longer needed.
(mf/defc stroke-block-styles*
[{:keys [objects shape stroke color-space]}]
(let [color (stroke->color stroke)]
[:div {:class (stl/css :attributes-fill-block)}
(for [property properties]
(let [property-name (cmm/get-css-rule-humanized property)
property-value (css/get-css-value objects stroke property)]
[:div {:class (stl/css :stroke-row) :key (str "stroke-" (:id shape) "-" property)}
[:div {:class (stl/css :global/attr-label)}
property-name]
[:div {:class (stl/css :global/attr-value)}
[:> copy-button* {:data (css/get-css-property objects stroke property)}
[:div {:class (stl/css :button-children)} property-value]]]]))
[:> cmm/color-row
{:color color
:property "Border color"
:format (d/nilv (keyword color-space) :hex)
:copy-data (css/get-shape-properties-css objects {:strokes [shape]} properties {:format (keyword color-space)})}]]))
(mf/defc stroke-panel*
[{:keys [shapes color-space]}]
(let [shapes (->> shapes (filter has-stroke?))] (let [shapes (->> shapes (filter has-stroke?))]
(when (seq shapes) (when (seq shapes)
[:div {:class (stl/css :attributes-block)} [:div {:class (stl/css :attributes-block)}
@ -66,6 +93,12 @@
[:div {:class (stl/css :attributes-content)} [:div {:class (stl/css :attributes-content)}
(for [shape shapes] (for [shape shapes]
(for [stroke (:strokes shape)] (for [stroke (:strokes shape)]
[:& stroke-block {:key (str "stroke-color-" (:id shape) stroke)
:shape shape (if (contains? cf/flags :inspect-styles)
:stroke stroke}]))]]))) [:> stroke-block-styles* {:key (str "stroke-color-" (:id shape) stroke)
:shape shape
:color-space color-space
:stroke stroke}]
[:& stroke-block {:key (str "stroke-color-" (:id shape) stroke)
:shape shape
:stroke stroke}])))]])))

View File

@ -185,7 +185,8 @@
:libraries libraries :libraries libraries
:file-id file-id}] :file-id file-id}]
:computed :computed
[:& attributes {:page-id page-id [:& attributes {:color-space color-space
:page-id page-id
:objects objects :objects objects
:file-id file-id :file-id file-id
:frame frame :frame frame

View File

@ -121,7 +121,7 @@
height: 100%; height: 100%;
border-radius: deprecated.$br-8; border-radius: deprecated.$br-8;
opacity: 42%; opacity: 42%;
background-color: var(--modal-separator-backogrund-color); background-color: var(--modal-separator-background-color);
} }
// MODAL RIGHT TEAM // MODAL RIGHT TEAM

View File

@ -331,7 +331,7 @@
hr { hr {
margin: deprecated.$s-20 0; margin: deprecated.$s-20 0;
border-top: solid deprecated.$s-1 var(--modal-separator-backogrund-color); border-top: solid deprecated.$s-1 var(--modal-separator-background-color);
} }
.separator { .separator {