🐛 Fix main menu is covered by the toolbar (#10926)

* 🐛 Fix main menu is covered by the toolbar

* ♻️ Refactor SCSS

* 🐛 Fix adjust z-index of workspace context menu

* ♻️ Refactor SCSS

* 🐛 Fix adjust z-index of tokens context menu

* ♻️ Refactor SCSS

* 🐛 Fix adjust z-index of old context menu

* 📎 PR improvements
This commit is contained in:
Luis de Dios 2026-07-31 12:48:59 +02:00 committed by GitHub
parent 1744d07731
commit ff32f104b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 399 additions and 403 deletions

View File

@ -976,7 +976,7 @@
margin: 0; margin: 0;
margin-top: $s-1; margin-top: $s-1;
border-radius: $br-8; border-radius: $br-8;
z-index: $z-index-4; z-index: var(--z-index-dropdown);
overflow: hidden auto; overflow: hidden auto;
background-color: var(--menu-background-color); background-color: var(--menu-background-color);
color: var(--menu-foreground-color); color: var(--menu-foreground-color);

View File

@ -106,7 +106,7 @@
(constantly on-unmount)) (constantly on-unmount))
(if icon (if icon
[:li {:class (stl/css :icon-menu-item) [:li {:class (stl/css :menu-item-icon)
:disabled disabled :disabled disabled
:data-value value :data-value value
:ref set-dom-node :ref set-dom-node
@ -114,21 +114,23 @@
:on-pointer-enter on-pointer-enter :on-pointer-enter on-pointer-enter
:on-pointer-leave on-pointer-leave} :on-pointer-leave on-pointer-leave}
[:span [:span
{:class (stl/css :icon-wrapper)} {:class (stl/css :menu-item-icon-group)}
(if is-selected [:span {:class (stl/css :selected-icon)} (if is-selected
[:> icon* {:icon-id i/tick :size "s"}]] [:span {:class (stl/css :icon)}
[:span {:class (stl/css :selected-icon)}]) [:> icon* {:icon-id i/tick :size "s"}]]
[:span {:class (stl/css :shape-icon)} [:span {:class (stl/css :icon)}])
[:span {:class (stl/css :icon)}
[:> icon* {:icon-id icon :size "s"}]]] [:> icon* {:icon-id icon :size "s"}]]]
[:span {:class (stl/css :title)} title]] [:span {:class (stl/css :menu-item-title)} title]]
[:li {:class (stl/css :context-menu-item)
[:li {:class (stl/css :menu-item)
:disabled disabled :disabled disabled
:ref set-dom-node :ref set-dom-node
:data-value value :data-value value
:on-click on-click' :on-click on-click'
:on-pointer-enter on-pointer-enter :on-pointer-enter on-pointer-enter
:on-pointer-leave on-pointer-leave} :on-pointer-leave on-pointer-leave}
[:span {:class (stl/css :title)} title] [:span {:class (stl/css :menu-item-title)} title]
(when shortcut (when shortcut
[:span {:class (stl/css :shortcut)} [:span {:class (stl/css :shortcut)}
(for [[idx sc] (d/enumerate (scd/split-sc shortcut))] (for [[idx sc] (d/enumerate (scd/split-sc shortcut))]
@ -137,11 +139,11 @@
:customized-key customized?)} sc])]) :customized-key customized?)} sc])])
(when (> (count children) 1) (when (> (count children) 1)
[:span {:class (stl/css :submenu-icon)} [:span {:class (stl/css :icon)}
[:> icon* {:icon-id i/arrow :size "s"}]]) [:> icon* {:icon-id i/arrow :size "s"}]])
(when (> (count children) 1) (when (> (count children) 1)
[:ul {:class (stl/css :workspace-context-submenu) [:ul {:class (stl/css :submenu)
:ref submenu-ref :ref submenu-ref
:style {:display "none" :left 250} :style {:display "none" :left 250}
:on-context-menu prevent-default} :on-context-menu prevent-default}
@ -172,28 +174,35 @@
enabled-paste-props* (mf/use-state false) enabled-paste-props* (mf/use-state false)
handle-copy-css handle-copy-css
(mf/use-callback #(st/emit! (dw/copy-selected-css))) (mf/use-fn
#(st/emit! (dw/copy-selected-css)))
handle-copy-css-nested handle-copy-css-nested
(mf/use-callback #(st/emit! (dw/copy-selected-css-nested))) (mf/use-fn
#(st/emit! (dw/copy-selected-css-nested)))
handle-copy-props handle-copy-props
(mf/use-callback #(st/emit! (dw/copy-selected-props))) (mf/use-fn
#(st/emit! (dw/copy-selected-props)))
handle-paste-props handle-paste-props
(mf/use-callback #(st/emit! (dw/paste-selected-props))) (mf/use-fn
#(st/emit! (dw/paste-selected-props)))
handle-copy-svg handle-copy-svg
(mf/use-callback #(st/emit! (dw/copy-selected-svg))) (mf/use-fn
#(st/emit! (dw/copy-selected-svg)))
handle-copy-text handle-copy-text
(mf/use-callback #(st/emit! (dw/copy-selected-text))) (mf/use-fn
#(st/emit! (dw/copy-selected-text)))
handle-copy-as-image handle-copy-as-image
(mf/use-callback #(st/emit! (dw/copy-as-image))) (mf/use-fn
#(st/emit! (dw/copy-as-image)))
handle-hover-copy-paste handle-hover-copy-paste
(mf/use-callback (mf/use-fn
(fn [] (fn []
(->> (clipboard/from-navigator) (->> (clipboard/from-navigator)
(rx/mapcat #(.text %)) (rx/mapcat #(.text %))
@ -1011,8 +1020,8 @@
(dwg/remove-guide guide))))] (dwg/remove-guide guide))))]
[:* [:*
[:li {:class (stl/css :context-menu-item :guide-color-label)} [:li {:class (stl/css :menu-item :guide-color-label)}
[:span {:class (stl/css :title)} [:span {:class (stl/css :menu-item-title)}
(tr "workspace.context-menu.guides.change-color")]] (tr "workspace.context-menu.guides.change-color")]]
[:li {:class (stl/css :guide-color-swatches)} [:li {:class (stl/css :guide-color-swatches)}
(for [color guide-color-presets] (for [color guide-color-presets]
@ -1051,13 +1060,13 @@
[:& dropdown {:show (boolean mdata) [:& dropdown {:show (boolean mdata)
:on-close #(st/emit! dw/hide-context-menu)} :on-close #(st/emit! dw/hide-context-menu)}
[:div {:class (stl/css :workspace-context-menu) [:div {:class (stl/css :menu-wrapper)
:ref dropdown-ref :ref dropdown-ref
:style {:top top :left left} :style {:top top :left left}
:data-testid "context-menu" :data-testid "context-menu"
:on-context-menu prevent-default} :on-context-menu prevent-default}
[:ul {:class (stl/css :context-list)} [:ul {:class (stl/css :menu)}
(if ^boolean read-only? (if ^boolean read-only?
[:> viewport-context-menu* {:mdata mdata}] [:> viewport-context-menu* {:mdata mdata}]
(case (:kind mdata) (case (:kind mdata)

View File

@ -4,143 +4,136 @@
// //
// Copyright (c) KALEIDOS INC Sucursal en España SL // Copyright (c) KALEIDOS INC Sucursal en España SL
@use "refactor/common-refactor.scss" as deprecated; @use "ds/_utils" as *;
@use "ds/_sizes" as *;
@use "ds/_borders" as *;
@use "ds/spacing" as *;
@use "ds/typography" as *;
@use "ds/z-index" as *;
.workspace-context-menu { .menu-wrapper {
position: absolute; position: absolute;
top: deprecated.$s-40; inset-block-start: $sz-40;
left: deprecated.$s-736; inset-inline-start: px2rem(736);
z-index: deprecated.$z-index-4; z-index: var(--z-index-dropdown);
} }
.context-list, .menu,
.workspace-context-submenu { .submenu {
@include deprecated.menu-shadow; box-shadow: 0 0 0.75rem 0 var(--color-shadow-dark);
display: grid; display: grid;
width: deprecated.$s-240; inline-size: px2rem(240);
padding: deprecated.$s-4; padding: var(--sp-xs);
border-radius: deprecated.$br-8; border-radius: $br-8;
border: deprecated.$s-2 solid var(--color-background-quaternary); border: $b-2 solid var(--color-background-quaternary);
background-color: var(--color-background-tertiary); background-color: var(--color-background-tertiary);
max-height: 100vh; max-block-size: 100vh;
overflow-y: auto; overflow-y: auto;
} }
.workspace-context-submenu { .submenu {
position: absolute; position: absolute;
} }
.separator { .menu-item {
height: deprecated.$s-12; --menu-item-bg-color: var(--color-background-tertiary);
} --menu-item-title-color: var(--color-foreground-primary);
--menu-item-shortcut-color: var(--color-foreground-secondary);
.context-menu-item { --menu-item-shortcut-border-color: transparent;
--context-menu-item-bg-color: var(--color-background-tertiary);
--context-menu-item-title-color: var(--color-foreground-primary);
--context-menu-item-shortcut-color: var(--color-foreground-secondary);
--context-menu-item-shortcut-bg-color: var(--color-background-primary);
--context-menu-item-shortcut-border-color: transparent;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
height: deprecated.$s-28; block-size: $sz-28;
width: 100%; inline-size: 100%;
padding: deprecated.$s-6; padding: px2rem(6);
border-radius: deprecated.$br-8; border-radius: $br-8;
cursor: pointer; background-color: var(--menu-item-bg-color);
background-color: var(--context-menu-item-bg-color); border: $b-1 solid var(--menu-item-shortcut-border-color);
border: 1px solid var(--context-menu-item-shortcut-border-color);
&:hover { &:hover {
--context-menu-item-title-color: var(--menu-foreground-color-hover); --menu-item-title-color: var(--color-foreground-primary);
--context-menu-item-bg-color: var(--menu-background-color-hover); --menu-item-bg-color: var(--color-background-quaternary);
--context-menu-item-shortcut-color: var(--menu-shortcut-foreground-color-hover); --menu-item-shortcut-color: var(--color-foreground-primary);
} }
&:focus { &:focus {
--context-menu-item-bg-color: var(--menu-background-color-focus); --menu-item-bg-color: var(--color-background-tertiary);
--context-menu-item-shortcut-border-color: var(--menu-border-color-focus); --menu-item-shortcut-border-color: var(--color-accent-primary);
} }
} }
.title { .menu-item-icon {
@include deprecated.body-small-typography;
color: var(--context-menu-item-title-color);
}
.shortcut {
@include deprecated.flex-center;
gap: deprecated.$s-2;
color: var(--context-menu-item-shortcut-color);
}
.shortcut-key {
@include deprecated.body-small-typography;
@include deprecated.flex-center;
height: deprecated.$s-20;
padding: deprecated.$s-2 deprecated.$s-6;
border-radius: deprecated.$br-6;
background-color: var(--context-menu-item-shortcut-bg-color);
}
.submenu-icon svg {
@extend %button-icon-small;
stroke: var(--menu-foreground-color);
}
.icon-menu-item {
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
height: deprecated.$s-28; gap: px2rem(6);
padding: deprecated.$s-6; block-size: $sz-28;
border-radius: deprecated.$br-8; padding: px2rem(6);
border-radius: $br-8;
&:hover { &:hover {
background-color: var(--menu-background-color-hover); background-color: var(--color-background-quaternary);
}
span.title {
margin-left: deprecated.$s-6;
}
.selected-icon {
svg {
@extend %button-icon-small;
stroke: var(--menu-foreground-color);
}
}
.shape-icon {
margin-left: deprecated.$s-2;
svg {
@extend %button-icon-small;
stroke: var(--menu-foreground-color);
}
}
.icon-wrapper {
display: grid;
grid-template-columns: 1fr 1fr;
margin: 0;
} }
} }
.icon-menu-item[disabled], .menu-item-icon[disabled],
.context-menu-item[disabled] { .menu-item[disabled] {
pointer-events: none; pointer-events: none;
opacity: 0.6; opacity: 0.6;
} }
.menu-item-icon-group {
display: flex;
justify-content: center;
align-items: center;
gap: var(--sp-xxs);
}
.menu-item-title {
@include use-typography("body-small");
color: var(--menu-item-title-color);
}
.shortcut {
display: flex;
justify-content: center;
align-items: center;
gap: var(--sp-xxs);
color: var(--menu-item-shortcut-color);
}
.shortcut-key {
@include use-typography("body-small");
display: flex;
justify-content: center;
align-items: center;
block-size: px2rem(20);
padding: var(--sp-xxs) px2rem(6);
border-radius: $br-6;
background-color: var(--color-background-primary);
&.customized-key {
background-color: var(--color-background-info);
color: var(--color-foreground-primary);
}
}
.icon {
display: flex;
justify-content: center;
align-items: center;
inline-size: $sz-16;
color: var(--color-foreground-primary);
stroke-width: 1.33px;
}
.separator {
block-size: $sz-12;
}
.guide-color-label { .guide-color-label {
cursor: default; cursor: default;
pointer-events: none; pointer-events: none;
@ -149,26 +142,21 @@
.guide-color-swatches { .guide-color-swatches {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: deprecated.$s-6; gap: px2rem(6);
padding: deprecated.$s-4 deprecated.$s-6 deprecated.$s-8; padding: var(--sp-xs) px2rem(6) var(--sp-s);
list-style: none; list-style: none;
} }
.guide-color-swatch { .guide-color-swatch {
width: deprecated.$s-20; inline-size: px2rem(20);
height: deprecated.$s-20; block-size: px2rem(20);
border-radius: 50%; border-radius: 50%;
cursor: pointer; cursor: pointer;
flex-shrink: 0; flex-shrink: 0;
box-sizing: border-box; box-sizing: border-box;
border: deprecated.$s-2 solid var(--panel-border-color); border: $b-2 solid var(--color-background-quaternary);
&.selected { &.selected {
border: deprecated.$s-2 solid var(--menu-foreground-color); border: $b-2 solid var(--color-foreground-primary);
} }
} }
.customized-key {
background-color: var(--color-background-info);
color: var(--color-foreground-primary);
}

View File

@ -53,7 +53,7 @@
{::mf/private true} {::mf/private true}
[] []
;; NOTE: This custom button may be replace by an action button when this variant is designed ;; NOTE: This custom button may be replace by an action button when this variant is designed
[:button {:class (stl/css :collapse-sidebar-button) [:button {:class (stl/css :collapse-button)
:on-click toggle-collapse-left-sidebar} :on-click toggle-collapse-left-sidebar}
[:> icon* {:icon-id i/arrow [:> icon* {:icon-id i/arrow
:size "s" :size "s"
@ -71,6 +71,7 @@
:title (tr "workspace.sidebar.expand") :title (tr "workspace.sidebar.expand")
:on-click toggle-collapse-left-sidebar} :on-click toggle-collapse-left-sidebar}
[:> icon* {:icon-id i/arrow [:> icon* {:icon-id i/arrow
:class (stl/css :collapsed-button-icon)
:size "s" :size "s"
:aria-label (tr "workspace.sidebar.expand")}]]]]) :aria-label (tr "workspace.sidebar.expand")}]]]])
@ -105,12 +106,12 @@
:on-toggle-collapsed on-toggle-sitemap-collapsed}] :on-toggle-collapsed on-toggle-sitemap-collapsed}]
(when-not ^boolean sitemap-collapsed? (when-not ^boolean sitemap-collapsed?
[:div {:class (stl/css :resize-area-horiz) [:div {:class (stl/css :layers-tab-resize-area)
:on-pointer-down on-pointer-down :on-pointer-down on-pointer-down
:on-lost-pointer-capture on-lost-pointer-capture :on-lost-pointer-capture on-lost-pointer-capture
:on-pointer-move on-pointer-move} :on-pointer-move on-pointer-move}
[:div {:class (stl/css :resize-handle-horiz)}]]) [:div {:class (stl/css :layers-tab-resize-handle)}]])
[:> layers-toolbox* {:size-parent width}]])) [:> layers-toolbox* {:size-parent width}]]))
@ -165,11 +166,10 @@
:id "assets"}]))) :id "assets"}])))
aside-class aside-class
(stl/css-case (stl/css-case :left-sidebar true
:left-settings-bar true :global/two-row (<= width 300)
:global/two-row (<= width 300) :global/three-row (and (> width 300) (<= width 400))
:global/three-row (and (> width 300) (<= width 400)) :global/four-row (> width 400))
:global/four-row (> width 400))
tabs-action-button tabs-action-button
(mf/with-memo [] (mf/with-memo []
@ -187,22 +187,22 @@
[:> left-header* {:file file [:> left-header* {:file file
:layout layout :layout layout
:project project :project project
:class (stl/css :left-header)}] :class (stl/css :left-sidebar-header)}]
[:div {:on-pointer-down on-pointer-down [:div {:on-pointer-down on-pointer-down
:on-lost-pointer-capture on-lost-pointer-capture :on-lost-pointer-capture on-lost-pointer-capture
:on-pointer-move on-pointer-move :on-pointer-move on-pointer-move
:class (stl/css :resize-area)}] :class (stl/css :left-sidebar-resize-area)}]
(cond (cond
(true? shortcuts?) (true? shortcuts?)
[:> shortcuts-container* {:class (stl/css :settings-bar-content)}] [:> shortcuts-container* {:class (stl/css :left-sidebar-content)}]
(true? show-debug?) (true? show-debug?)
[:> debug-panel* {:class (stl/css :settings-bar-content)}] [:> debug-panel* {:class (stl/css :left-sidebar-content)}]
:else :else
[:div {:class (stl/css :settings-bar-content)} [:div {:class (stl/css :left-sidebar-content)}
[:> tab-switcher* {:tabs tabs [:> tab-switcher* {:tabs tabs
:default "layers" :default "layers"
:selected (name section) :selected (name section)
@ -213,20 +213,17 @@
(case section (case section
:assets :assets
[:> assets-toolbox* [:> assets-toolbox* {:size (- width 58)
{:size (- width 58) :file-id file-id}]
:file-id file-id}]
:tokens :tokens
[:> tokens-sidebar-tab* [:> tokens-sidebar-tab* {:tokens-lib tokens-lib
{:tokens-lib tokens-lib :active-tokens active-tokens
:active-tokens active-tokens :resolved-active-tokens resolved-active-tokens}]
:resolved-active-tokens resolved-active-tokens}]
:layers :layers
[:> layers-content* [:> layers-content* {:layout layout
{:layout layout :width width}])]])]]))
:width width}])]])]]))
;; --- Right Sidebar (Component) ;; --- Right Sidebar (Component)
@ -245,7 +242,8 @@
(deref selected*) (deref selected*)
on-change-tab on-change-tab
(mf/use-fn #(reset! selected* %)) (mf/use-fn
#(reset! selected* %))
tabs tabs
(mf/with-memo [] (mf/with-memo []
@ -302,7 +300,8 @@
(use-resize-hook :code right-sidebar-default-width right-sidebar-default-width right-sidebar-default-max-width :x true :right) (use-resize-hook :code right-sidebar-default-width right-sidebar-default-width right-sidebar-default-max-width :x true :right)
on-change-section on-change-section
(mf/use-fn #(reset! current-section* %)) (mf/use-fn
#(reset! current-section* %))
on-expand on-expand
(mf/use-fn (mf/use-fn
@ -319,7 +318,7 @@
[:> (mf/provider muc/sidebar) {:value :right} [:> (mf/provider muc/sidebar) {:value :right}
[:> (mf/provider muc/active-tokens-by-type) {:value active-tokens-by-type} [:> (mf/provider muc/active-tokens-by-type) {:value active-tokens-by-type}
[:aside [:aside
{:class (stl/css-case :right-settings-bar true {:class (stl/css-case :right-sidebar true
:not-expand (not can-be-expanded?) :not-expand (not can-be-expanded?)
:expanded (or is-debug? (> width right-sidebar-default-width))) :expanded (or is-debug? (> width right-sidebar-default-width)))
@ -338,12 +337,11 @@
:on-lost-pointer-capture on-lost-pointer-capture :on-lost-pointer-capture on-lost-pointer-capture
:on-pointer-move on-pointer-move}]) :on-pointer-move on-pointer-move}])
[:> right-header* [:> right-header* {:file-id file-id
{:file-id file-id :layout layout
:layout layout :page-id page-id}]
:page-id page-id}]
[:div {:class (stl/css :settings-bar-inside)} [:div {:class (stl/css :right-sidebar-content)}
(cond (cond
is-comments? is-comments?
[:> comments-sidebar* {}] [:> comments-sidebar* {}]

View File

@ -4,110 +4,23 @@
// //
// Copyright (c) KALEIDOS INC Sucursal en España SL // Copyright (c) KALEIDOS INC Sucursal en España SL
@use "ds/_borders.scss" as *;
@use "ds/_sizes.scss" as *; @use "ds/_sizes.scss" as *;
@use "refactor/common-refactor.scss" as deprecated; @use "ds/_utils.scss" as *;
@use "ds/z-index.scss" as *;
.left-settings-bar { // Component: collapse-button*
display: grid;
grid-template: "header header" deprecated.$s-52 "content resize" 1fr / 1fr 0;
position: relative;
grid-area: left-sidebar;
min-width: var(--left-sidebar-width);
max-width: var(--left-sidebar-width-max);
width: var(--right-sidebar-width);
background-color: var(--panel-background-color);
height: 100vh;
max-height: 100vh;
z-index: deprecated.$z-index-1;
.resize-area { .collapse-button {
grid-area: resize;
}
}
.layers-tab {
padding-top: deprecated.$s-4;
overflow-x: hidden;
}
.left-header {
grid-area: header;
}
.settings-bar-content {
grid-area: content;
right: calc(-1 * deprecated.$s-8);
}
.resize-area {
position: absolute;
top: 0;
left: unset;
z-index: deprecated.$z-index-4;
width: deprecated.$s-8;
cursor: ew-resize;
height: 100%;
}
.tab-spacing {
margin-inline: deprecated.$s-12;
}
.right-settings-bar {
grid-area: right-sidebar;
display: grid;
grid-template-rows: auto minmax(0, 1fr);
height: 100vh;
width: var(--right-sidebar-width);
background-color: var(--panel-background-color);
z-index: deprecated.$z-index-1;
&.not-expand {
max-width: var(--right-sidebar-width);
}
&.expanded {
width: var(--right-sidebar-width, var(--right-sidebar-width));
}
.settings-bar-inside {
display: grid;
grid-template-columns: 100%;
grid-template-rows: 100%;
height: calc(100vh - deprecated.$s-52);
overflow: hidden;
}
}
.resize-area-horiz {
background-color: var(--panel-background-color);
position: absolute;
left: 0;
width: 100%;
padding: deprecated.$s-3 0 deprecated.$s-1 0;
height: deprecated.$s-6;
cursor: ns-resize;
}
.resize-handle-horiz {
border-bottom: deprecated.$s-2 solid var(--resize-area-border-color);
cursor: ns-resize;
}
.left-sidebar-tabs {
--tabs-nav-padding-inline-start: var(--sp-m);
--tabs-nav-padding-inline-end: var(--sp-m);
}
.collapse-sidebar-button {
--collapse-icon-color: var(--color-foreground-secondary); --collapse-icon-color: var(--color-foreground-secondary);
@include deprecated.flex-center; display: flex;
@include deprecated.button-style; justify-content: center;
align-items: center;
height: 100%; border: none;
width: deprecated.$s-24; background: none;
border-radius: deprecated.$br-5; block-size: 100%;
inline-size: $sz-24;
color: var(--collapse-icon-color); color: var(--collapse-icon-color);
transform: rotate(180deg); transform: rotate(180deg);
@ -116,58 +29,150 @@
} }
} }
.collapsed-sidebar { // Component: collapsed-button*
@include deprecated.flex-center;
.collapsed-sidebar {
display: flex;
justify-content: center;
align-items: center;
position: absolute; position: absolute;
top: deprecated.$s-48; inset-block-start: px2rem(48);
left: 0; inset-inline-start: 0;
padding: deprecated.$s-4; padding: var(--sp-xs);
border-radius: deprecated.$br-8; border-radius: $br-8;
background: var(--color-background-primary); background: var(--color-background-primary);
margin-inline-start: var(--sp-m); margin-inline-start: var(--sp-m);
} }
.collapsed-title { .collapsed-title {
@include deprecated.flex-center; display: flex;
justify-content: center;
height: deprecated.$s-36; align-items: center;
width: deprecated.$s-24; block-size: $sz-36;
border-radius: deprecated.$br-8; inline-size: $sz-24;
border-radius: $br-8;
background: var(--color-background-secondary); background: var(--color-background-secondary);
} }
.collapsed-button { .collapsed-button {
@include deprecated.button-style; --collapsed-icon-color: var(--color-foreground-secondary);
height: deprecated.$s-24; border: none;
width: deprecated.$s-16; background: none;
block-size: $sz-24;
inline-size: $sz-16;
padding: 0; padding: 0;
border-radius: deprecated.$br-5;
svg {
@include deprecated.flex-center;
height: deprecated.$s-16;
width: deprecated.$s-16;
color: transparent;
fill: none;
stroke: var(--icon-foreground);
}
&:hover { &:hover {
svg { --collapsed-icon-color: var(--color-foreground-primary);
stroke: var(--icon-foreground-hover);
}
} }
} }
.versions-tab { .collapsed-button-icon {
width: 100%; color: var(--collapsed-icon-color);
overflow: hidden; display: flex;
height: calc(100vh - deprecated.$s-88); justify-content: center;
align-items: center;
} }
// Component: layers-content*
.layers-tab {
padding-block-start: var(--sp-xs);
overflow-x: hidden;
}
.layers-tab-resize-area {
background-color: var(--color-background-primary);
position: absolute;
inset-inline-start: 0;
inline-size: 100%;
padding: px2rem(3) 0 px2rem(1);
block-size: $sz-6;
cursor: ns-resize;
}
.layers-tab-resize-handle {
border-block-end: $b-2 solid var(--color-background-quaternary);
cursor: ns-resize;
}
// Component: left-sidebar*
.left-sidebar {
display: grid;
grid-template: "header header" px2rem(52) "content resize" 1fr / 1fr 0;
position: relative;
grid-area: left-sidebar;
min-inline-size: var(--left-sidebar-width);
max-inline-size: var(--left-sidebar-width-max);
inline-size: var(--left-sidebar-width);
background-color: var(--color-background-primary);
block-size: 100vh;
max-block-size: 100vh;
z-index: var(--z-index-panels);
}
.left-sidebar-header {
grid-area: header;
}
.left-sidebar-content {
grid-area: content;
inset-inline-end: calc(-1 * var(--sp-s));
}
.left-sidebar-tabs {
--tabs-nav-padding-inline-start: var(--sp-m);
--tabs-nav-padding-inline-end: var(--sp-m);
}
.left-sidebar-resize-area {
grid-area: resize;
position: absolute;
inset-block-start: 0;
inset-inline-start: unset;
inline-size: var(--sp-s);
block-size: 100%;
cursor: ew-resize;
}
// Component: right-sidebar*
.right-sidebar {
grid-area: right-sidebar;
display: grid;
grid-template-rows: auto minmax(0, 1fr);
block-size: 100vh;
inline-size: var(--right-sidebar-width);
background-color: var(--color-background-primary);
z-index: var(--z-index-panels);
&.not-expand {
max-inline-size: var(--right-sidebar-width);
}
&.expanded {
inline-size: var(--right-sidebar-width, var(--right-sidebar-width));
}
}
.right-sidebar-content {
display: grid;
grid-template-columns: 100%;
grid-template-rows: 100%;
block-size: calc(100vh - px2rem(52));
overflow: hidden;
}
// Component: history-content*
.history-tab { .history-tab {
overflow-y: auto; overflow-y: auto;
} }
.versions-tab {
inline-size: 100%;
overflow: hidden;
block-size: calc(100vh - $sz-88);
}

View File

@ -32,7 +32,8 @@
;; Helpers --------------------------------------------------------------------- ;; Helpers ---------------------------------------------------------------------
(defn- key-in-map? [ks m] (defn- key-in-map?
[ks m]
(some #(contains? m %) ks)) (some #(contains? m %) ks))
(defn clean-separators (defn clean-separators
@ -48,14 +49,16 @@
;; Actions --------------------------------------------------------------------- ;; Actions ---------------------------------------------------------------------
(defn attribute-actions [token selected-shapes attributes] (defn attribute-actions
[token selected-shapes attributes]
(let [ids-by-attributes (cfo/shapes-ids-by-applied-attributes token selected-shapes attributes) (let [ids-by-attributes (cfo/shapes-ids-by-applied-attributes token selected-shapes attributes)
shape-ids (into #{} (map :id selected-shapes))] shape-ids (into #{} (map :id selected-shapes))]
{:all-selected? (cfo/shapes-applied-all? ids-by-attributes shape-ids attributes) {:all-selected? (cfo/shapes-applied-all? ids-by-attributes shape-ids attributes)
:shape-ids shape-ids :shape-ids shape-ids
:selected-pred #(seq (% ids-by-attributes))})) :selected-pred #(seq (% ids-by-attributes))}))
(defn generic-attribute-actions [attributes title {:keys [token selected-shapes on-update-shape hint allowed-shape-attributes]}] (defn generic-attribute-actions
[attributes title {:keys [token selected-shapes on-update-shape hint allowed-shape-attributes]}]
(let [allowed-attributes (set/intersection attributes allowed-shape-attributes) (let [allowed-attributes (set/intersection attributes allowed-shape-attributes)
on-update-shape-fn (or on-update-shape (dwta/get-update-shape-fn token)) on-update-shape-fn (or on-update-shape (dwta/get-update-shape-fn token))
@ -80,8 +83,9 @@
(st/emit! (dwta/apply-token (assoc props :on-update-shape on-update-shape-fn)))))})) (st/emit! (dwta/apply-token (assoc props :on-update-shape on-update-shape-fn)))))}))
allowed-attributes))) allowed-attributes)))
(defn all-or-separate-actions [{:keys [attribute-labels on-update-shape-all on-update-shape hint]} (defn all-or-separate-actions
{:keys [token selected-shapes allowed-shape-attributes]}] [{:keys [attribute-labels on-update-shape-all on-update-shape hint]}
{:keys [token selected-shapes allowed-shape-attributes]}]
(when-let [attribute-labels (seq (select-keys attribute-labels allowed-shape-attributes))] (when-let [attribute-labels (seq (select-keys attribute-labels allowed-shape-attributes))]
(let [attributes (-> (keys attribute-labels) (set)) (let [attributes (-> (keys attribute-labels) (set))
{:keys [all-selected? selected-pred shape-ids]} (attribute-actions token selected-shapes attributes) {:keys [all-selected? selected-pred shape-ids]} (attribute-actions token selected-shapes attributes)
@ -117,7 +121,8 @@
attribute-labels)] attribute-labels)]
(concat (when all-action [all-action]) single-actions)))) (concat (when all-action [all-action]) single-actions))))
(defn layout-spacing-items [{:keys [token selected-shapes all-attr-labels horizontal-attr-labels vertical-attr-labels on-update-shape hint]}] (defn layout-spacing-items
[{:keys [token selected-shapes all-attr-labels horizontal-attr-labels vertical-attr-labels on-update-shape hint]}]
(let [horizontal-attrs (into #{} (keys horizontal-attr-labels)) (let [horizontal-attrs (into #{} (keys horizontal-attr-labels))
vertical-attrs (into #{} (keys vertical-attr-labels)) vertical-attrs (into #{} (keys vertical-attr-labels))
attrs (set/union horizontal-attrs vertical-attrs) attrs (set/union horizontal-attrs vertical-attrs)
@ -192,13 +197,15 @@
all-attr-labels)] all-attr-labels)]
(concat multi-items single-items))) (concat multi-items single-items)))
(defn update-shape-layout-padding [value shape-ids attributes] (defn update-shape-layout-padding
[value shape-ids attributes]
(st/emit! (st/emit!
(when (= (count attributes) 1) (when (= (count attributes) 1)
(dwsl/update-layout shape-ids {:layout-padding-type :multiple})) (dwsl/update-layout shape-ids {:layout-padding-type :multiple}))
(dwta/update-layout-padding value shape-ids attributes))) (dwta/update-layout-padding value shape-ids attributes)))
(defn update-shape-layout-margin [value shape-ids attributes] (defn update-shape-layout-margin
[value shape-ids attributes]
(st/emit! (st/emit!
(when (= (count attributes) 1) (when (= (count attributes) 1)
(dwsl/update-layout shape-ids {:layout-item-margin-type :multiple})) (dwsl/update-layout shape-ids {:layout-item-margin-type :multiple}))
@ -206,7 +213,8 @@
(defn spacing-attribute-actions [{:keys [token selected-shapes allowed-shape-attributes is-selected-inside-layout] :as context-data}] (defn spacing-attribute-actions
[{:keys [token selected-shapes allowed-shape-attributes is-selected-inside-layout] :as context-data}]
(let [padding-attr-labels {:p1 "Padding top" (let [padding-attr-labels {:p1 "Padding top"
:p2 "Padding right" :p2 "Padding right"
:p3 "Padding bottom" :p3 "Padding bottom"
@ -250,7 +258,8 @@
margin-items) margin-items)
(clean-separators)))) (clean-separators))))
(defn sizing-attribute-actions [context-data] (defn sizing-attribute-actions
[context-data]
(->> (->>
(concat (concat
(all-or-separate-actions {:attribute-labels {:width "Width" (all-or-separate-actions {:attribute-labels {:width "Width"
@ -272,7 +281,8 @@
context-data)) context-data))
(clean-separators))) (clean-separators)))
(defn update-shape-radius-for-corners [value shape-ids attributes] (defn update-shape-radius-for-corners
[value shape-ids attributes]
(st/emit! (st/emit!
(ptk/data-event :expand-border-radius) (ptk/data-event :expand-border-radius)
(dwta/update-shape-radius-for-corners value shape-ids attributes))) (dwta/update-shape-radius-for-corners value shape-ids attributes)))
@ -333,7 +343,8 @@
(generic-attribute-actions #{:y} "Y" (assoc context-data :on-update-shape dwta/update-shape-position))) (generic-attribute-actions #{:y} "Y" (assoc context-data :on-update-shape dwta/update-shape-position)))
(clean-separators)))})) (clean-separators)))}))
(defn default-actions [{:keys [token selected-token-set-id on-delete-token errors]}] (defn default-actions
[{:keys [token selected-token-set-id on-delete-token errors]}]
(let [{:keys [modal]} (dwta/get-token-properties token) (let [{:keys [modal]} (dwta/get-token-properties token)
on-copy-name #(clipboard/to-clipboard (:name token)) on-copy-name #(clipboard/to-clipboard (:name token))
on-duplicate-token #(st/emit! (dwtl/duplicate-token (:id token)))] on-duplicate-token #(st/emit! (dwtl/duplicate-token (:id token)))]
@ -361,7 +372,8 @@
:no-selectable true :no-selectable true
:action #(on-delete-token token)}])) :action #(on-delete-token token)}]))
(defn- allowed-shape-attributes [shapes] (defn- allowed-shape-attributes
[shapes]
(reduce into #{} (map #(ctt/shape-type->attributes (:type %) (:layout %)) shapes))) (reduce into #{} (map #(ctt/shape-type->attributes (:type %) (:layout %)) shapes)))
(defn menu-actions [{:keys [type token selected-shapes] :as context-data}] (defn menu-actions [{:keys [type token selected-shapes] :as context-data}]
@ -370,14 +382,16 @@
attribute-actions (if with-actions (with-actions context-data) [])] attribute-actions (if with-actions (with-actions context-data) [])]
attribute-actions)) attribute-actions))
(defn selection-actions [context-data] (defn selection-actions
[context-data]
(let [attribute-actions (menu-actions context-data)] (let [attribute-actions (menu-actions context-data)]
(concat (concat
attribute-actions attribute-actions
(when (seq attribute-actions) [:separator]) (when (seq attribute-actions) [:separator])
(default-actions context-data)))) (default-actions context-data))))
(defn submenu-actions-selection-actions [context-data] (defn submenu-actions-selection-actions
[context-data]
(menu-actions context-data)) (menu-actions context-data))
;; Components ------------------------------------------------------------------ ;; Components ------------------------------------------------------------------
@ -426,29 +440,27 @@
(when (some? parent-menu-dom-element) (when (some? parent-menu-dom-element)
(reset! parent-menu-dom-element-pos* (dm/str (.-offsetTop parent-menu-dom-element) "px")))))] (reset! parent-menu-dom-element-pos* (dm/str (.-offsetTop parent-menu-dom-element) "px")))))]
[:li {:class (stl/css-case [:li {:class (stl/css-case :menu-item true
:context-menu-item true :selected (and (not no-selectable) selected?)
:context-menu-item-selected (and (not no-selectable) selected?) :unselected (and (not no-selectable) (not selected?))
:context-menu-item-unselected (and (not no-selectable) (not selected?)) :hint hint?)
:context-menu-item-hint-wrapper hint?)
:ref get-parent-menu-entry-position :ref get-parent-menu-entry-position
:data-value value :data-value value
:on-click on-click :on-click on-click
:on-pointer-enter on-pointer-enter :on-pointer-enter on-pointer-enter
:on-pointer-leave on-pointer-leave} :on-pointer-leave on-pointer-leave}
(when hint (when hint
[:span {:class (stl/css :context-menu-item-hint)} hint]) [:span {:class (stl/css :menu-item-hint)} hint])
(when (not no-selectable) (when (not no-selectable)
[:> icon* {:icon-id i/tick :size "s" :class (stl/css :icon-wrapper)}]) [:> icon* {:icon-id i/tick :size "s" :class (stl/css :menu-item-icon)}])
[:span {:class (stl/css :item-text)} [:span {:class (stl/css :menu-item-text)}
title] title]
(when children (when children
[:* [:*
[:> icon* {:icon-id i/arrow :size "s"}] [:> icon* {:icon-id i/arrow :size "s"}]
[:ul {:ref submenu-ref [:ul {:ref submenu-ref
:class (stl/css-case :class (stl/css-case :submenu true
:token-context-submenu true :submenu-top is-submenu-outside?)
:token-context-submenu-top is-submenu-outside?)
:style {:left (dm/str submenu-offset "px") :style {:left (dm/str submenu-offset "px")
:top (if is-submenu-outside? "unset" parent-menu-dom-element-pos)} :top (if is-submenu-outside? "unset" parent-menu-dom-element-pos)}
:on-context-menu prevent-default} :on-context-menu prevent-default}
@ -503,7 +515,7 @@
(when (contains? #{:spacing :dimensions} token-type) (when (contains? #{:spacing :dimensions} token-type)
(some #(ctsl/any-layout-immediate-child? objects %) selected-shapes)))] (some #(ctsl/any-layout-immediate-child? objects %) selected-shapes)))]
[:ul {:class (stl/css :context-list)} [:ul {:class (stl/css :menu)}
[:& menu-tree {:submenu-offset width [:& menu-tree {:submenu-offset width
:token token :token token
:errors errors :errors errors
@ -550,7 +562,7 @@
(mf/html (mf/html
[:& dropdown {:show is-open? [:& dropdown {:show is-open?
:on-close #(st/emit! (dwtl/assign-token-context-menu nil))} :on-close #(st/emit! (dwtl/assign-token-context-menu nil))}
[:div {:class (stl/css :token-context-menu) [:div {:class (stl/css :menu-wrapper)
:data-testid "tokens-context-menu-for-token" :data-testid "tokens-context-menu-for-token"
:ref dropdown-ref :ref dropdown-ref
:data-direction dropdown-direction :data-direction dropdown-direction

View File

@ -4,131 +4,115 @@
// //
// Copyright (c) KALEIDOS INC Sucursal en España SL // Copyright (c) KALEIDOS INC Sucursal en España SL
@use "ds/_borders.scss" as *;
@use "ds/_sizes.scss" as *;
@use "ds/_utils.scss" as *;
@use "ds/typography.scss" as *; @use "ds/typography.scss" as *;
@use "refactor/common-refactor.scss" as deprecated;
.token-context-menu { .menu-wrapper {
position: absolute; position: absolute;
z-index: deprecated.$z-index-4; z-index: var(--z-index-dropdown);
} }
.token-context-menu[data-direction="up"] { .menu-wrapper[data-direction="up"] {
bottom: var(--bottom); bottom: var(--bottom);
} }
.token-context-menu[data-direction="down"] { .menu-wrapper[data-direction="down"] {
top: var(--top); top: var(--top);
} }
.context-list, .menu,
.token-context-submenu { .submenu {
@include deprecated.menu-shadow; box-shadow: 0 0 px2rem(12) 0 var(--color-shadow-dark);
display: grid; display: grid;
width: deprecated.$s-240; inline-size: px2rem(240);
padding: deprecated.$s-4; padding: var(--sp-xs);
border-radius: deprecated.$br-8; border-radius: $br-8;
border: deprecated.$s-2 solid var(--color-background-quaternary); border: $b-2 solid var(--color-background-quaternary);
background-color: var(--color-background-tertiary); background-color: var(--color-background-tertiary);
max-height: 100vh; max-block-size: 100vh;
overflow-y: auto; overflow-y: auto;
} }
.token-context-submenu { .submenu {
display: none; display: none;
}
.token-context-submenu-top {
bottom: 80px;
}
.token-context-submenu {
position: absolute; position: absolute;
padding: deprecated.$s-4; padding: var(--sp-xs);
margin-left: deprecated.$s-6; margin-inline-start: px2rem(6);
}
.submenu-top {
inset-block-end: px2rem(80);
} }
.separator { .separator {
margin: deprecated.$s-6; margin: px2rem(6);
border-block-start: deprecated.$s-1 solid var(--panel-border-color); border-block-start: $b-1 solid var(--color-background-quaternary);
} }
.context-menu-item { .menu-item {
--context-menu-item-bg-color: none; --menu-item-bg-color: none;
--context-menu-item-fg-color: var(--color-foreground-primary); --menu-item-fg-color: var(--color-foreground-primary);
--context-menu-item-border-color: none; --menu-item-border-color: none;
--menu-item-icon-color: none;
@include use-typography("body-small"); @include use-typography("body-small");
cursor: default;
display: flex; display: flex;
align-items: center; align-items: center;
height: deprecated.$s-32; block-size: $sz-32;
width: 100%; inline-size: 100%;
padding: deprecated.$s-8; padding: var(--sp-s);
border-radius: deprecated.$br-8; border-radius: $br-8;
color: var(--context-menu-item-fg-color); color: var(--menu-item-fg-color);
background-color: var(--context-menu-item-bg-color); background-color: var(--menu-item-bg-color);
border: deprecated.$s-1 solid var(--context-menu-item-border-color); border: $b-1 solid var(--menu-item-border-color);
cursor: pointer;
&:hover { &:hover {
--context-menu-item-bg-color: var(--color-background-quaternary); --menu-item-bg-color: var(--color-background-quaternary);
} }
&:focus { &:focus {
--context-menu-item-bg-color: var(--menu-background-color-focus); --menu-item-bg-color: var(--color-background-tertiary);
--context-menu-item-border-color: var(--color-background-tertiary); --menu-item-border-color: var(--color-background-tertiary);
} }
&[aria-selected="true"] { &.selected {
--context-menu-item-bg-color: var(--color-background-quaternary); --menu-item-icon-color: var(--color-accent-primary);
}
}
.context-menu-item-hint-wrapper {
position: relative;
}
.context-menu-item-selected {
& .icon-wrapper {
color: var(--color-accent-primary);
}
}
.context-menu-item-unselected {
color: var(--color-foreground-secondary);
& .icon-wrapper {
color: var(--color-background-quaternary);
} }
&:hover { &.unselected {
color: var(--color-foreground-primary); --menu-item-fg-color: var(--color-foreground-secondary);
--menu-item-icon-color: var(--color-background-quaternary);
& .icon-wrapper { &:hover {
color: var(--color-foreground-secondary); --menu-item-fg-color: var(--color-foreground-primary);
--menu-item-icon-color: var(--color-foreground-secondary);
} }
} }
&.hint {
position: relative;
}
} }
.context-menu-item-hint { .menu-item-hint {
position: absolute; position: absolute;
background-color: var(--color-background-primary); background-color: var(--color-background-primary);
border-radius: deprecated.$br-6; border-radius: $br-6;
padding: deprecated.$s-4; padding: var(--sp-xs);
inset-inline-end: deprecated.$s-4; inset-inline-end: var(--sp-xs);
inset-block-start: deprecated.$s-4; inset-block-start: var(--sp-xs);
color: var(--color-foreground-secondary); color: var(--color-foreground-secondary);
} }
.item-text { .menu-item-text {
flex-grow: 1; flex-grow: 1;
} }
.item-with-icon-space { .menu-item-icon {
padding-left: deprecated.$s-20; color: var(--menu-item-icon-color);
} margin-inline-end: var(--sp-xs);
.icon-wrapper {
margin-right: deprecated.$s-4;
} }