🐛 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-top: $s-1;
border-radius: $br-8;
z-index: $z-index-4;
z-index: var(--z-index-dropdown);
overflow: hidden auto;
background-color: var(--menu-background-color);
color: var(--menu-foreground-color);

View File

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

View File

@ -4,143 +4,136 @@
//
// 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;
top: deprecated.$s-40;
left: deprecated.$s-736;
z-index: deprecated.$z-index-4;
inset-block-start: $sz-40;
inset-inline-start: px2rem(736);
z-index: var(--z-index-dropdown);
}
.context-list,
.workspace-context-submenu {
@include deprecated.menu-shadow;
.menu,
.submenu {
box-shadow: 0 0 0.75rem 0 var(--color-shadow-dark);
display: grid;
width: deprecated.$s-240;
padding: deprecated.$s-4;
border-radius: deprecated.$br-8;
border: deprecated.$s-2 solid var(--color-background-quaternary);
inline-size: px2rem(240);
padding: var(--sp-xs);
border-radius: $br-8;
border: $b-2 solid var(--color-background-quaternary);
background-color: var(--color-background-tertiary);
max-height: 100vh;
max-block-size: 100vh;
overflow-y: auto;
}
.workspace-context-submenu {
.submenu {
position: absolute;
}
.separator {
height: deprecated.$s-12;
}
.context-menu-item {
--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;
.menu-item {
--menu-item-bg-color: var(--color-background-tertiary);
--menu-item-title-color: var(--color-foreground-primary);
--menu-item-shortcut-color: var(--color-foreground-secondary);
--menu-item-shortcut-border-color: transparent;
display: flex;
align-items: center;
justify-content: space-between;
height: deprecated.$s-28;
width: 100%;
padding: deprecated.$s-6;
border-radius: deprecated.$br-8;
cursor: pointer;
background-color: var(--context-menu-item-bg-color);
border: 1px solid var(--context-menu-item-shortcut-border-color);
block-size: $sz-28;
inline-size: 100%;
padding: px2rem(6);
border-radius: $br-8;
background-color: var(--menu-item-bg-color);
border: $b-1 solid var(--menu-item-shortcut-border-color);
&:hover {
--context-menu-item-title-color: var(--menu-foreground-color-hover);
--context-menu-item-bg-color: var(--menu-background-color-hover);
--context-menu-item-shortcut-color: var(--menu-shortcut-foreground-color-hover);
--menu-item-title-color: var(--color-foreground-primary);
--menu-item-bg-color: var(--color-background-quaternary);
--menu-item-shortcut-color: var(--color-foreground-primary);
}
&:focus {
--context-menu-item-bg-color: var(--menu-background-color-focus);
--context-menu-item-shortcut-border-color: var(--menu-border-color-focus);
--menu-item-bg-color: var(--color-background-tertiary);
--menu-item-shortcut-border-color: var(--color-accent-primary);
}
}
.title {
@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 {
.menu-item-icon {
display: flex;
justify-content: flex-start;
align-items: center;
height: deprecated.$s-28;
padding: deprecated.$s-6;
border-radius: deprecated.$br-8;
gap: px2rem(6);
block-size: $sz-28;
padding: px2rem(6);
border-radius: $br-8;
&:hover {
background-color: var(--menu-background-color-hover);
}
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;
background-color: var(--color-background-quaternary);
}
}
.icon-menu-item[disabled],
.context-menu-item[disabled] {
.menu-item-icon[disabled],
.menu-item[disabled] {
pointer-events: none;
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 {
cursor: default;
pointer-events: none;
@ -149,26 +142,21 @@
.guide-color-swatches {
display: flex;
flex-wrap: wrap;
gap: deprecated.$s-6;
padding: deprecated.$s-4 deprecated.$s-6 deprecated.$s-8;
gap: px2rem(6);
padding: var(--sp-xs) px2rem(6) var(--sp-s);
list-style: none;
}
.guide-color-swatch {
width: deprecated.$s-20;
height: deprecated.$s-20;
inline-size: px2rem(20);
block-size: px2rem(20);
border-radius: 50%;
cursor: pointer;
flex-shrink: 0;
box-sizing: border-box;
border: deprecated.$s-2 solid var(--panel-border-color);
border: $b-2 solid var(--color-background-quaternary);
&.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}
[]
;; 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}
[:> icon* {:icon-id i/arrow
:size "s"
@ -71,6 +71,7 @@
:title (tr "workspace.sidebar.expand")
:on-click toggle-collapse-left-sidebar}
[:> icon* {:icon-id i/arrow
:class (stl/css :collapsed-button-icon)
:size "s"
:aria-label (tr "workspace.sidebar.expand")}]]]])
@ -105,12 +106,12 @@
:on-toggle-collapsed on-toggle-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-lost-pointer-capture on-lost-pointer-capture
: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}]]))
@ -165,11 +166,10 @@
:id "assets"}])))
aside-class
(stl/css-case
:left-settings-bar true
:global/two-row (<= width 300)
:global/three-row (and (> width 300) (<= width 400))
:global/four-row (> width 400))
(stl/css-case :left-sidebar true
:global/two-row (<= width 300)
:global/three-row (and (> width 300) (<= width 400))
:global/four-row (> width 400))
tabs-action-button
(mf/with-memo []
@ -187,22 +187,22 @@
[:> left-header* {:file file
:layout layout
:project project
:class (stl/css :left-header)}]
:class (stl/css :left-sidebar-header)}]
[:div {:on-pointer-down on-pointer-down
:on-lost-pointer-capture on-lost-pointer-capture
:on-pointer-move on-pointer-move
:class (stl/css :resize-area)}]
:class (stl/css :left-sidebar-resize-area)}]
(cond
(true? shortcuts?)
[:> shortcuts-container* {:class (stl/css :settings-bar-content)}]
[:> shortcuts-container* {:class (stl/css :left-sidebar-content)}]
(true? show-debug?)
[:> debug-panel* {:class (stl/css :settings-bar-content)}]
[:> debug-panel* {:class (stl/css :left-sidebar-content)}]
:else
[:div {:class (stl/css :settings-bar-content)}
[:div {:class (stl/css :left-sidebar-content)}
[:> tab-switcher* {:tabs tabs
:default "layers"
:selected (name section)
@ -213,20 +213,17 @@
(case section
:assets
[:> assets-toolbox*
{:size (- width 58)
:file-id file-id}]
[:> assets-toolbox* {:size (- width 58)
:file-id file-id}]
:tokens
[:> tokens-sidebar-tab*
{:tokens-lib tokens-lib
:active-tokens active-tokens
:resolved-active-tokens resolved-active-tokens}]
[:> tokens-sidebar-tab* {:tokens-lib tokens-lib
:active-tokens active-tokens
:resolved-active-tokens resolved-active-tokens}]
:layers
[:> layers-content*
{:layout layout
:width width}])]])]]))
[:> layers-content* {:layout layout
:width width}])]])]]))
;; --- Right Sidebar (Component)
@ -245,7 +242,8 @@
(deref selected*)
on-change-tab
(mf/use-fn #(reset! selected* %))
(mf/use-fn
#(reset! selected* %))
tabs
(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)
on-change-section
(mf/use-fn #(reset! current-section* %))
(mf/use-fn
#(reset! current-section* %))
on-expand
(mf/use-fn
@ -319,7 +318,7 @@
[:> (mf/provider muc/sidebar) {:value :right}
[:> (mf/provider muc/active-tokens-by-type) {:value active-tokens-by-type}
[:aside
{:class (stl/css-case :right-settings-bar true
{:class (stl/css-case :right-sidebar true
:not-expand (not can-be-expanded?)
:expanded (or is-debug? (> width right-sidebar-default-width)))
@ -338,12 +337,11 @@
:on-lost-pointer-capture on-lost-pointer-capture
:on-pointer-move on-pointer-move}])
[:> right-header*
{:file-id file-id
:layout layout
:page-id page-id}]
[:> right-header* {:file-id file-id
:layout layout
:page-id page-id}]
[:div {:class (stl/css :settings-bar-inside)}
[:div {:class (stl/css :right-sidebar-content)}
(cond
is-comments?
[:> comments-sidebar* {}]

View File

@ -4,110 +4,23 @@
//
// Copyright (c) KALEIDOS INC Sucursal en España SL
@use "ds/_borders.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 {
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;
// Component: collapse-button*
.resize-area {
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-button {
--collapse-icon-color: var(--color-foreground-secondary);
@include deprecated.flex-center;
@include deprecated.button-style;
height: 100%;
width: deprecated.$s-24;
border-radius: deprecated.$br-5;
display: flex;
justify-content: center;
align-items: center;
border: none;
background: none;
block-size: 100%;
inline-size: $sz-24;
color: var(--collapse-icon-color);
transform: rotate(180deg);
@ -116,58 +29,150 @@
}
}
.collapsed-sidebar {
@include deprecated.flex-center;
// Component: collapsed-button*
.collapsed-sidebar {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: deprecated.$s-48;
left: 0;
padding: deprecated.$s-4;
border-radius: deprecated.$br-8;
inset-block-start: px2rem(48);
inset-inline-start: 0;
padding: var(--sp-xs);
border-radius: $br-8;
background: var(--color-background-primary);
margin-inline-start: var(--sp-m);
}
.collapsed-title {
@include deprecated.flex-center;
height: deprecated.$s-36;
width: deprecated.$s-24;
border-radius: deprecated.$br-8;
display: flex;
justify-content: center;
align-items: center;
block-size: $sz-36;
inline-size: $sz-24;
border-radius: $br-8;
background: var(--color-background-secondary);
}
.collapsed-button {
@include deprecated.button-style;
--collapsed-icon-color: var(--color-foreground-secondary);
height: deprecated.$s-24;
width: deprecated.$s-16;
border: none;
background: none;
block-size: $sz-24;
inline-size: $sz-16;
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 {
svg {
stroke: var(--icon-foreground-hover);
}
--collapsed-icon-color: var(--color-foreground-primary);
}
}
.versions-tab {
width: 100%;
overflow: hidden;
height: calc(100vh - deprecated.$s-88);
.collapsed-button-icon {
color: var(--collapsed-icon-color);
display: flex;
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 {
overflow-y: auto;
}
.versions-tab {
inline-size: 100%;
overflow: hidden;
block-size: calc(100vh - $sz-88);
}

View File

@ -32,7 +32,8 @@
;; Helpers ---------------------------------------------------------------------
(defn- key-in-map? [ks m]
(defn- key-in-map?
[ks m]
(some #(contains? m %) ks))
(defn clean-separators
@ -48,14 +49,16 @@
;; 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)
shape-ids (into #{} (map :id selected-shapes))]
{:all-selected? (cfo/shapes-applied-all? ids-by-attributes shape-ids attributes)
:shape-ids shape-ids
: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)
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)))))}))
allowed-attributes)))
(defn all-or-separate-actions [{:keys [attribute-labels on-update-shape-all on-update-shape hint]}
{:keys [token selected-shapes allowed-shape-attributes]}]
(defn all-or-separate-actions
[{: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))]
(let [attributes (-> (keys attribute-labels) (set))
{:keys [all-selected? selected-pred shape-ids]} (attribute-actions token selected-shapes attributes)
@ -117,7 +121,8 @@
attribute-labels)]
(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))
vertical-attrs (into #{} (keys vertical-attr-labels))
attrs (set/union horizontal-attrs vertical-attrs)
@ -192,13 +197,15 @@
all-attr-labels)]
(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!
(when (= (count attributes) 1)
(dwsl/update-layout shape-ids {:layout-padding-type :multiple}))
(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!
(when (= (count attributes) 1)
(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"
:p2 "Padding right"
:p3 "Padding bottom"
@ -250,7 +258,8 @@
margin-items)
(clean-separators))))
(defn sizing-attribute-actions [context-data]
(defn sizing-attribute-actions
[context-data]
(->>
(concat
(all-or-separate-actions {:attribute-labels {:width "Width"
@ -272,7 +281,8 @@
context-data))
(clean-separators)))
(defn update-shape-radius-for-corners [value shape-ids attributes]
(defn update-shape-radius-for-corners
[value shape-ids attributes]
(st/emit!
(ptk/data-event :expand-border-radius)
(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)))
(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)
on-copy-name #(clipboard/to-clipboard (:name token))
on-duplicate-token #(st/emit! (dwtl/duplicate-token (:id token)))]
@ -361,7 +372,8 @@
:no-selectable true
: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)))
(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))
(defn selection-actions [context-data]
(defn selection-actions
[context-data]
(let [attribute-actions (menu-actions context-data)]
(concat
attribute-actions
(when (seq attribute-actions) [:separator])
(default-actions context-data))))
(defn submenu-actions-selection-actions [context-data]
(defn submenu-actions-selection-actions
[context-data]
(menu-actions context-data))
;; Components ------------------------------------------------------------------
@ -426,29 +440,27 @@
(when (some? parent-menu-dom-element)
(reset! parent-menu-dom-element-pos* (dm/str (.-offsetTop parent-menu-dom-element) "px")))))]
[:li {:class (stl/css-case
:context-menu-item true
:context-menu-item-selected (and (not no-selectable) selected?)
:context-menu-item-unselected (and (not no-selectable) (not selected?))
:context-menu-item-hint-wrapper hint?)
[:li {:class (stl/css-case :menu-item true
:selected (and (not no-selectable) selected?)
:unselected (and (not no-selectable) (not selected?))
:hint hint?)
:ref get-parent-menu-entry-position
:data-value value
:on-click on-click
:on-pointer-enter on-pointer-enter
:on-pointer-leave on-pointer-leave}
(when hint
[:span {:class (stl/css :context-menu-item-hint)} hint])
[:span {:class (stl/css :menu-item-hint)} hint])
(when (not no-selectable)
[:> icon* {:icon-id i/tick :size "s" :class (stl/css :icon-wrapper)}])
[:span {:class (stl/css :item-text)}
[:> icon* {:icon-id i/tick :size "s" :class (stl/css :menu-item-icon)}])
[:span {:class (stl/css :menu-item-text)}
title]
(when children
[:*
[:> icon* {:icon-id i/arrow :size "s"}]
[:ul {:ref submenu-ref
:class (stl/css-case
:token-context-submenu true
:token-context-submenu-top is-submenu-outside?)
:class (stl/css-case :submenu true
:submenu-top is-submenu-outside?)
:style {:left (dm/str submenu-offset "px")
:top (if is-submenu-outside? "unset" parent-menu-dom-element-pos)}
:on-context-menu prevent-default}
@ -503,7 +515,7 @@
(when (contains? #{:spacing :dimensions} token-type)
(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
:token token
:errors errors
@ -550,7 +562,7 @@
(mf/html
[:& dropdown {:show is-open?
: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"
:ref dropdown-ref
:data-direction dropdown-direction

View File

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