diff --git a/frontend/playwright/ui/specs/tokens/apply.spec.js b/frontend/playwright/ui/specs/tokens/apply.spec.js
index a8401e2d51..69ed14f051 100644
--- a/frontend/playwright/ui/specs/tokens/apply.spec.js
+++ b/frontend/playwright/ui/specs/tokens/apply.spec.js
@@ -72,7 +72,7 @@ test.describe("Tokens: Apply token", () => {
// Check if border radius sections is visible on right sidebar
const borderRadiusSection = page.getByRole("region", {
- name: "border-radius-section",
+ name: "Border radius section",
});
await expect(borderRadiusSection).toBeVisible();
@@ -135,7 +135,7 @@ test.describe("Tokens: Apply token", () => {
// Check if opacity sections is visible on right sidebar
const layerMenuSection = page.getByRole("region", {
- name: "layer-menu-section",
+ name: "Layer menu section",
});
await expect(layerMenuSection).toBeVisible();
@@ -688,7 +688,7 @@ test.describe("Tokens: Apply token", () => {
// Check if border radius sections is visible on right sidebar
const borderRadiusSection = page.getByRole("region", {
- name: "border-radius-section",
+ name: "Border radius section",
});
await expect(borderRadiusSection).toBeVisible();
@@ -897,7 +897,7 @@ test.describe("Tokens: Detach token", () => {
// Check if border radius sections is visible on right sidebar
const borderRadiusSection = page.getByRole("region", {
- name: "border-radius-section",
+ name: "Border radius section",
});
await expect(borderRadiusSection).toBeVisible();
diff --git a/frontend/resources/images/icons/stroke-center.svg b/frontend/resources/images/icons/stroke-center.svg
new file mode 100644
index 0000000000..a00cdf58df
--- /dev/null
+++ b/frontend/resources/images/icons/stroke-center.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/frontend/resources/images/icons/stroke-dashed.svg b/frontend/resources/images/icons/stroke-dashed.svg
new file mode 100644
index 0000000000..40c3bdcae1
--- /dev/null
+++ b/frontend/resources/images/icons/stroke-dashed.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/frontend/resources/images/icons/stroke-dotted.svg b/frontend/resources/images/icons/stroke-dotted.svg
new file mode 100644
index 0000000000..8b3c1940e3
--- /dev/null
+++ b/frontend/resources/images/icons/stroke-dotted.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/frontend/resources/images/icons/stroke-inside.svg b/frontend/resources/images/icons/stroke-inside.svg
new file mode 100644
index 0000000000..21f2eb1c52
--- /dev/null
+++ b/frontend/resources/images/icons/stroke-inside.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/frontend/resources/images/icons/stroke-mixed.svg b/frontend/resources/images/icons/stroke-mixed.svg
new file mode 100644
index 0000000000..56070d56ee
--- /dev/null
+++ b/frontend/resources/images/icons/stroke-mixed.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/frontend/resources/images/icons/stroke-outside.svg b/frontend/resources/images/icons/stroke-outside.svg
new file mode 100644
index 0000000000..0f4dec0924
--- /dev/null
+++ b/frontend/resources/images/icons/stroke-outside.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/frontend/resources/images/icons/stroke-solid.svg b/frontend/resources/images/icons/stroke-solid.svg
new file mode 100644
index 0000000000..a9bba0e9b9
--- /dev/null
+++ b/frontend/resources/images/icons/stroke-solid.svg
@@ -0,0 +1,3 @@
+
diff --git a/frontend/src/app/main/data/workspace/tokens/application.cljs b/frontend/src/app/main/data/workspace/tokens/application.cljs
index 3ee7758284..9c79d40260 100644
--- a/frontend/src/app/main/data/workspace/tokens/application.cljs
+++ b/frontend/src/app/main/data/workspace/tokens/application.cljs
@@ -822,9 +822,50 @@
:shape-ids shape-ids
:on-update-shape on-update-shape}))))))))
-(defn apply-token-on-selected
+(defn apply-token-from-input
+ [{:keys [token attrs shape-ids expand-with-children]}]
+ (ptk/reify ::apply-token-from-input
+ ptk/WatchEvent
+ (watch [_ state _]
+ (let [objects (dsh/lookup-page-objects state)
+ shapes (into [] (keep (d/getf objects)) shape-ids)
+
+ shapes
+ (if expand-with-children
+ (into []
+ (mapcat (fn [shape]
+ (if (= (:type shape) :group)
+ (keep objects (:shapes shape))
+ [shape])))
+ shapes)
+ shapes)
+
+ {:keys [attributes _ on-update-shape]}
+ (get token-properties (:type token))
+
+ on-update-shape
+ (if (seq attrs)
+ (or (get attr->shape-update (first attrs)) on-update-shape)
+ on-update-shape)]
+
+ (rx/of
+ (cond
+ (and (= (:type token) :spacing)
+ (nil? attrs))
+ (apply-spacing-token-separated {:token token
+ :attr attrs
+ :shapes shapes})
+
+ :else
+ (apply-token {:attributes (if (empty? attrs) attributes attrs)
+ :token token
+ :shape-ids shape-ids
+ :on-update-shape on-update-shape})))))))
+
+
+(defn apply-token-on-color-selected
[color-operations token]
- (ptk/reify ::apply-token-on-selected
+ (ptk/reify ::apply-token-on-color-selected
ptk/WatchEvent
(watch [_ _ _]
(let [undo-id (js/Symbol)]
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 cb86f6bdab..a98dba1c8d 100644
--- a/frontend/src/app/main/ui/ds/controls/numeric_input.cljs
+++ b/frontend/src/app/main/ui/ds/controls/numeric_input.cljs
@@ -140,6 +140,8 @@
[:on-focus {:optional true} fn?]
[:on-detach {:optional true} fn?]
[:property {:optional true} :string]
+ [:tooltip-placement {:optional true}
+ [:maybe [:enum "top" "bottom" "left" "right" "top-right" "bottom-right" "bottom-left" "top-left"]]]
[:align {:optional true} [:maybe [:enum :left :right]]]])
(mf/defc numeric-input*
@@ -151,7 +153,7 @@
tokens applied-token empty-to-end
on-change on-blur on-focus on-detach
property align ref name
- text-icon]
+ tooltip-placement text-icon]
:rest props}]
(let [;; NOTE: we use mfu/bean here for transparently handle
@@ -574,9 +576,9 @@
:icon i/tokens
:tooltip-class (stl/css :button-tooltip)
:class (stl/css :invisible-button)
- :tooltip-placement "top-left"
:aria-label (tr "ds.inputs.numeric-input.open-token-list-dropdown")
:ref open-dropdown-ref
+ :tooltip-placement tooltip-placement
:on-click open-dropdown}])))
:max-length max-length})
@@ -603,6 +605,7 @@
:class inner-class
:property property
:is-open is-open
+ :tooltip-placement tooltip-placement
:slot-start (when (or icon text-icon)
(mf/html
(cond
diff --git a/frontend/src/app/main/ui/ds/controls/select.cljs b/frontend/src/app/main/ui/ds/controls/select.cljs
index d40d7275b8..c31fb45264 100644
--- a/frontend/src/app/main/ui/ds/controls/select.cljs
+++ b/frontend/src/app/main/ui/ds/controls/select.cljs
@@ -9,8 +9,10 @@
[app.main.style :as stl])
(:require
[app.common.data :as d]
+ [app.common.data.macros :as dm]
[app.main.ui.ds.controls.shared.options-dropdown :refer [options-dropdown* schema:option]]
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
+ [app.main.ui.ds.tooltip.tooltip :refer [tooltip*]]
[app.util.dom :as dom]
[app.util.keyboard :as kbd]
[app.util.object :as obj]
@@ -50,15 +52,17 @@
[:map
[:options [:vector {:min 1} schema:option]]
[:class {:optional true} :string]
+ [:wrapper-class {:optional true} :string]
[:disabled {:optional true} :boolean]
[:default-selected {:optional true} :string]
[:empty-to-end {:optional true} [:maybe :boolean]]
[:on-change {:optional true} fn?]
- [:variant {:optional true} [:maybe [:enum "default" "ghost"]]]])
+ [:dropdown-alignment {:optional true} [:maybe [:enum :left :right]]]
+ [:variant {:optional true} [:maybe [:enum "default" "ghost" "icon-only"]]]])
(mf/defc select*
{::mf/schema schema:select}
- [{:keys [options class disabled default-selected empty-to-end on-change variant] :rest props}]
+ [{:keys [options class disabled default-selected empty-to-end on-change variant wrapper-class dropdown-alignment] :rest props}]
(let [;; NOTE: we use mfu/bean here for transparently handle
;; options provide as clojure data structures or javascript
;; plain objects and lists.
@@ -192,26 +196,40 @@
(some? icon)
dimmed?
- (:dimmed selected-option)]
+ (:dimmed selected-option)
+
+ icon-ref (mf/use-ref nil)
+ icon-id (mf/use-id)]
(mf/with-effect [options]
(mf/set-ref-val! options-ref options))
- [:div {:class (stl/css :select-wrapper)
+ [:div {:class [wrapper-class (stl/css :select-wrapper)]
:on-click on-click
:ref select-ref
:on-blur on-blur}
[:> :button props
[:span {:class (stl/css-case :select-header true
- :header-icon has-icon?)}
+ :header-icon has-icon?
+ :header-icon-only (= variant "icon-only"))}
(when ^boolean has-icon?
- [:> icon* {:icon-id icon
- :size "s"
- :aria-hidden true}])
- [:span {:class (stl/css-case :header-label true
- :header-label-dimmed (or empty-selected-id? dimmed?))}
- (if ^boolean empty-selected-id? "--" label)]]
+ (if (= variant "icon-only")
+ [:> tooltip* {:content label
+ :trigger-ref icon-ref
+ :id (dm/str icon-id "-name")
+ :class (stl/css :option-text)}
+ [:> icon* {:icon-id icon
+ :ref icon-ref
+ :aria-labelledby (dm/str icon-id "-name")}]]
+ [:> icon* {:icon-id icon
+ :size "s"
+ :aria-hidden true}]))
+
+ (when-not ^boolean (= variant "icon-only")
+ [:span {:class (stl/css-case :header-label true
+ :header-label-dimmed (or empty-selected-id? dimmed?))}
+ (if ^boolean empty-selected-id? "--" label)])]
[:> icon* {:icon-id i/arrow-down
:class (stl/css :arrow)
@@ -224,5 +242,6 @@
:options options
:selected selected-id
:focused focused-id
+ :align dropdown-alignment
:empty-to-end empty-to-end
:ref set-option-ref}])]))
diff --git a/frontend/src/app/main/ui/ds/controls/select.scss b/frontend/src/app/main/ui/ds/controls/select.scss
index d52be44549..3b96b1b7e8 100644
--- a/frontend/src/app/main/ui/ds/controls/select.scss
+++ b/frontend/src/app/main/ui/ds/controls/select.scss
@@ -109,3 +109,8 @@
grid-template-columns: auto 1fr;
color: var(--select-icon-color);
}
+
+.header-icon-only {
+ grid-template-columns: 1fr;
+ color: var(--select-icon-color);
+}
diff --git a/frontend/src/app/main/ui/ds/controls/select.stories.jsx b/frontend/src/app/main/ui/ds/controls/select.stories.jsx
index 3cf750d5d7..8a2005cd32 100644
--- a/frontend/src/app/main/ui/ds/controls/select.stories.jsx
+++ b/frontend/src/app/main/ui/ds/controls/select.stories.jsx
@@ -9,7 +9,7 @@ import Components from "@target/components";
const { Select } = Components;
-const variants = ["default", "ghost"];
+const variants = ["default", "ghost", "icon-only"];
const options = [
{ id: "option-code", label: "Code" },
@@ -75,3 +75,10 @@ export const EmptyToEnd = {
emptyToEnd: true,
},
};
+
+export const OnlyWithIcons = {
+ args: {
+ options: optionsWithIcons,
+ variant: variants[2],
+ },
+};
diff --git a/frontend/src/app/main/ui/ds/controls/shared/options_dropdown.cljs b/frontend/src/app/main/ui/ds/controls/shared/options_dropdown.cljs
index 0191891398..7d566f7d63 100644
--- a/frontend/src/app/main/ui/ds/controls/shared/options_dropdown.cljs
+++ b/frontend/src/app/main/ui/ds/controls/shared/options_dropdown.cljs
@@ -28,6 +28,7 @@
[:resolved-value {:optional true}
[:or :int :string :float]]
[:name {:optional true} :string]
+ [:value {:optional true} :keyword]
[:icon {:optional true} schema:icon-list]
[:label {:optional true} :string]
[:aria-label {:optional true} :string]])
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 3e825f2b38..8b67fa82f8 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
@@ -31,12 +31,14 @@
[:on-token-key-down fn?]
[:on-blur {:optional true} fn?]
[:on-focus {:optional true} fn?]
+ [:tooltip-placement {:optional true}
+ [:maybe [:enum "top" "bottom" "left" "right" "top-right" "bottom-right" "bottom-left" "top-left"]]]
[:detach-token fn?]])
(mf/defc token-field*
{::mf/schema schema:token-field}
[{:keys [id label value slot-start disabled class
- on-click on-token-key-down on-blur detach-token
+ on-click on-token-key-down on-blur detach-token tooltip-placement
token-wrapper-ref token-detach-btn-ref on-focus property is-open]}]
(let [set-active? (some? id)
content (if set-active?
@@ -92,8 +94,8 @@
:class (stl/css-case :invisible-button true
:invisible-btn-dropdown-open is-open)
:tooltip-class (stl/css :button-tooltip)
+ :tooltip-placement tooltip-placement
:icon i/broken-link
:ref token-detach-btn-ref
- :tooltip-placement "top-left"
:aria-label (tr "ds.inputs.token-field.detach-token")
:on-click detach-token}])]]))
diff --git a/frontend/src/app/main/ui/ds/foundations/assets/icon.cljs b/frontend/src/app/main/ui/ds/foundations/assets/icon.cljs
index 0e83173bee..0203bf9999 100644
--- a/frontend/src/app/main/ui/ds/foundations/assets/icon.cljs
+++ b/frontend/src/app/main/ui/ds/foundations/assets/icon.cljs
@@ -245,12 +245,19 @@
(def ^:icon-id status-update "status-update")
(def ^:icon-id status-wrong "status-wrong")
(def ^:icon-id stroke-arrow "stroke-arrow")
+(def ^:icon-id stroke-center "stroke-center")
(def ^:icon-id stroke-circle "stroke-circle")
+(def ^:icon-id stroke-dashed "stroke-dashed")
(def ^:icon-id stroke-diamond "stroke-diamond")
+(def ^:icon-id stroke-dotted "stroke-dotted")
+(def ^:icon-id stroke-inside "stroke-inside")
+(def ^:icon-id stroke-mixed "stroke-mixed")
+(def ^:icon-id stroke-outside "stroke-outside")
(def ^:icon-id stroke-rectangle "stroke-rectangle")
(def ^:icon-id stroke-rounded "stroke-rounded")
(def ^:icon-id stroke-size "stroke-size")
(def ^:icon-id stroke-squared "stroke-squared")
+(def ^:icon-id stroke-solid "stroke-solid")
(def ^:icon-id stroke-triangle "stroke-triangle")
(def ^:icon-id svg "svg")
(def ^:icon-id swatches "swatches")
diff --git a/frontend/src/app/main/ui/workspace/sidebar/common/sidebar.scss b/frontend/src/app/main/ui/workspace/sidebar/common/sidebar.scss
index b5a372a431..a20ad8d615 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/common/sidebar.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/common/sidebar.scss
@@ -43,11 +43,15 @@ $column-number: 8; // total number of columns
// -> 8 columns (32px each) + 7 gaps (4px each) = 284px
// Derived widths
-$options-width: calc(#{$column-width} * #{$column-number} + #{$column-gap} * calc(#{$column-number} - 1));
-$seven-column-width: calc(
- #{$column-width} * calc(#{$column-number} - 1) + #{$column-gap} * calc(#{$column-number} - 2)
-);
+@function grid-width($cols) {
+ @return calc(#{$column-width} * #{$cols} + #{$column-gap} * #{$cols - 1});
+}
+$options-width: grid-width($column-number);
+$two-column-width: grid-width(2);
+$three-column-width: grid-width(3);
+$four-column-width: grid-width(4);
+$seven-column-width: grid-width(7);
// ------------------------------------------------------------
// Grid mixin — applies the standard structure to any container
// ------------------------------------------------------------
@@ -73,16 +77,28 @@ $seven-column-width: calc(
// |___|-|___|-|___|-|___|-|___|-|___|-|___|-|___|
// -> 8 columns (32px each) + 7 gaps (4px each) = 284px
//
-// But one block (grid-exception-input) doesn’t fit perfectly:
+// But two blocks don’t fit perfectly:
+// First (grid-exception-input-width)
// |__________________|-|__________________|-|___|
-//
-// We calculate the width of that grid-exception-input as:
+// We calculate the width of that grid-exception-input-width as:
//
// - 3.5 columns of base grid width
// - + 3 inter-column gaps
// - − half a gap (because it’s visually shared with the next block)
-
$grid-exception-input-width: calc(#{$sz-32} * 3.5 + 3 * var(--sp-xs) - (var(--sp-xs) / 2));
+//
+// |___|-|___|-|___|-|___|-|___|-|___|-|___|-|___|
+//
+// Second (grid-exception-input-width-small)
+// |__________________|-|____________|-|___|-|___|
+//
+// We calculate the width of that grid-exception-input-width-small as:
+//
+// - 2.5 columns of base grid width
+// - + 2 inter-column gaps
+// - − half a gap (because it’s visually shared with the next block)
+
+$grid-exception-input-width-small: calc(#{$sz-32} * 2.5 + 2 * var(--sp-xs) - (var(--sp-xs) / 2));
// ============================================================
// CSS VARIABLES (exposed for runtime use)
@@ -95,7 +111,11 @@ $grid-exception-input-width: calc(#{$sz-32} * 3.5 + 3 * var(--sp-xs) - (var(--sp
--left-sidebar-width-max: #{$left-sidebar-width-max};
--right-sidebar-width: #{$right-sidebar-width};
--right-sidebar-width-max: #{$right-sidebar-width-max};
- --7-columns-dropdown-width: #{$seven-column-width};
+ --2-columns-width: #{$two-column-width};
+ --3-columns-width: #{$three-column-width};
+ --4-columns-width: #{$four-column-width};
+ --7-columns-width: #{$seven-column-width};
--options-width: #{$options-width};
--grid-exception-input-width: #{$grid-exception-input-width};
+ --grid-exception-input-width-small: #{$grid-exception-input-width-small};
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/border_radius.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/border_radius.cljs
index 13c260726f..16feaa68d0 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/border_radius.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/border_radius.cljs
@@ -164,64 +164,50 @@
(mf/with-effect [ids]
(reset! radius-expanded* false))
- [:section {:class (dm/str class " " (stl/css :radius))
- :aria-label "border-radius-section"}
- (if (not radius-expanded)
- (if token-numeric-inputs
- [:> numeric-input-wrapper*
- {:on-change on-all-radius-change
- :on-detach on-detach-all
- :icon i/corner-radius
- :min 0
- :attr :border-radius
- :nillable true
- :property (tr "workspace.options.radius")
- :applied-token (cond
- (not (seq applied-tokens))
- nil
+ (if token-numeric-inputs
+ [:section {:class (dm/str class " " (stl/css :radius-token))
+ :aria-label (tr "workspace.options.radius.radius-section")}
+ [:div {:class (stl/css :radius-first-row)}
+ [:> numeric-input-wrapper*
+ {:on-change on-all-radius-change
+ :on-detach on-detach-all
+ :icon i/corner-radius
+ :min 0
+ :attr :border-radius
+ :nillable true
+ :property (tr "workspace.options.radius")
+ :applied-token (cond
+ (not (seq applied-tokens))
+ nil
- (or (not all-values-equal?) (not all-token-equal?))
- :multiple
+ (or (not all-values-equal?) (not all-token-equal?))
+ :multiple
- :else
- (get applied-tokens :r1))
- :align :right
- :placeholder (cond
- (or (not all-values-equal?)
- (not all-token-equal?))
- (tr "settings.multiple")
- :else
- "--")
- :value (if all-values-equal?
- (if (nil? (:r1 values))
- 0
- (:r1 values))
- nil)}]
-
- [:div {:class (stl/css :radius-1)
- :title (tr "workspace.options.radius")}
- [:> icon* {:icon-id i/corner-radius
- :size "s"
- :class (stl/css :icon)}]
- [:> deprecated-input/numeric-input*
- {:placeholder (cond
- (not all-values-equal?)
- (tr "settings.multiple")
- (= :multiple (:r1 values))
- (tr "settings.multiple")
:else
- "--")
- :min 0
- :nillable true
- :on-change on-all-radius-change
- :value (if all-values-equal?
- (if (nil? (:r1 values))
- 0
- (:r1 values))
- nil)}]])
+ (get applied-tokens :r1))
+ :align :right
+ :placeholder (cond
+ (or (not all-values-equal?)
+ (not all-token-equal?))
+ (tr "settings.multiple")
+ :else
+ "--")
+ :value (if all-values-equal?
+ (if (nil? (:r1 values))
+ 0
+ (:r1 values))
+ nil)}]
+ [:> icon-button* {:class (stl/css-case :selected radius-expanded)
+ :variant "ghost"
+ :tooltip-placement "top-left"
+ :on-click toggle-radius-mode
+ :aria-label (if radius-expanded
+ (tr "workspace.options.radius.hide-all-corners")
+ (tr "workspace.options.radius.show-single-corners"))
+ :icon i/corner-radius}]]
- (if token-numeric-inputs
- [:div {:class (stl/css :radius-4)}
+ (when radius-expanded
+ [:div {:class (stl/css :radius-4-token)}
[:> numeric-input-wrapper*
{:on-change on-radius-r1-change
:on-detach on-detach-r1
@@ -249,6 +235,7 @@
:property (tr "workspace.options.radius-top-right")
:applied-token (get applied-tokens :r2)
:align :right
+ :tooltip-placement "top-left"
:inner-class (stl/css :no-icon-input)
:placeholder (cond
(or (= :multiple (get applied-tokens :r2))
@@ -293,9 +280,33 @@
"--")
:align :right
:class (stl/css :radius-wrapper)
+ :tooltip-placement "top-left"
:inner-class (stl/css :no-icon-input)
- :value (:r3 values)}]]
-
+ :value (:r3 values)}]])]
+ [:section {:class (dm/str class " " (stl/css :radius))
+ :aria-label (tr "workspace.options.radius.radius-section")}
+ (if (not radius-expanded)
+ [:div {:class (stl/css :radius-1)
+ :title (tr "workspace.options.radius")}
+ [:> icon* {:icon-id i/corner-radius
+ :size "s"
+ :class (stl/css :icon)}]
+ [:> deprecated-input/numeric-input*
+ {:placeholder (cond
+ (not all-values-equal?)
+ (tr "settings.multiple")
+ (= :multiple (:r1 values))
+ (tr "settings.multiple")
+ :else
+ "--")
+ :min 0
+ :nillable true
+ :on-change on-all-radius-change
+ :value (if all-values-equal?
+ (if (nil? (:r1 values))
+ 0
+ (:r1 values))
+ nil)}]]
[:div {:class (stl/css :radius-4)}
[:div {:class (stl/css :small-input)}
[:> deprecated-input/numeric-input*
@@ -327,12 +338,11 @@
:title (tr "workspace.options.radius-bottom-right")
:min 0
:on-change on-radius-r3-change
- :value (:r3 values)}]]]))
-
- [:> icon-button* {:class (stl/css-case :selected radius-expanded)
- :variant "ghost"
- :on-click toggle-radius-mode
- :aria-label (if radius-expanded
- (tr "workspace.options.radius.hide-all-corners")
- (tr "workspace.options.radius.show-single-corners"))
- :icon i/corner-radius}]]))
+ :value (:r3 values)}]]])
+ [:> icon-button* {:class (stl/css-case :selected radius-expanded)
+ :variant "ghost"
+ :on-click toggle-radius-mode
+ :aria-label (if radius-expanded
+ (tr "workspace.options.radius.hide-all-corners")
+ (tr "workspace.options.radius.show-single-corners"))
+ :icon i/corner-radius}]])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/border_radius.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/border_radius.scss
index 5473314c67..222dc5bd03 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/border_radius.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/border_radius.scss
@@ -14,7 +14,8 @@
gap: var(--sp-xs);
}
-.radius-1 {
+.radius-1,
+.small-input {
@extend .input-element;
@include t.use-typography("body-small");
}
@@ -25,23 +26,12 @@
gap: var(--sp-xs);
}
-.small-input {
- @extend .input-element;
- @include t.use-typography("body-small");
-}
-
.selected {
border-color: var(--button-icon-border-color-selected);
background-color: var(--button-icon-background-color-selected);
color: var(--color-accent-primary);
}
-.selected {
- border-color: var(--button-icon-border-color-selected);
- background-color: var(--button-icon-background-color-selected);
- color: var(--button-icon-foreground-color-selected);
-}
-
.icon {
margin-inline: var(--sp-xs);
}
@@ -53,3 +43,20 @@
.dropdown-offset {
--dropdown-offset: #{px2rem(-65)};
}
+
+.radius-token {
+ display: grid;
+ gap: var(--sp-xs);
+}
+
+.radius-first-row {
+ display: grid;
+ grid-template-columns: 1fr auto;
+ gap: var(--sp-xs);
+}
+
+.radius-4-token {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: var(--sp-xs);
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs
index eac46af116..31dd4ad3a5 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs
@@ -190,7 +190,7 @@
[color-operations _] (retrieve-color-operations groups old-color prev-colors)]
(mf/set-ref-val! prev-colors-ref
(conj prev-colors color))
- (st/emit! (dwta/apply-token-on-selected color-operations token)))))]
+ (st/emit! (dwta/apply-token-on-color-selected color-operations token)))))]
[:div {:class (stl/css :element-set)}
[:div {:class (stl/css :element-title)}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.cljs
index 20a4198431..b3509487e2 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.cljs
@@ -174,10 +174,10 @@
(mf/deps ids)
(fn [_ token]
(st/emit!
- (dwta/toggle-token {:token token
- :attrs #{:fill}
- :shape-ids ids
- :expand-with-children true}))))
+ (dwta/apply-token-from-input {:token token
+ :attrs #{:fill}
+ :shape-ids ids
+ :expand-with-children true}))))
on-detach-token
(mf/use-fn
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/input_wrapper_tokens.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/input_wrapper_tokens.scss
index b5d6de75d1..aeeaa99191 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/input_wrapper_tokens.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/input_wrapper_tokens.scss
@@ -5,5 +5,5 @@
// Copyright (c) KALEIDOS INC
.numeric-input-wrapper {
- --dropdown-width: var(--7-columns-dropdown-width);
+ --dropdown-width: var(--7-columns-width);
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.cljs
index 3e5cfe9921..3c08d9d6d8 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.cljs
@@ -138,14 +138,13 @@
on-opacity-change
(mf/use-fn
- (mf/deps on-change handle-opacity-change)
+ (mf/deps handle-opacity-change)
(fn [value]
(if (or (string? value) (number? value))
(handle-opacity-change value)
- (do
- (st/emit! (dwta/toggle-token {:token (first value)
- :attrs #{:opacity}
- :shape-ids ids}))))))
+ (st/emit! (dwta/apply-token-from-input {:token (first value)
+ :attrs #{:opacity}
+ :shape-ids ids})))))
handle-set-hidden
(mf/use-fn
@@ -205,20 +204,25 @@
preview-complete?))
(swap! state* assoc :selected-blend-mode current-blend-mode)))
- [:section {:class (stl/css-case :element-set-content true
- :hidden hidden?)
- :aria-label "layer-menu-section"}
- [:div {:class (stl/css :select)}
- [:& select
- {:default-value selected-blend-mode
- :options options
- :on-change handle-change-blend-mode
- :is-open? option-highlighted?
- :class (stl/css-case :hidden-select hidden?)
- :on-pointer-enter-option handle-blend-mode-enter
- :on-pointer-leave-option handle-blend-mode-leave}]]
+ ;; NOTE:
+ ;; This code is temporarily duplicated because the UI is changing with a new feature.
+ ;; The new implementation is currently behind a feature/config flag and not yet released.
+ ;; Once the feature is released, the duplicated ClojureScript and SCSS code should be removed.
+ ;; https://tree.taiga.io/project/penpot/task/13704
+
+ (if token-numeric-inputs
+ ;; TODO: When duplicated code is remove rename this class removing the "token" reference from it
+ [:section {:class (stl/css :element-set-content-token)
+ :aria-label (tr "workspace.options.layer-options.layer-section")}
+ [:& select
+ {:default-value selected-blend-mode
+ :options options
+ :on-change handle-change-blend-mode
+ :is-open? option-highlighted?
+ :class (stl/css-case :hidden-select hidden?)
+ :on-pointer-enter-option handle-blend-mode-enter
+ :on-pointer-leave-option handle-blend-mode-leave}]
- (if token-numeric-inputs
[:> numeric-input-wrapper*
{:on-change on-opacity-change
:on-detach on-detach-token
@@ -233,10 +237,54 @@
(tr "settings.multiple")
"--")
:align :right
+ :disabled hidden?
:class (stl/css :numeric-input-wrapper)
:value (* 100
(or (get values :opacity) 1))}]
+ (cond
+ (or (= :multiple hidden?) (not hidden?))
+ [:> icon-button* {:variant "ghost"
+ :aria-label (tr "workspace.options.layer-options.toggle-layer")
+ :on-click handle-set-hidden
+ :tooltip-placement "top-left"
+ :icon i/shown}]
+
+ :else
+ [:> icon-button* {:variant "ghost"
+ :aria-label (tr "workspace.options.layer-options.toggle-layer")
+ :on-click handle-set-visible
+ :tooltip-placement "top-left"
+ :icon i/hide}])
+
+ (cond
+ (or (= :multiple blocked?) (not blocked?))
+ [:> icon-button* {:variant "ghost"
+ :aria-label (tr "workspace.shape.menu.lock")
+ :on-click handle-set-blocked
+ :tooltip-placement "top-left"
+ :icon i/unlock}]
+
+ :else
+ [:> icon-button* {:variant "ghost"
+ :aria-label (tr "workspace.shape.menu.unlock")
+ :on-click handle-set-unblocked
+ :tooltip-placement "top-left"
+ :icon i/lock}])]
+
+ [:section {:class (stl/css-case :element-set-content true
+ :hidden hidden?)
+ :aria-label (tr "workspace.options.layer-options.layer-section")}
+ [:div {:class (stl/css :select)}
+ [:& select
+ {:default-value selected-blend-mode
+ :options options
+ :on-change handle-change-blend-mode
+ :is-open? option-highlighted?
+ :class (stl/css-case :hidden-select hidden?)
+ :on-pointer-enter-option handle-blend-mode-enter
+ :on-pointer-leave-option handle-blend-mode-leave}]]
+
[:div {:class (stl/css :input)
:title (tr "workspace.options.opacity")}
[:span {:class (stl/css :icon)} "%"]
@@ -246,31 +294,31 @@
:on-change handle-opacity-change
:min 0
:max 100
- :className (stl/css :numeric-input)}]])
+ :className (stl/css :numeric-input)}]]
- [:div {:class (stl/css :actions)}
- (cond
- (or (= :multiple hidden?) (not hidden?))
- [:> icon-button* {:variant "ghost"
- :aria-label (tr "workspace.options.layer-options.toggle-layer")
- :on-click handle-set-hidden
- :icon i/shown}]
+ [:div {:class (stl/css :actions)}
+ (cond
+ (or (= :multiple hidden?) (not hidden?))
+ [:> icon-button* {:variant "ghost"
+ :aria-label (tr "workspace.options.layer-options.toggle-layer")
+ :on-click handle-set-hidden
+ :icon i/shown}]
- :else
- [:> icon-button* {:variant "ghost"
- :aria-label (tr "workspace.options.layer-options.toggle-layer")
- :on-click handle-set-visible
- :icon i/hide}])
+ :else
+ [:> icon-button* {:variant "ghost"
+ :aria-label (tr "workspace.options.layer-options.toggle-layer")
+ :on-click handle-set-visible
+ :icon i/hide}])
- (cond
- (or (= :multiple blocked?) (not blocked?))
- [:> icon-button* {:variant "ghost"
- :aria-label (tr "workspace.shape.menu.lock")
- :on-click handle-set-blocked
- :icon i/unlock}]
+ (cond
+ (or (= :multiple blocked?) (not blocked?))
+ [:> icon-button* {:variant "ghost"
+ :aria-label (tr "workspace.shape.menu.lock")
+ :on-click handle-set-blocked
+ :icon i/unlock}]
- :else
- [:> icon-button* {:variant "ghost"
- :aria-label (tr "workspace.shape.menu.unlock")
- :on-click handle-set-unblocked
- :icon i/lock}])]]))
+ :else
+ [:> icon-button* {:variant "ghost"
+ :aria-label (tr "workspace.shape.menu.unlock")
+ :on-click handle-set-unblocked
+ :icon i/lock}])]])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.scss
index 637cf9a090..21fe114676 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.scss
@@ -7,18 +7,23 @@
@use "refactor/common-refactor.scss" as deprecated;
@use "../../../sidebar/common/sidebar.scss" as sidebar;
@use "ds/_utils.scss" as *;
+@use "ds/_sizes.scss" as *;
+@use "ds/_borders.scss" as *;
+@use "ds/typography.scss" as t;
+// This code should be remove when numeric-input-tokens are activated
+// https://tree.taiga.io/project/penpot/task/13704
.element-set-content {
@include sidebar.option-grid-structure;
- height: deprecated.$s-32;
- margin-bottom: deprecated.$s-8;
+ block-size: $sz-32;
+ margin-block-end: var(--sp-s);
.select {
grid-column: span 4;
padding: 0;
}
.input {
@extend .input-element;
- @include deprecated.bodySmallTypography;
+ @include t.use-typography("body-small");
grid-column: span 2;
}
.actions {
@@ -29,12 +34,22 @@
&.hidden {
.hidden-select {
- @include deprecated.hiddenElement;
- border: deprecated.$s-1 solid var(--input-border-color-disabled);
+ cursor: default;
+ pointer-events: none;
+ box-sizing: border-box;
+ color: var(--input-foreground-color-disabled);
+ stroke: var(--input-foreground-color-disabled);
+ background-color: transparent;
+ border: $b-1 solid var(--input-border-color-disabled);
}
.input {
- @include deprecated.hiddenElement;
- border: deprecated.$s-1 solid var(--input-border-color-disabled);
+ cursor: default;
+ pointer-events: none;
+ box-sizing: border-box;
+ color: var(--input-foreground-color-disabled);
+ stroke: var(--input-foreground-color-disabled);
+ background-color: transparent;
+ border: $b-1 solid var(--input-border-color-disabled);
.icon {
stroke: var(--input-foreground-color-disabled);
}
@@ -45,7 +60,28 @@
}
}
+// This code should remain when numeric-input-tokens are activated
+// https://tree.taiga.io/project/penpot/task/13704
+
+// This rule should be rename when numeric-input-tokens are
+// activated removing the token reference on the class
+.element-set-content-token {
+ @include sidebar.option-grid-structure;
+ block-size: $sz-32;
+ margin-block-end: var(--sp-s);
+ grid-template-columns: var(--grid-exception-input-width) var(--grid-exception-input-width-small) auto auto;
+}
+
+.hidden-select {
+ cursor: default;
+ pointer-events: none;
+ box-sizing: border-box;
+ color: var(--input-foreground-color-disabled);
+ stroke: var(--input-foreground-color-disabled);
+ background-color: transparent;
+ border: $b-1 solid var(--input-border-color-disabled);
+}
+
.numeric-input-wrapper {
- grid-column: span 2;
--dropdown-offset: #{px2rem(-35)};
}
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 568bea26da..7ad7c0186a 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
@@ -463,9 +463,9 @@
(if (or (string? value) (number? value))
(on-change :multiple attr value event)
(do
- (st/emit! (dwta/toggle-token {:token (first value)
- :attrs #{attr}
- :shape-ids ids}))))))
+ (st/emit! (dwta/apply-token-from-input {:token (first value)
+ :attrs #{attr}
+ :shape-ids ids}))))))
on-focus
(mf/use-fn
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 9c5030e99c..ef9936d90e 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
@@ -283,9 +283,9 @@
(st/emit! (udw/trigger-bounding-box-cloaking ids)
(udw/update-dimensions ids attr value))
(st/emit! (udw/trigger-bounding-box-cloaking ids)
- (dwta/toggle-token {:token (first value)
- :attrs #{attr}
- :shape-ids ids})))))
+ (dwta/apply-token-from-input {:token (first value)
+ :attrs #{attr}
+ :shape-ids ids})))))
on-proportion-lock-change
(mf/use-fn
@@ -304,9 +304,9 @@
(st/emit! (udw/trigger-bounding-box-cloaking ids))
(st/emit! (udw/update-positions ids {attr value})))
(st/emit! (udw/trigger-bounding-box-cloaking ids)
- (dwta/toggle-token {:token (first value)
- :attrs #{attr}
- :shape-ids ids})))))
+ (dwta/apply-token-from-input {:token (first value)
+ :attrs #{attr}
+ :shape-ids ids})))))
on-rotation-change
(mf/use-fn
@@ -317,9 +317,9 @@
(st/emit! (udw/trigger-bounding-box-cloaking ids))
(st/emit! (udw/increase-rotation ids value)))
(st/emit! (udw/trigger-bounding-box-cloaking ids)
- (dwta/toggle-token {:token (first value)
- :attrs #{:rotation}
- :shape-ids ids})))))
+ (dwta/apply-token-from-input {:token (first value)
+ :attrs #{:rotation}
+ :shape-ids ids})))))
on-width-change
(mf/use-fn (mf/deps on-size-change) #(on-size-change % :width))
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 e214e0f636..c75c161942 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
@@ -191,5 +191,5 @@
// TODO: Add a proper variable to this sizing
.numeric-input-measures {
- --dropdown-width: var(--7-columns-dropdown-width);
+ --dropdown-width: var(--7-columns-width);
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs
index 9fe822f9df..955e69f26c 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs
@@ -16,6 +16,7 @@
[app.main.ui.components.reorder-handler :refer [reorder-handler*]]
[app.main.ui.components.select :refer [select]]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
+ [app.main.ui.ds.controls.select :refer [select*]]
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
[app.main.ui.hooks :as h]
[app.main.ui.workspace.sidebar.options.common :as soc]
@@ -108,9 +109,9 @@
(d/concat-vec
(when (= :multiple stroke-alignment)
[{:value :multiple :label "--"}])
- [{:value :center :label (tr "workspace.options.stroke.center")}
- {:value :inner :label (tr "workspace.options.stroke.inner")}
- {:value :outer :label (tr "workspace.options.stroke.outer")}]))
+ [{:value :center :label (tr "workspace.options.stroke.center") :id "center" :icon "stroke-center"}
+ {:value :inner :label (tr "workspace.options.stroke.inner") :id "inner" :icon "stroke-inside"}
+ {:value :outer :label (tr "workspace.options.stroke.outer") :id "outer" :icon "stroke-outside"}]))
on-alignment-change
(mf/use-fn
@@ -122,10 +123,10 @@
(mf/deps ids)
(fn [_ token]
(st/emit!
- (dwta/toggle-token {:token token
- :attrs #{:stroke-color}
- :shape-ids ids
- :expand-with-children true}))))
+ (dwta/apply-token-from-input {:token token
+ :attrs #{:stroke-color}
+ :shape-ids ids
+ :expand-with-children true}))))
stroke-style (or (:stroke-style stroke) :solid)
@@ -134,10 +135,10 @@
(d/concat-vec
(when (= :multiple stroke-style)
[{:value :multiple :label "--"}])
- [{:value :solid :label (tr "workspace.options.stroke.solid")}
- {:value :dotted :label (tr "workspace.options.stroke.dotted")}
- {:value :dashed :label (tr "workspace.options.stroke.dashed")}
- {:value :mixed :label (tr "workspace.options.stroke.mixed")}]))
+ [{:value :solid :label (tr "workspace.options.stroke.solid") :id "solid" :icon "stroke-solid"}
+ {:value :dotted :label (tr "workspace.options.stroke.dotted") :id "dotted" :icon "stroke-dotted"}
+ {:value :dashed :label (tr "workspace.options.stroke.dashed") :id "dashed" :icon "stroke-dashed"}
+ {:value :mixed :label (tr "workspace.options.stroke.mixed") :id "mixed" :icon "stroke-mixed"}]))
on-style-change
(mf/use-fn
@@ -212,8 +213,8 @@
:on-blur on-blur}]
;; Stroke Width, Alignment & Style
- [:div {:class (stl/css :stroke-options)}
- (if token-numeric-inputs
+ (if token-numeric-inputs
+ [:div {:class (stl/css :stroke-options-tokens)}
[:> numeric-input-wrapper* {:on-change on-width-change
:on-detach on-detach-token-width
:icon i/stroke-size
@@ -225,7 +226,23 @@
:property (tr "workspace.options.stroke-width")
:applied-token (get applied-tokens :stroke-width)
:value stroke-width}]
+ [:> select* {:default-selected (d/name stroke-alignment)
+ :options stroke-alignment-options
+ :variant "icon-only"
+ :data-testid "stroke.alignment"
+ :wrapper-class (stl/css :stroke-align-icon-select)
+ :on-change on-alignment-change}]
+ (when-not disable-stroke-style
+ [:> select* {:default-selected (d/name stroke-style)
+ :options stroke-style-options
+ :wrapper-class (stl/css :stroke-style-icon-select)
+ :data-testid "stroke.style"
+ :variant "icon-only"
+ :dropdown-alignment :right
+ :on-change on-style-change}])]
+
+ [:div {:class (stl/css :stroke-options)}
[:div {:class (stl/css :stroke-width-input)
:title (tr "workspace.options.stroke-width")}
[:> icon* {:icon-id i/stroke-size
@@ -236,20 +253,19 @@
:on-change on-width-change
:on-focus on-focus
:select-on-focus select-on-focus
- :on-blur on-blur}]])
+ :on-blur on-blur}]]
+ [:div {:class (stl/css :stroke-alignment-select)
+ :data-testid "stroke.alignment"}
+ [:& select {:default-value stroke-alignment
+ :options stroke-alignment-options
+ :on-change on-alignment-change}]]
- [:div {:class (stl/css :stroke-alignment-select)
- :data-testid "stroke.alignment"}
- [:& select {:default-value stroke-alignment
- :options stroke-alignment-options
- :on-change on-alignment-change}]]
-
- (when-not disable-stroke-style
- [:div {:class (stl/css :stroke-style-select)
- :data-testid "stroke.style"}
- [:& select {:default-value stroke-style
- :options stroke-style-options
- :on-change on-style-change}]])]
+ (when-not disable-stroke-style
+ [:div {:class (stl/css :stroke-style-select)
+ :data-testid "stroke.style"}
+ [:& select {:default-value stroke-style
+ :options stroke-style-options
+ :on-change on-style-change}]])])
;; Stroke Caps
(when show-caps
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 19f81ac9c2..830acdab03 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
@@ -38,17 +38,12 @@
.stroke-width-input {
grid-column: span 2;
- // TODO replace with numeric-input* from DS
@extend .input-element;
@include t.use-typography("body-small");
padding-inline-start: var(--sp-xs);
}
-.numeric-input-wrapper {
- grid-column: span 2;
-}
-
.stroke-alignment-select {
grid-column: span 3;
}
@@ -62,3 +57,18 @@
grid-template-columns: 1fr auto 1fr;
column-gap: var(--sp-xs);
}
+
+.stroke-options-tokens {
+ @include sidebar.option-grid-structure;
+ grid-template-columns: var(--3-columns-width) var(--grid-exception-input-width-small) var(
+ --grid-exception-input-width-small
+ );
+}
+
+.stroke-align-icon-select {
+ --dropdown-width: var(--4-columns-width);
+}
+
+.stroke-style-icon-select {
+ --dropdown-width: var(--4-columns-width);
+}
diff --git a/frontend/translations/en.po b/frontend/translations/en.po
index bc9944638c..624b8a2acb 100644
--- a/frontend/translations/en.po
+++ b/frontend/translations/en.po
@@ -6845,6 +6845,10 @@ msgstr "Selected layers"
msgid "workspace.options.layer-options.toggle-layer"
msgstr "Toggle layer visibility"
+#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:255
+msgid "workspace.options.layer-options.layer-section"
+msgstr "Layer menu section"
+
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
#, unused
msgid "workspace.options.layout-item.advanced-ops"
@@ -7029,6 +7033,10 @@ msgstr "Collapse independent radius"
msgid "workspace.options.radius.show-single-corners"
msgstr "Show independent radius"
+#: src/app/main/ui/workspace/sidebar/options/menus/border_radius.cljs:341
+msgid "workspace.options.radius.radius-section"
+msgstr "Border radius section"
+
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:191
msgid "workspace.options.recent-fonts"
msgstr "Recent"
diff --git a/frontend/translations/es.po b/frontend/translations/es.po
index 3b12ef2a44..6c378c4985 100644
--- a/frontend/translations/es.po
+++ b/frontend/translations/es.po
@@ -6762,6 +6762,10 @@ msgstr "Capas seleccionadas"
msgid "workspace.options.layer-options.toggle-layer"
msgstr "Mostrar/ocultar capa"
+#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:255
+msgid "workspace.options.layer-options.layer-section"
+msgstr "Sección del menú de capas"
+
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
#, unused
msgid "workspace.options.layout-item.advanced-ops"
@@ -6946,6 +6950,10 @@ msgstr "Colapsar radios individuales"
msgid "workspace.options.radius.show-single-corners"
msgstr "Mostrar radios individuales"
+#: src/app/main/ui/workspace/sidebar/options/menus/border_radius.cljs:341
+msgid "workspace.options.radius.radius-section"
+msgstr "Sección de radios de borde"
+
#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:191
msgid "workspace.options.recent-fonts"
msgstr "Recientes"