🐛 Fix problem with sidebar layout

This commit is contained in:
alonso.torres 2025-05-22 15:55:00 +02:00 committed by Alonso Torres
parent 0df2a12814
commit eaaca5629e
26 changed files with 430 additions and 289 deletions

View file

@ -85,6 +85,7 @@ A non exhaustive list of changes:
- Fix spacing / sizes of different elements in the measurements section of the design tab [Taiga #11076](https://tree.taiga.io/project/penpot/issue/11076) - Fix spacing / sizes of different elements in the measurements section of the design tab [Taiga #11076](https://tree.taiga.io/project/penpot/issue/11076)
- Fix selection of short paths [Github #4472](https://github.com/penpot/penpot/issues/4472) - Fix selection of short paths [Github #4472](https://github.com/penpot/penpot/issues/4472)
- Fix element positioning on the right side to adjust to grid [#11073](https://tree.taiga.io/project/penpot/issue/11073)
## 2.7.0 (Unreleased) ## 2.7.0 (Unreleased)

View file

@ -196,7 +196,7 @@ test("[Bugfixing] User cut paste a variant container into a board, and undo twic
//Create a board //Create a board
await workspacePage.boardButton.click(); await workspacePage.boardButton.click();
await workspacePage.clickWithDragViewportAt(500, 500, 200, 200); await workspacePage.clickWithDragViewportAt(500, 500, 100, 100);
await workspacePage.clickAt(495, 495); await workspacePage.clickAt(495, 495);
const board = await workspacePage.rootShape.locator("Board"); const board = await workspacePage.rootShape.locator("Board");

View file

@ -62,7 +62,7 @@
(let [encode-fn (d/nilv encode-fn identity) (let [encode-fn (d/nilv encode-fn identity)
decode-fn (d/nilv decode-fn identity) decode-fn (d/nilv decode-fn identity)
nitems (if (array? children) nitems (if (array? children)
(alength children) (count (keep identity children))
1) 1)
;; FIXME: we should handle this with CSS ;; FIXME: we should handle this with CSS
width (mf/with-memo [nitems] width (mf/with-memo [nitems]
@ -70,7 +70,7 @@
"unset" "unset"
(fmt/format-pixels (fmt/format-pixels
(+ (* 4 (- nitems 1)) (+ (* 4 (- nitems 1))
(* 28 nitems))))) (* 32 nitems)))))
on-change' on-change'
(mf/use-fn (mf/use-fn

View file

@ -54,6 +54,7 @@
.dropdown-button { .dropdown-button {
@include flexCenter; @include flexCenter;
margin-inline-end: var(--sp-xxs);
svg { svg {
@extend .button-icon-small; @extend .button-icon-small;
transform: rotate(90deg); transform: rotate(90deg);

View file

@ -13,12 +13,16 @@ $sz-32: px2rem(32);
$sz-36: px2rem(36); $sz-36: px2rem(36);
$sz-40: px2rem(40); $sz-40: px2rem(40);
$sz-48: px2rem(48); $sz-48: px2rem(48);
$sz-80: px2rem(80);
$sz-88: px2rem(88);
$sz-160: px2rem(160); $sz-160: px2rem(160);
$sz-200: px2rem(200); $sz-200: px2rem(200);
$sz-224: px2rem(224); $sz-224: px2rem(224);
$sz-252: px2rem(252); $sz-252: px2rem(252);
$sz-284: px2rem(284); $sz-284: px2rem(284);
$sz-318: px2rem(318);
$sz-352: px2rem(352); $sz-352: px2rem(352);
$sz-400: px2rem(400); $sz-400: px2rem(400);
$sz-480: px2rem(480); $sz-480: px2rem(480);
$sz-500: px2rem(500);
$sz-964: px2rem(964); $sz-964: px2rem(964);

View file

@ -5,6 +5,7 @@
// Copyright (c) KALEIDOS INC // Copyright (c) KALEIDOS INC
@import "refactor/common-refactor.scss"; @import "refactor/common-refactor.scss";
@import "../ds/_sizes.scss";
.element-options { .element-options {
display: flex; display: flex;
@ -19,5 +20,5 @@
} }
.workspace-element-options { .workspace-element-options {
height: calc(100vh - #{$s-164}); // TODO: Fix this hardcoded value height: calc(100vh - #{$sz-200}); // TODO: Fix this hardcoded value
} }

View file

@ -5,9 +5,10 @@
// Copyright (c) KALEIDOS INC // Copyright (c) KALEIDOS INC
@import "refactor/common-refactor.scss"; @import "refactor/common-refactor.scss";
@import "../ds/_sizes.scss";
$width-settings-bar: $s-276; $width-settings-bar: $sz-318;
$width-settings-bar-max: $s-500; $width-settings-bar-max: $sz-500;
.left-settings-bar { .left-settings-bar {
display: grid; display: grid;

View file

@ -4,6 +4,7 @@
// //
// Copyright (c) KALEIDOS INC // Copyright (c) KALEIDOS INC
@import "../../ds/_sizes.scss";
@import "refactor/common-refactor.scss"; @import "refactor/common-refactor.scss";
.tool-window { .tool-window {
@ -29,7 +30,7 @@
flex-direction: column; flex-direction: column;
gap: $s-8; gap: $s-8;
width: 100%; width: 100%;
height: calc(100vh - $s-80); height: calc(100vh - $sz-88);
padding-top: $s-8; padding-top: $s-8;
} }

View file

@ -43,7 +43,7 @@
(when (not (and disabled-align disabled-distribute)) (when (not (and disabled-align disabled-distribute))
[:div {:class (stl/css :align-options)} [:div {:class (stl/css :align-options)}
[:div {:class (stl/css :align-group)} [:div {:class (stl/css :align-group-horizontal)}
[:button {:class (stl/css-case :align-button true [:button {:class (stl/css-case :align-button true
:disabled disabled-align) :disabled disabled-align)
:disabled disabled-align :disabled disabled-align
@ -76,7 +76,7 @@
:on-click distribute-objects} :on-click distribute-objects}
i/distribute-horizontally]] i/distribute-horizontally]]
[:div {:class (stl/css :align-group)} [:div {:class (stl/css :align-group-vertical)}
[:button {:class (stl/css-case :align-button true [:button {:class (stl/css-case :align-button true
:disabled disabled-align) :disabled disabled-align)
:disabled disabled-align :disabled disabled-align

View file

@ -7,19 +7,31 @@
@import "refactor/common-refactor.scss"; @import "refactor/common-refactor.scss";
.align-options { .align-options {
display: flex; display: grid;
gap: $s-4; grid-template-columns: repeat(8, var(--sp-xxxl));
column-gap: var(--sp-xs);
height: $s-32; height: $s-32;
margin: 0 calc(-1 * $s-2);
} }
.align-group { .align-group-horizontal,
@include flexRow; .align-group-vertical {
display: grid;
grid-template-columns: subgrid;
align-items: center;
justify-items: center;
}
.align-group-horizontal {
grid-column: 1 / span 4;
}
.align-group-vertical {
grid-column: 5 / span 4;
} }
.align-button { .align-button {
@extend .button-tertiary; @extend .button-tertiary;
height: $s-28; height: $s-32;
width: $s-28; width: $s-32;
padding: 0; padding: 0;
border-radius: $br-8; border-radius: $br-8;
svg { svg {

View file

@ -21,9 +21,12 @@
} }
.first-row { .first-row {
@include flexRow; display: grid;
width: 100%; grid-template-columns: repeat(8, var(--sp-xxxl));
gap: var(--sp-xs);
.blur-info { .blur-info {
grid-column: span 6;
display: flex; display: flex;
align-items: center; align-items: center;
gap: $s-1; gap: $s-1;

View file

@ -8,9 +8,9 @@
.boolean-options { .boolean-options {
display: grid; display: grid;
grid-template-columns: repeat(8, $s-28); grid-template-columns: repeat(8, var(--sp-xxxl));
column-gap: $s-4; column-gap: var(--sp-xs);
height: $s-32; height: var(--sp-xxxl);
} }
.bool-group { .bool-group {
@ -45,4 +45,5 @@
.boolean-radio-btn { .boolean-radio-btn {
background-color: transparent; background-color: transparent;
gap: var(--sp-xs);
} }

View file

@ -16,8 +16,9 @@
} }
.element-set-content { .element-set-content {
@include flexColumn; display: grid;
margin: $s-4 0 $s-8 0; grid-template-columns: repeat(8, var(--sp-xxxl));
gap: var(--sp-xs);
} }
.multiple-exports { .multiple-exports {
@ -32,18 +33,18 @@
.element-group { .element-group {
display: grid; display: grid;
grid-template-columns: repeat(9, 1fr); grid-template-columns: subgrid;
column-gap: $s-4; grid-column: 1 / -1;
} }
.input-wrapper { .input-wrapper {
grid-column: span 8; grid-column: span 7;
display: grid; display: grid;
grid-template-columns: subgrid; grid-template-columns: subgrid;
} }
.format-select { .format-select {
grid-column: span 3; grid-column: span 2;
padding: 0; padding: 0;
.dropdown-upwards { .dropdown-upwards {
@ -72,6 +73,6 @@
.export-btn { .export-btn {
@extend .button-secondary; @extend .button-secondary;
@include uppercaseTitleTipography; @include uppercaseTitleTipography;
grid-column: 1 / span 8;
height: $s-32; height: $s-32;
width: $s-252;
} }

View file

@ -21,10 +21,13 @@
} }
.grid-title { .grid-title {
@include flexRow; display: grid;
grid-template-columns: repeat(8, var(--sp-xxxl));
gap: $s-4;
} }
.option-row { .option-row {
grid-column: span 6;
display: flex; display: flex;
align-items: center; align-items: center;
gap: $s-1; gap: $s-1;
@ -45,6 +48,7 @@
} }
} }
.type-select-wrapper { .type-select-wrapper {
flex-grow: 1;
width: $s-96; width: $s-96;
padding: 0; padding: 0;
border-radius: 0; border-radius: 0;
@ -143,6 +147,7 @@
.actions { .actions {
@include flexRow; @include flexRow;
grid-column: span 2;
} }
.grid-advanced-options { .grid-advanced-options {

View file

@ -160,53 +160,52 @@
preview-complete?)) preview-complete?))
(swap! state* assoc :selected-blend-mode current-blend-mode))) (swap! state* assoc :selected-blend-mode current-blend-mode)))
[:div {:class (stl/css :element-set)} [:div {:class (stl/css-case :element-set-content true
[:div {:class (stl/css-case :element-set-content true :hidden hidden?)}
:hidden hidden?)} [:div {:class (stl/css :select)}
[:div {:class (stl/css :select)} [:& select
[:& select {:default-value selected-blend-mode
{:default-value selected-blend-mode :options options
:options options :on-change handle-change-blend-mode
:on-change handle-change-blend-mode :is-open? option-highlighted?
:is-open? option-highlighted? :class (stl/css-case :hidden-select hidden?)
:class (stl/css-case :hidden-select hidden?) :on-pointer-enter-option handle-blend-mode-enter
:on-pointer-enter-option handle-blend-mode-enter :on-pointer-leave-option handle-blend-mode-leave}]]
:on-pointer-leave-option handle-blend-mode-leave}]] [:div {:class (stl/css :input)
[:div {:class (stl/css :input) :title (tr "workspace.options.opacity")}
:title (tr "workspace.options.opacity")} [:span {:class (stl/css :icon)} "%"]
[:span {:class (stl/css :icon)} "%"] [:> numeric-input*
[:> numeric-input* {:value current-opacity
{:value current-opacity :placeholder "--"
:placeholder "--" :on-change handle-opacity-change
:on-change handle-opacity-change :min 0
:min 0 :max 100
:max 100 :className (stl/css :numeric-input)}]]
:className (stl/css :numeric-input)}]]
[:div {:class (stl/css :actions)} [:div {:class (stl/css :actions)}
(cond (cond
(or (= :multiple hidden?) (not hidden?)) (or (= :multiple hidden?) (not hidden?))
[:> icon-button* {:variant "ghost" [:> icon-button* {:variant "ghost"
:aria-label (tr "workspace.options.layer-options.toggle-layer") :aria-label (tr "workspace.options.layer-options.toggle-layer")
:on-click handle-set-hidden :on-click handle-set-hidden
:icon "shown"}] :icon "shown"}]
:else :else
[:> icon-button* {:variant "ghost" [:> icon-button* {:variant "ghost"
:aria-label (tr "workspace.options.layer-options.toggle-layer") :aria-label (tr "workspace.options.layer-options.toggle-layer")
:on-click handle-set-visible :on-click handle-set-visible
:icon "hide"}]) :icon "hide"}])
(cond (cond
(or (= :multiple blocked?) (not blocked?)) (or (= :multiple blocked?) (not blocked?))
[:> icon-button* {:variant "ghost" [:> icon-button* {:variant "ghost"
:aria-label (tr "workspace.shape.menu.lock") :aria-label (tr "workspace.shape.menu.lock")
:on-click handle-set-blocked :on-click handle-set-blocked
:icon "unlock"}] :icon "unlock"}]
:else :else
[:> icon-button* {:variant "ghost" [:> icon-button* {:variant "ghost"
:aria-label (tr "workspace.shape.menu.unlock") :aria-label (tr "workspace.shape.menu.unlock")
:on-click handle-set-unblocked :on-click handle-set-unblocked
:icon "lock"}])]]])) :icon "lock"}])]]))

View file

@ -6,25 +6,25 @@
@import "refactor/common-refactor.scss"; @import "refactor/common-refactor.scss";
.element-set {
margin-bottom: $s-8;
}
.element-set-content { .element-set-content {
display: flex; display: grid;
grid-template-columns: repeat(8, var(--sp-xxxl));
gap: var(--sp-xs);
height: $s-32; height: $s-32;
gap: $s-4; margin-bottom: $s-8;
.select { .select {
width: $s-124; grid-column: span 4;
padding: 0; padding: 0;
} }
.input { .input {
@extend .input-element; @extend .input-element;
@include bodySmallTypography; @include bodySmallTypography;
width: $s-60; grid-column: span 2;
} }
.actions { .actions {
display: flex; grid-column: span 2;
gap: $s-4; display: grid;
grid-template-columns: subgrid;
} }
&.hidden { &.hidden {

View file

@ -162,7 +162,8 @@
{::mf/props :obj {::mf/props :obj
::mf/private true} ::mf/private true}
[{:keys [value on-change]}] [{:keys [value on-change]}]
[:& radio-buttons {:selected (d/name value) [:& radio-buttons {:class (stl/css :direction-row-flex)
:selected (d/name value)
:decode-fn keyword :decode-fn keyword
:on-change on-change :on-change on-change
:name "flex-direction"} :name "flex-direction"}
@ -197,7 +198,8 @@
(mf/defc align-row (mf/defc align-row
{::mf/props :obj} {::mf/props :obj}
[{:keys [is-column value on-change]}] [{:keys [is-column value on-change]}]
[:& radio-buttons {:selected (d/name value) [:& radio-buttons {:class (stl/css :align-row)
:selected (d/name value)
:decode-fn keyword :decode-fn keyword
:on-change on-change :on-change on-change
:name "flex-align-items"} :name "flex-align-items"}
@ -217,7 +219,8 @@
(mf/defc align-content-row (mf/defc align-content-row
{::mf/props :obj} {::mf/props :obj}
[{:keys [is-column value on-change]}] [{:keys [is-column value on-change]}]
[:& radio-buttons {:selected (d/name value) [:& radio-buttons {:class (stl/css :align-content-row)
:selected (d/name value)
:decode-fn keyword :decode-fn keyword
:on-change on-change :on-change on-change
:name "flex-align-content"} :name "flex-align-content"}
@ -249,7 +252,8 @@
(mf/defc justify-content-row (mf/defc justify-content-row
{::mf/props :obj} {::mf/props :obj}
[{:keys [is-column justify-content on-change]}] [{:keys [is-column justify-content on-change]}]
[:& radio-buttons {:selected (d/name justify-content) [:& radio-buttons {:class (stl/css :justify-content-row)
:selected (d/name justify-content)
:on-change on-change :on-change on-change
:name "flex-justify"} :name "flex-justify"}
[:& radio-button {:value "start" [:& radio-button {:value "start"
@ -582,7 +586,8 @@
(mf/defc direction-row-grid (mf/defc direction-row-grid
{::mf/props :obj} {::mf/props :obj}
[{:keys [value on-change] :as props}] [{:keys [value on-change] :as props}]
[:& radio-buttons {:selected (d/name value) [:& radio-buttons {:class (stl/css :direction-row-grid)
:selected (d/name value)
:decode-fn keyword :decode-fn keyword
:on-change on-change :on-change on-change
:name "grid-direction"} :name "grid-direction"}
@ -619,7 +624,8 @@
::mf/private true} ::mf/private true}
[{:keys [is-column value on-change]}] [{:keys [is-column value on-change]}]
(let [type (if ^boolean is-column "column" "row")] (let [type (if ^boolean is-column "column" "row")]
[:& radio-buttons {:selected (d/name value) [:& radio-buttons {:class (stl/css :align-grid-row)
:selected (d/name value)
:decode-fn keyword :decode-fn keyword
:on-change on-change :on-change on-change
:name (dm/str "flex-align-items-" type)} :name (dm/str "flex-align-items-" type)}
@ -641,7 +647,8 @@
::mf/private :obj} ::mf/private :obj}
[{:keys [is-column value on-change]}] [{:keys [is-column value on-change]}]
(let [type (if ^boolean is-column "column" "row")] (let [type (if ^boolean is-column "column" "row")]
[:& radio-buttons {:selected (d/name value) [:& radio-buttons {:class (stl/css :justify-grid-row)
:selected (d/name value)
:on-change on-change :on-change on-change
:decode-fn keyword :decode-fn keyword
:name (dm/str "grid-justify-items-" type)} :name (dm/str "grid-justify-items-" type)}
@ -1103,7 +1110,7 @@
:on-click open-grid-help :on-click open-grid-help
:icon "help"}]]) :icon "help"}]])
[:div {:class (stl/css :row :first-row)} [:div {:class (stl/css :first-row)}
[:div {:class (stl/css :direction-edit)} [:div {:class (stl/css :direction-edit)}
[:div {:class (stl/css :direction)} [:div {:class (stl/css :direction)}
[:& direction-row-grid {:value saved-grid-dir [:& direction-row-grid {:value saved-grid-dir
@ -1124,10 +1131,10 @@
:value grid-justify-content-row :value grid-justify-content-row
:on-change on-row-justify-change}]] :on-change on-row-justify-change}]]
[:div {:class (stl/css :row)} [:div {:class (stl/css :gap-row)}
[:& gap-section {:on-change on-gap-change [:& gap-section {:on-change on-gap-change
:value (:layout-gap values)}]] :value (:layout-gap values)}]]
[:div {:class (stl/css :row :padding-section)} [:div {:class (stl/css :padding-row)}
[:& padding-section {:value (:layout-padding values) [:& padding-section {:value (:layout-padding values)
:type (:layout-padding-type values) :type (:layout-padding-type values)
:on-type-change on-padding-type-change :on-type-change on-padding-type-change

View file

@ -30,17 +30,31 @@
} }
} }
.flex-layout-menu { .flex-layout-menu {
display: grid;
grid-template-columns: repeat(8, var(--sp-xxxl));
gap: var(--sp-xs);
margin-bottom: $s-8; margin-bottom: $s-8;
.first-row { .first-row {
display: flex; grid-column: 1 / -1;
gap: $s-4; display: grid;
grid-template-columns: subgrid;
margin-bottom: $s-12; margin-bottom: $s-12;
margin-top: $s-4; margin-top: $s-4;
.align-row {
grid-column: span 3;
}
.direction-row-flex {
grid-column: span 4;
}
.wrap-button { .wrap-button {
@extend .button-tertiary; @extend .button-tertiary;
border-radius: $br-8; border-radius: $br-8;
height: $s-32; height: $s-32;
width: $s-28; width: $s-32;
svg { svg {
@extend .button-icon; @extend .button-icon;
stroke: var(--icon-foreground); stroke: var(--icon-foreground);
@ -52,12 +66,25 @@
} }
.second-row, .second-row,
.third-row { .third-row {
grid-column: 1 / -1;
display: grid;
grid-template-columns: subgrid;
margin-bottom: $s-12; margin-bottom: $s-12;
.align-content-row,
.justify-content-row {
grid-column: span 6;
}
} }
.forth-row { .forth-row {
@include flexColumn; display: grid;
--input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2);
grid-template-columns: var(--input-width) var(--input-width) var(--sp-xxxl);
gap: var(--sp-xs);
grid-column: 1 / -1;
} }
.help-button-wrapper { .help-button-wrapper {
grid-column: 1 / -1;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
@ -66,12 +93,12 @@
} }
.gap-group { .gap-group {
display: flex; grid-column: span 3;
gap: $s-4; display: grid;
grid-template-columns: subgrid;
.column-gap { .column-gap {
@extend .input-element; @extend .input-element;
@include bodySmallTypography; @include bodySmallTypography;
width: $s-108;
&.disabled { &.disabled {
@extend .disabled-input; @extend .disabled-input;
} }
@ -79,7 +106,6 @@
.row-gap { .row-gap {
@extend .input-element; @extend .input-element;
@include bodySmallTypography; @include bodySmallTypography;
width: $s-108;
&.disabled { &.disabled {
@extend .disabled-input; @extend .disabled-input;
} }
@ -87,41 +113,43 @@
} }
.padding-group { .padding-group {
display: flex; display: grid;
gap: $s-4; grid-column: span 3;
grid-template-columns: subgrid;
.padding-inputs { .padding-inputs {
display: flex; grid-column: span 2;
gap: $s-4; display: grid;
grid-template-columns: subgrid;
} }
.paddings-simple { .paddings-simple {
display: flex; display: grid;
gap: $s-4; grid-column: span 2;
grid-template-columns: subgrid;
.padding-simple { .padding-simple {
@extend .input-element; @extend .input-element;
@include bodySmallTypography; @include bodySmallTypography;
max-width: $s-108;
} }
} }
.paddings-multiple { .paddings-multiple {
display: grid; display: grid;
grid-template-columns: 1fr 1fr; grid-column: span 2;
gap: $s-4; grid-template-columns: subgrid;
gap: var(--sp-xs);
.padding-multiple { .padding-multiple {
@extend .input-element; @extend .input-element;
@include bodySmallTypography; @include bodySmallTypography;
max-width: $s-108;
} }
} }
.padding-toggle { .padding-toggle {
@extend .button-tertiary; @extend .button-tertiary;
height: $s-32; height: $s-32;
width: $s-28; width: $s-32;
border-radius: $br-8; border-radius: $br-8;
svg { svg {
@extend .button-icon; @extend .button-icon;
@ -134,22 +162,30 @@
} }
.grid-layout-menu { .grid-layout-menu {
@include flexColumn; display: grid;
gap: $s-8; grid-template-columns: repeat(8, var(--sp-xxxl));
gap: var(--sp-xs);
.row { .edit-grid-wrapper,
@include flexRow; .first-row,
.grid-layout-align,
.gap-row,
.padding-row {
grid-column: 1 / -1;
} }
.first-row { .first-row {
margin-bottom: $s-8; margin-bottom: $s-8;
display: grid;
grid-template-columns: subgrid;
} }
.grid-layout-align { .grid-layout-align {
@include flexColumn; display: grid;
gap: $s-4; grid-template-columns: subgrid;
align-items: flex-start; align-items: flex-start;
position: relative; position: relative;
gap: var(--sp-xs);
.locate-button { .locate-button {
position: absolute; position: absolute;
@ -169,6 +205,7 @@
@include uppercaseTitleTipography; @include uppercaseTitleTipography;
width: 100%; width: 100%;
padding: $s-8; padding: $s-8;
grid-column: span 7;
} }
.exit-btn { .exit-btn {
@ -193,7 +230,8 @@
} }
.edit-grid-wrapper { .edit-grid-wrapper {
@include flexRow; display: grid;
grid-template-columns: subgrid;
} }
} }
@ -324,3 +362,23 @@
} }
} }
} }
.direction-edit {
grid-column: span 2;
}
.align-grid-row {
grid-column: span 3;
}
.justify-grid-row {
grid-column: 1 / span 6;
}
.gap-row,
.padding-row {
display: grid;
--input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2);
grid-template-columns: var(--input-width) var(--input-width) var(--sp-xxxl);
gap: var(--sp-xs);
}

View file

@ -230,7 +230,6 @@
{:selected (d/name value) {:selected (d/name value)
:decode-fn keyword :decode-fn keyword
:on-change on-change :on-change on-change
:wide true
:name "flex-behaviour-h"} :name "flex-behaviour-h"}
[:& radio-button [:& radio-button
@ -265,7 +264,6 @@
{:selected (d/name value) {:selected (d/name value)
:decode-fn keyword :decode-fn keyword
:on-change on-change :on-change on-change
:wide true
:name "flex-behaviour-v"} :name "flex-behaviour-v"}
[:& radio-button [:& radio-button
@ -451,7 +449,7 @@
(when open? (when open?
[:div {:class (stl/css :flex-element-menu)} [:div {:class (stl/css :flex-element-menu)}
(when (or is-layout-child? is-absolute?) (when (or is-layout-child? is-absolute?)
[:div {:class (stl/css :row)} [:div {:class (stl/css :position-row)}
[:div {:class (stl/css :position-options)} [:div {:class (stl/css :position-options)}
[:& radio-buttons {:selected (if is-absolute? "absolute" "static") [:& radio-buttons {:selected (if is-absolute? "absolute" "static")
:decode-fn keyword :decode-fn keyword
@ -475,7 +473,7 @@
:nillable true :nillable true
:value (:layout-item-z-index values)}]]]) :value (:layout-item-z-index values)}]]])
[:div {:class (stl/css :row)} [:div {:class (stl/css :behavior-row)}
[:div {:class (stl/css-case [:div {:class (stl/css-case
:behaviour-menu true :behaviour-menu true
:wrap (and ^boolean is-layout-child? :wrap (and ^boolean is-layout-child?
@ -492,85 +490,83 @@
:on-change on-behaviour-v-change}]]] :on-change on-behaviour-v-change}]]]
(when (and is-layout-child? is-flex-parent?) (when (and is-layout-child? is-flex-parent?)
[:div {:class (stl/css :row)} [:div {:class (stl/css :align-row)}
[:& align-self-row {:is-col is-col? [:& align-self-row {:is-col is-col?
:value align-self :value align-self
:on-change on-align-self-change}]]) :on-change on-align-self-change}]])
(when is-layout-child? (when is-layout-child?
[:div {:class (stl/css :row)} [:> margin-section* {:value (:layout-item-margin values)
[:> margin-section* {:value (:layout-item-margin values) :type (:layout-item-margin-type values)
:type (:layout-item-margin-type values) :on-type-change on-margin-type-change
:on-type-change on-margin-type-change :on-change on-margin-change}])
:on-change on-margin-change}]])
(when (or (= h-sizing :fill) (when (or (= h-sizing :fill)
(= v-sizing :fill)) (= v-sizing :fill))
[:div {:class (stl/css :row)} [:div {:class (stl/css :advanced-options)}
[:div {:class (stl/css :advanced-options)} (when (= (:layout-item-h-sizing values) :fill)
(when (= (:layout-item-h-sizing values) :fill) [:div {:class (stl/css :horizontal-fill)}
[:div {:class (stl/css :horizontal-fill)} [:div {:class (stl/css :layout-item-min-w)
[:div {:class (stl/css :layout-item-min-w) :title (tr "workspace.options.layout-item.layout-item-min-w")}
:title (tr "workspace.options.layout-item.layout-item-min-w")}
[:span {:class (stl/css :icon-text)} "MIN W"] [:span {:class (stl/css :icon-text)} "MIN W"]
[:> numeric-input* [:> numeric-input*
{:class (stl/css :numeric-input) {:class (stl/css :numeric-input)
:no-validate true :no-validate true
:min 0 :min 0
:data-wrap true :data-wrap true
:placeholder "--" :placeholder "--"
:data-attr "layout-item-min-w" :data-attr "layout-item-min-w"
:on-focus dom/select-target :on-focus dom/select-target
:on-change on-size-change :on-change on-size-change
:value (get values :layout-item-min-w) :value (get values :layout-item-min-w)
:nillable true}]] :nillable true}]]
[:div {:class (stl/css :layout-item-max-w) [:div {:class (stl/css :layout-item-max-w)
:title (tr "workspace.options.layout-item.layout-item-max-w")} :title (tr "workspace.options.layout-item.layout-item-max-w")}
[:span {:class (stl/css :icon-text)} "MAX W"] [:span {:class (stl/css :icon-text)} "MAX W"]
[:> numeric-input* [:> numeric-input*
{:class (stl/css :numeric-input) {:class (stl/css :numeric-input)
:no-validate true :no-validate true
:min 0 :min 0
:data-wrap true :data-wrap true
:placeholder "--" :placeholder "--"
:data-attr "layout-item-max-w" :data-attr "layout-item-max-w"
:on-focus dom/select-target :on-focus dom/select-target
:on-change on-size-change :on-change on-size-change
:value (get values :layout-item-max-w) :value (get values :layout-item-max-w)
:nillable true}]]]) :nillable true}]]])
(when (= v-sizing :fill) (when (= v-sizing :fill)
[:div {:class (stl/css :vertical-fill)} [:div {:class (stl/css :vertical-fill)}
[:div {:class (stl/css :layout-item-min-h) [:div {:class (stl/css :layout-item-min-h)
:title (tr "workspace.options.layout-item.layout-item-min-h")} :title (tr "workspace.options.layout-item.layout-item-min-h")}
[:span {:class (stl/css :icon-text)} "MIN H"] [:span {:class (stl/css :icon-text)} "MIN H"]
[:> numeric-input* [:> numeric-input*
{:class (stl/css :numeric-input) {:class (stl/css :numeric-input)
:no-validate true :no-validate true
:min 0 :min 0
:data-wrap true :data-wrap true
:placeholder "--" :placeholder "--"
:data-attr "layout-item-min-h" :data-attr "layout-item-min-h"
:on-focus dom/select-target :on-focus dom/select-target
:on-change on-size-change :on-change on-size-change
:value (get values :layout-item-min-h) :value (get values :layout-item-min-h)
:nillable true}]] :nillable true}]]
[:div {:class (stl/css :layout-item-max-h) [:div {:class (stl/css :layout-item-max-h)
:title (tr "workspace.options.layout-item.layout-item-max-h")} :title (tr "workspace.options.layout-item.layout-item-max-h")}
[:span {:class (stl/css :icon-text)} "MAX H"] [:span {:class (stl/css :icon-text)} "MAX H"]
[:> numeric-input* [:> numeric-input*
{:class (stl/css :numeric-input) {:class (stl/css :numeric-input)
:no-validate true :no-validate true
:min 0 :min 0
:data-wrap true :data-wrap true
:placeholder "--" :placeholder "--"
:data-attr "layout-item-max-h" :data-attr "layout-item-max-h"
:on-focus dom/select-target :on-focus dom/select-target
:on-change on-size-change :on-change on-size-change
:value (get values :layout-item-max-h) :value (get values :layout-item-max-h)
:nillable true}]]])]])])])) :nillable true}]]])])])]))

View file

@ -19,68 +19,60 @@
} }
.flex-element-menu { .flex-element-menu {
@include flexColumn; display: grid;
gap: $s-12; grid-template-columns: repeat(8, var(--sp-xxxl));
margin-block-end: $s-8; gap: var(--sp-xs);
} }
.behaviour-menu { .behaviour-menu {
display: flex; display: grid;
gap: $s-4; column-gap: var(--sp-xs);
} grid-template-columns: auto auto;
.horizontal-behaviour {
&.one-element {
width: $s-28;
}
&.two-element {
width: $s-60;
}
&.three-element {
width: $s-92;
}
} }
.vertical-behaviour { .vertical-behaviour {
.rotated { .rotated {
transform: rotate(90deg); transform: rotate(90deg);
} }
&.one-element {
width: $s-28;
}
&.two-element {
width: $s-60;
}
&.three-element {
width: $s-92;
}
} }
.z-index-wrapper { .z-index-wrapper {
@extend .input-element; @extend .input-element;
@include bodySmallTypography; @include bodySmallTypography;
width: $s-60; grid-column: 6 / span 3;
} }
.row { .row {
display: flex; display: flex;
gap: $s-4; gap: var(--sp-xs);
}
.position-row,
.behavior-row,
.align-row,
.margin-row {
display: grid;
grid-template-columns: subgrid;
grid-column: 1 / -1;
} }
.position-options { .position-options {
width: $s-188; width: 100%;
grid-column: 1 / span 5;
} }
.margin-row { .margin-row {
display: flex; display: grid;
align-items: flex-start; // NOTE: this does not follow the 8-column grid and the size is not normalized,
gap: $s-4; --input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2);
grid-template-columns: var(--input-width) var(--input-width) var(--sp-xxxl);
gap: var(--sp-xs);
} }
.margin-mode { .margin-mode {
@extend .button-tertiary; @extend .button-tertiary;
grid-column: 3;
height: $s-32; height: $s-32;
width: $s-28;
svg { svg {
@extend .button-icon; @extend .button-icon;
} }
@ -90,20 +82,26 @@
} }
.margin-simple { .margin-simple {
display: flex; display: grid;
gap: $s-4; gap: var(--sp-xs);
grid-template-columns: subgrid;
.vertical-margin, .vertical-margin,
.horizontal-margin { .horizontal-margin {
@extend .input-element; @extend .input-element;
@include bodySmallTypography; @include bodySmallTypography;
width: $s-108; }
.vertical-margin {
grid-column: 1;
}
.horizontal-margin {
grid-column: 2;
} }
} }
.margin-multiple { .margin-multiple {
display: grid; display: grid;
grid-template-columns: 1fr 1fr; grid-template-columns: subgrid;
gap: $s-4; gap: var(--sp-xs);
} }
.top-margin, .top-margin,
@ -112,17 +110,40 @@
.right-margin { .right-margin {
@extend .input-element; @extend .input-element;
@include bodySmallTypography; @include bodySmallTypography;
width: $s-108; }
.top-margin {
grid-column: 1;
grid-row: 1;
}
.bottom-margin {
grid-column: 2;
grid-row: 1;
}
.left-margin {
grid-column: 1;
grid-row: 2;
}
.right-margin {
grid-column: 2;
grid-row: 2;
} }
.advanced-options { .advanced-options {
@include flexColumn; display: grid;
--input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2);
grid-template-columns: var(--input-width) var(--input-width) var(--sp-xxxl);
gap: var(--sp-xs);
} }
.horizontal-fill, .horizontal-fill,
.vertical-fill { .vertical-fill {
display: flex; display: grid;
gap: $s-4; grid-template-columns: subgrid;
grid-column: 1 / -1;
} }
.layout-item-min-w, .layout-item-min-w,
@ -131,10 +152,13 @@
.layout-item-max-h { .layout-item-max-h {
@extend .input-element; @extend .input-element;
@include bodySmallTypography; @include bodySmallTypography;
width: $s-108;
.icon-text { .icon-text {
justify-content: flex-start; justify-content: flex-start;
width: $s-80; width: $s-80;
padding-top: $s-2; padding-top: $s-2;
} }
} }
.inputs-wrapper {
grid-column: 1 / span 2;
}

View file

@ -8,26 +8,24 @@
.element-set { .element-set {
display: grid; display: grid;
row-gap: var(--sp-xs);
margin-bottom: var(--sp-s); margin-bottom: var(--sp-s);
// NOTE: this does not follow the 8-column grid and the size is not normalized, // NOTE: this does not follow the 8-column grid and the size is not normalized,
// so we need to hardcode this width :( --input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2);
--input-width: calc(var(--sp-xxxl) * 3.5 - 2 * var(--sp-xs));
grid-template-columns: var(--input-width) var(--input-width) var(--sp-xxxl); grid-template-columns: var(--input-width) var(--input-width) var(--sp-xxxl);
column-gap: var(--sp-xs); gap: var(--sp-xs);
} }
.presets { .presets {
display: grid; display: grid;
grid-column: 1 / -1;
grid-template-columns: repeat(8, var(--sp-xxxl)); grid-template-columns: repeat(8, var(--sp-xxxl));
gap: $s-4; gap: var(--sp-xs);
grid-column: 1 / -1;
} }
.presets-wrapper { .presets-wrapper {
@extend .asset-element; @extend .asset-element;
position: relative; position: relative;
grid-column: span 4; grid-column: span 5;
display: flex; display: flex;
height: $s-32; height: $s-32;
padding: $s-8; padding: $s-8;

View file

@ -196,7 +196,8 @@
:on-change on-update-offset-y :on-change on-update-offset-y
:value (:offset-y shadow)}]] :value (:offset-y shadow)}]]
[:> color-row* {:color (:color shadow) [:> color-row* {:class (stl/css :shadow-color)
:color (:color shadow)
:title (tr "workspace.options.shadow-options.color") :title (tr "workspace.options.shadow-options.color")
:disable-gradient true :disable-gradient true
:disable-image true :disable-image true

View file

@ -30,7 +30,9 @@
} }
.actions { .actions {
@include flexRow; display: grid;
grid-template-columns: subgrid;
grid-column: span 2;
} }
.shadow-element { .shadow-element {
@ -53,14 +55,17 @@
} }
.basic-options { .basic-options {
@include flexRow; display: grid;
grid-template-columns: repeat(8, var(--sp-xxxl));
gap: var(--sp-xs);
} }
.shadow-info { .shadow-info {
grid-column: span 6;
display: flex; display: flex;
align-items: center; align-items: center;
gap: $s-1; gap: $s-1;
width: $s-188;
.more-options { .more-options {
@extend .button-secondary; @extend .button-secondary;
height: $s-32; height: $s-32;
@ -102,34 +107,46 @@
} }
.shadow-advanced-options { .shadow-advanced-options {
@include flexColumn; display: grid;
width: $sz-252; grid-template-columns: repeat(8, var(--sp-xxxl));
gap: var(--sp-xs);
} }
.first-row, .first-row,
.second-row { .second-row {
@include flexRow; display: grid;
.offset-x-input, grid-column: 1 / -1;
.blur-input, grid-template-columns: subgrid;
.spread-input, }
.offset-y-input {
@extend .input-element; .offset-x-input,
@include bodySmallTypography; .blur-input,
width: $s-60; .spread-input,
min-width: $s-60; .offset-y-input {
align-items: baseline; @extend .input-element;
input { @include bodySmallTypography;
width: $s-32; }
}
} .input-label {
.blur-input, width: $sz-48;
.spread-input { }
width: $s-92;
.input-label { .offset-x-input {
width: $s-44; grid-column: span 2;
} }
}
.spread-input { .offset-y-input {
gap: $s-8; grid-column: span 2;
} }
.blur-input {
grid-column: span 3;
}
.spread-input {
grid-column: span 3;
}
.shadow-color {
grid-column: span 6;
} }

View file

@ -45,7 +45,7 @@
(if (= v :multiple) nil v)) (if (= v :multiple) nil v))
(mf/defc color-row* (mf/defc color-row*
[{:keys [index color disable-gradient disable-opacity disable-image disable-picker hidden [{:keys [index color class disable-gradient disable-opacity disable-image disable-picker hidden
on-change on-reorder on-detach on-open on-close on-remove on-change on-reorder on-detach on-open on-close on-remove
disable-drag on-focus on-blur select-only select-on-focus]}] disable-drag on-focus on-blur select-only select-on-focus]}]
(let [libraries (mf/deref refs/files) (let [libraries (mf/deref refs/files)
@ -68,6 +68,8 @@
editing-text* (mf/use-state false) editing-text* (mf/use-state false)
editing-text? (deref editing-text*) editing-text? (deref editing-text*)
class (if (some? class) (dm/str class " ") "")
opacity? opacity?
(and (not multiple-colors?) (and (not multiple-colors?)
(not library-color?) (not library-color?)
@ -187,11 +189,13 @@
(when (and (not disable-picker) (not= prev-color color)) (when (and (not disable-picker) (not= prev-color color))
(modal/update-props! :colorpicker {:data (parse-color color)}))) (modal/update-props! :colorpicker {:data (parse-color color)})))
[:div {:class (stl/css-case [:div {:class (dm/str
:color-data true class
:hidden hidden (stl/css-case
:dnd-over-top (= (:over dprops) :top) :color-data true
:dnd-over-bot (= (:over dprops) :bot))} :hidden hidden
:dnd-over-top (= (:over dprops) :top)
:dnd-over-bot (= (:over dprops) :bot)))}
;; Drag handler ;; Drag handler
(when (some? on-reorder) (when (some? on-reorder)

View file

@ -176,7 +176,7 @@
:select-on-focus select-on-focus :select-on-focus select-on-focus
:on-blur on-blur}]] :on-blur on-blur}]]
[:div {:class (stl/css :select-wrapper) [:div {:class (stl/css :select-wrapper :stroke-alignment-select)
:data-testid "stroke.alignment"} :data-testid "stroke.alignment"}
[:& select [:& select
{:default-value stroke-alignment {:default-value stroke-alignment
@ -184,7 +184,7 @@
:on-change on-alignment-change}]] :on-change on-alignment-change}]]
(when-not disable-stroke-style (when-not disable-stroke-style
[:div {:class (stl/css :select-wrapper) [:div {:class (stl/css :select-wrapper :stroke-style-select)
:data-testid "stroke.style"} :data-testid "stroke.style"}
[:& select [:& select
{:default-value stroke-style {:default-value stroke-style

View file

@ -29,24 +29,30 @@
.stroke-options { .stroke-options {
display: grid; display: grid;
align-items: center; align-items: center;
gap: $s-4; grid-template-columns: repeat(8, var(--sp-xxxl));
grid-template-columns: 1fr 2fr 2fr; gap: var(--sp-xs);
.stroke-width-input-element { .stroke-width-input-element {
@extend .input-element; @extend .input-element;
@include bodySmallTypography; @include bodySmallTypography;
grid-column: span 2;
}
.stroke-alignment-select {
grid-column: span 3;
}
.stroke-style-select {
grid-column: span 3;
} }
} }
.stroke-caps-options { .stroke-caps-options {
display: grid; display: grid;
align-items: center; --input-width: calc(var(--sp-xxxl) * 3.5 + 3 * var(--sp-xs) - var(--sp-xs) / 2);
gap: $s-4; grid-template-columns: var(--input-width) var(--sp-xxxl) var(--input-width);
grid-template-columns: 1fr auto 1fr; gap: var(--sp-xs);
} }
.cap-select {
width: 100%;
}
.stroke-cap-dropdown, .stroke-cap-dropdown,
.stroke-cap-dropdown-start { .stroke-cap-dropdown-start {
min-width: $s-124; min-width: $s-124;
@ -62,8 +68,8 @@
} }
.swap-caps-btn { .swap-caps-btn {
@extend .button-secondary; @extend .button-secondary;
height: $s-32; height: var(--sp-xxxl);
width: $s-28; width: var(--sp-xxxl);
svg { svg {
@extend .button-icon; @extend .button-icon;
} }