diff --git a/frontend/resources/images/icons/hsva-refactor.svg b/frontend/resources/images/icons/hsva-refactor.svg
new file mode 100644
index 0000000000..eb7571bf58
--- /dev/null
+++ b/frontend/resources/images/icons/hsva-refactor.svg
@@ -0,0 +1,3 @@
+
diff --git a/frontend/resources/images/icons/picker-refactor.svg b/frontend/resources/images/icons/picker-refactor.svg
new file mode 100644
index 0000000000..05f1ed1a70
--- /dev/null
+++ b/frontend/resources/images/icons/picker-refactor.svg
@@ -0,0 +1,3 @@
+
diff --git a/frontend/resources/images/icons/rgba-complementary-refactor.svg b/frontend/resources/images/icons/rgba-complementary-refactor.svg
new file mode 100644
index 0000000000..35df1b9b53
--- /dev/null
+++ b/frontend/resources/images/icons/rgba-complementary-refactor.svg
@@ -0,0 +1,3 @@
+
diff --git a/frontend/resources/images/icons/rgba-refactor.svg b/frontend/resources/images/icons/rgba-refactor.svg
new file mode 100644
index 0000000000..236e6b4d29
--- /dev/null
+++ b/frontend/resources/images/icons/rgba-refactor.svg
@@ -0,0 +1,3 @@
+
diff --git a/frontend/resources/images/icons/switch-refactor.svg b/frontend/resources/images/icons/switch-refactor.svg
new file mode 100644
index 0000000000..4e802c8183
--- /dev/null
+++ b/frontend/resources/images/icons/switch-refactor.svg
@@ -0,0 +1,3 @@
+
diff --git a/frontend/resources/styles/common/refactor/basic-rules.scss b/frontend/resources/styles/common/refactor/basic-rules.scss
index d174fa4dc6..0206395eaf 100644
--- a/frontend/resources/styles/common/refactor/basic-rules.scss
+++ b/frontend/resources/styles/common/refactor/basic-rules.scss
@@ -4,6 +4,36 @@
//
// Copyright (c) KALEIDOS INC
+// SCROLLBAR
+.new-scrollbar {
+ ::-webkit-scrollbar {
+ background-color: transparent;
+ cursor: pointer;
+ height: $s-12;
+ width: $s-12;
+ }
+ ::-webkit-scrollbar-track,
+ ::-webkit-scrollbar-corner {
+ background-color: transparent;
+ }
+
+ ::-webkit-scrollbar-thumb {
+ background-color: rgba(170, 181, 186, 0.3);
+ background-clip: content-box;
+ border: $s-2 solid transparent;
+ border-radius: $br-8;
+ &:hover {
+ background-color: rgba(170, 181, 186, 0.7);
+ outline: none;
+ }
+ }
+
+ ::selection {
+ background-color: var(--color-accent-primary-muted);
+ }
+}
+
+// BUTTONS
.button-primary {
@include buttonStyle;
@include flexCenter;
@@ -235,14 +265,130 @@
stroke-width: 1.33px;
}
-.link {
- background: unset;
- border: none;
- color: var(--link-foreground-color);
- cursor: pointer;
- text-decoration: none;
+.button-constraint {
+ @include buttonStyle;
+ width: $s-32;
+ height: $s-4;
+ border-radius: $br-8;
+ background-color: var(--button-constraint-background-color-rest);
+ padding: 0;
+ margin: 0;
+ &:hover,
+ &:focus {
+ outline: $s-4 solid var(--button-constraint-border-color-hover);
+ background-color: var(--button-constraint-background-color-hover);
+ }
}
+// INPUTS
+
+.input-base {
+ @include removeInputStyle;
+ @include titleTipography;
+ @include textEllipsis;
+ height: $s-28;
+ width: 100%;
+ margin: $s-2 0;
+ padding: 0 0 0 $s-4;
+ color: var(--input-foreground-color-active);
+ &:focus-within,
+ &:active {
+ color: var(--input-foreground-color-active);
+ background-color: var(--input-background-color-active);
+ }
+}
+
+.input-icon {
+ @include flexCenter;
+ min-width: $s-12;
+ height: $s-32;
+ margin-right: $s-4;
+ svg {
+ @extend .button-icon;
+ }
+}
+
+.input-label {
+ @include tabTitleTipography;
+ @include flexCenter;
+ min-width: $s-12;
+ height: $s-32;
+ margin-right: $s-4;
+ color: var(--input-foreground-color);
+}
+
+.input-element {
+ @include titleTipography;
+ display: flex;
+ align-items: center;
+ height: $s-32;
+ padding: 0 $s-4;
+ border-radius: $br-8;
+ background-color: var(--input-background-color);
+ border: $s-1 solid var(--input-background-color);
+ color: var(--input-foreground-color);
+ span {
+ @extend .input-label;
+ svg {
+ @extend .button-icon;
+ stroke: var(--input-foreground-color);
+ }
+ }
+
+ input {
+ @extend .input-base;
+ }
+ ::placeholder {
+ color: var(--input-placeholder-color);
+ }
+ &:hover {
+ span {
+ color: var(--input-foreground-color);
+ }
+ input {
+ color: var(--input-foreground-color-active);
+ }
+ background-color: var(--input-background-color-hover);
+ }
+
+ &:focus-within,
+ &:active {
+ input {
+ color: var(--input-foreground-color-active);
+ }
+ background-color: var(--input-background-color-active);
+ border: $s-1 solid var(--input-border-color-active);
+ }
+}
+
+.disabled-input {
+ background-color: var(--input-background-color-disabled);
+ border: 1px solid var(--input-border-color-disabled);
+ color: var(--input-foreground-color-disabled);
+ input {
+ pointer-events: none;
+ cursor: default;
+ color: var(--input-foreground-color-disabled);
+ }
+ span svg {
+ stroke: var(--input-foreground-color-disabled);
+ }
+}
+
+//MODALS
+.modal-background {
+ @include menuShadow;
+ position: absolute;
+ display: flex;
+ flex-direction: column;
+ padding: $s-12;
+ border-radius: $br-8;
+ z-index: $z-index-10;
+ color: var(--color-foreground-primary);
+ background-color: var(--modal-background-color);
+}
+
+// UI ELEMENTS
.asset-element {
@include titleTipography;
display: flex;
@@ -259,89 +405,6 @@
}
}
-.input-element {
- @include titleTipography;
- display: flex;
- align-items: center;
- height: $s-32;
- border-radius: $br-8;
- background-color: var(--input-background-color);
- color: var(--input-foreground-color);
- span {
- color: var(--input-foreground-color);
- }
- input {
- @include removeInputStyle;
- @include titleTipography;
- color: var(--input-foreground-color);
- height: $s-32;
- }
- ::placeholder {
- color: var(--input-placeholder-color);
- }
- &:hover,
- &:focus-within {
- span {
- color: var(--input-foreground-color);
- }
- input {
- color: var(--input-foreground-color-active);
- }
- background-color: var(--input-background-color-hover);
- }
-}
-.new-scrollbar {
- ::-webkit-scrollbar {
- background-color: transparent;
- cursor: pointer;
- height: $s-12;
- width: $s-12;
- }
- ::-webkit-scrollbar-track,
- ::-webkit-scrollbar-corner {
- background-color: transparent;
- }
-
- ::-webkit-scrollbar-thumb {
- background-color: rgba(170, 181, 186, 0.3);
- background-clip: content-box;
- border: $s-2 solid transparent;
- border-radius: $br-8;
- &:hover {
- background-color: rgba(170, 181, 186, 0.7);
- outline: none;
- }
- }
-}
-
-.menu-dropdown {
- @include menuShadow;
- color: var(--title-foreground-color-hover);
- display: flex;
- flex-direction: column;
- gap: $s-4;
- width: $s-192;
- padding: $s-4;
- border-radius: $br-8;
- background-color: var(--menu-background-color);
- z-index: $z-index-10;
-}
-
-.menu-item {
- @include titleTipography;
- display: flex;
- align-items: center;
- justify-content: space-between;
- height: $s-28;
- width: 100%;
- padding: $s-6;
- border-radius: $br-8;
- cursor: pointer;
- &:hover {
- background-color: var(--menu-background-color-hover);
- }
-}
-
.shortcut {
@include flexCenter;
gap: $s-2;
@@ -368,3 +431,114 @@
border: $s-2 solid var(--user-count-foreground-color);
}
}
+
+.mixed-bar {
+ @include titleTipography;
+ display: flex;
+ align-items: center;
+ flex-grow: 1;
+ border-radius: $br-8;
+ height: $s-32;
+ padding: $s-8;
+ background-color: var(--input-background-color);
+ color: var(--input-foreground-color-active);
+}
+
+.link {
+ background: unset;
+ border: none;
+ color: var(--link-foreground-color);
+ cursor: pointer;
+ text-decoration: none;
+}
+
+.colorpicker-handler {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ width: $s-24;
+ height: $s-24;
+ border: $s-2 solid var(--colorpicker-details-color);
+ border-radius: $br-circle;
+ transform: translate(calc(-1 * $s-12), calc(-1 * $s-12));
+ z-index: $z-index-1;
+ &:hover,
+ &:active {
+ border-color: var(--colorpicker-details-color-selected);
+ }
+}
+// SELECTS AND DROPDOWNS
+
+.menu-dropdown {
+ @include menuShadow;
+ position: absolute;
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ padding: $s-4;
+ border-radius: $br-8;
+ z-index: $z-index-10;
+ color: var(--title-foreground-color-hover);
+ background-color: var(--menu-background-color);
+}
+
+.menu-item {
+ @include titleTipography;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ height: $s-28;
+ width: 100%;
+ padding: $s-6;
+ border-radius: $br-8;
+ cursor: pointer;
+ &:hover {
+ background-color: var(--menu-background-color-hover);
+ }
+}
+
+.dropdown-element-base {
+ @include titleTipography;
+ display: flex;
+ align-items: center;
+ gap: $s-8;
+ height: $s-32;
+ padding: 0 $s-8;
+ border-radius: $br-6;
+ cursor: pointer;
+ color: var(--menu-foreground-color-rest);
+
+ span {
+ @include flexCenter;
+ @include textEllipsis;
+ svg {
+ @extend .button-icon-small;
+ stroke: var(--icon-foreground);
+ }
+ }
+ &:hover {
+ background-color: var(--menu-background-color-hover);
+ color: var(--menu-foreground-color);
+ span svg {
+ stroke: var(--menu-foreground-color-hover);
+ }
+ }
+}
+
+.dropdown-wrapper {
+ @include menuShadow;
+ position: absolute;
+ top: $s-32;
+ left: 0;
+ width: 100%;
+ max-height: $s-300;
+ padding: $s-2;
+ margin: 0;
+ margin-top: $s-4;
+ border-radius: $br-8;
+ z-index: $z-index-3;
+ overflow-y: auto;
+ overflow-x: hidden;
+ background-color: var(--menu-background-color);
+ color: var(--menu-foreground-color);
+}
diff --git a/frontend/resources/styles/common/refactor/design-tokens.scss b/frontend/resources/styles/common/refactor/design-tokens.scss
index 199fe20118..aec6339a37 100644
--- a/frontend/resources/styles/common/refactor/design-tokens.scss
+++ b/frontend/resources/styles/common/refactor/design-tokens.scss
@@ -77,6 +77,13 @@
--button-disabled-border-color-rest: var(--color-background-disabled);
--button-disabled-foreground-color-rest: var(--color-foreground-disabled);
+ --button-constraint-background-color-rest: var(--color-foreground-secondary);
+ --button-constraint-border-color-rest: var(--color-background-tertiary);
+ --button-constraint-border-color-hover: var(--color-accent-primary-muted);
+ --button-constraint-background-color-hover: var(--color-accent-primary);
+ --constraint-widget-background-color: var(--color-background-tertiary);
+ --constraint-center-area-background-color: var(--color-background-primary);
+
--icon-foreground: var(--color-foreground-secondary);
--icon-foreground-hover: var(--color-foreground-primary);
@@ -111,18 +118,19 @@
--search-bar-input-border-color: var(--color-background-tertiary);
--input-background-color: var(--color-background-tertiary);
- --input-background-color-active: var(--color-background-primary);
+ --input-foreground-color: var(--color-foreground-secondary);
+ --input-placeholder-color: var(--color-foreground-secondary);
--input-background-color-hover: var(--color-background-quaternary);
--input-background-color-focus: var(--color-background-tertiary);
- --input-background-color-disabled: var(--color-background-primary);
- --input-placeholder-color: var(--color-foreground-secondary);
- --input-foreground-color: var(--color-foreground-secondary);
- --input-foreground-color-active: var(--color-foreground-primary);
- --input-foreground-color-disabled: var(--color-foreground-secondary);
- --input-border-color-active: var(--color-accent-primary);
- --input-border-color-disabled: var(--color-background-quaternary);
- --input-border-outline-color-active: var(--color-accent-primary-muted);
--input-border-color-focus: var(--color-accent-primary);
+ --input-background-color-active: var(--color-background-primary);
+ --input-foreground-color-active: var(--color-foreground-primary);
+ --input-border-outline-color-active: var(--color-accent-primary-muted);
+ --input-border-color-active: var(--color-accent-primary);
+ --input-background-color-disabled: var(--color-background-primary);
+ --input-foreground-color-disabled: var(--color-foreground-secondary);
+ --input-border-color-disabled: var(--color-background-quaternary);
+ --input-details-color: var(--color-background-primary);
--pill-background-color: var(--color-background-tertiary);
--pill-foreground-color: var(--color-foreground-primary);
@@ -130,17 +138,20 @@
--menu-background-color: var(--color-background-tertiary);
--menu-foreground-color: var(--color-foreground-primary);
--menu-background-color-selected: var(--color-background-tertiary);
- --menu-foreground-color-selected: var(--color-foreground-primary);
--menu-background-color-hover: var(--color-background-quaternary);
--menu-foreground-color-hover: var(--color-foreground-primary);
--menu-background-color-focus: var(--color-background-tertiary);
--menu-foreground-color-focus: var(--color-foreground-primary);
+ --menu-foreground-color-rest: var(--color-foreground-secondary);
--menu-border-color-focus: var(--color-accent-primary);
--menu-shortcut-background-color: var(--color-background-primary);
--menu-shortcut-foreground-color: var(--color-foreground-secondary);
--menu-shortcut-foreground-color-selected: var(--color-foreground-primary);
--menu-shortcut-foreground-color-hover: var(--color-foreground-primary);
--menu-shadow-color: var(--color-background-subtle);
+ --menu-background-color-disabled: var(--color-background-primary);
+ --menu-foreground-color-disabled: var(--color-foreground-secondary);
+ --menu-border-color-disabled: var(--color-background-quaternary);
--tag-background-color: var(--color-accent-primary);
@@ -210,4 +221,8 @@
--modal-background-color: var(--color-background-primary);
--modal-foreground-color: var(--color-foreground-primary);
--modal-foreground-color-secondary: var(--color-foreground-secondary);
+
+ --colorpicker-details-color: var(--color-background-quaternary);
+ --colorpicker-details-color-selected: var(--color-accent-primary);
+ --colorpicker-handlers-color: var(--color-foreground-primary);
}
diff --git a/frontend/resources/styles/common/refactor/spacing.scss b/frontend/resources/styles/common/refactor/spacing.scss
index f2e18cd90d..e955e84789 100644
--- a/frontend/resources/styles/common/refactor/spacing.scss
+++ b/frontend/resources/styles/common/refactor/spacing.scss
@@ -33,11 +33,13 @@ $s-80: calc(var(--s-4) * 20);
$s-84: calc(var(--s-4) * 21);
$s-92: calc(var(--s-4) * 23);
$s-96: calc(var(--s-4) * 24);
+$s-100: calc(var(--s-4) * 25);
$s-104: calc(var(--s-4) * 26);
$s-108: calc(var(--s-4) * 27);
$s-116: calc(var(--s-4) * 29);
$s-120: calc(var(--s-4) * 30);
$s-124: calc(var(--s-4) * 31);
+$s-128: calc(var(--s-4) * 32);
$s-136: calc(var(--s-4) * 34);
$s-140: calc(var(--s-4) * 35);
$s-148: calc(var(--s-4) * 37);
@@ -45,6 +47,7 @@ $s-156: calc(var(--s-4) * 39);
$s-152: calc(var(--s-4) * 38);
$s-160: calc(var(--s-4) * 40);
$s-168: calc(var(--s-4) * 42);
+$s-172: calc(var(--s-4) * 43);
$s-180: calc(var(--s-4) * 45);
$s-184: calc(var(--s-4) * 46);
$s-188: calc(var(--s-4) * 47);
@@ -53,10 +56,12 @@ $s-196: calc(var(--s-4) * 49);
$s-200: calc(var(--s-4) * 50);
$s-216: calc(var(--s-4) * 54);
$s-220: calc(var(--s-4) * 55);
+$s-228: calc(var(--s-4) * 57);
$s-240: calc(var(--s-4) * 60);
$s-248: calc(var(--s-4) * 62);
$s-252: calc(var(--s-4) * 63);
$s-256: calc(var(--s-4) * 64);
+$s-260: calc(var(--s-4) * 65);
$s-272: calc(var(--s-4) * 68);
$s-276: calc(var(--s-4) * 69);
$s-280: calc(var(--s-4) * 70);
diff --git a/frontend/resources/styles/main/partials/colorpicker.scss b/frontend/resources/styles/main/partials/colorpicker.scss
index 71b049d8cf..e4559e9cb2 100644
--- a/frontend/resources/styles/main/partials/colorpicker.scss
+++ b/frontend/resources/styles/main/partials/colorpicker.scss
@@ -342,6 +342,9 @@
margin-right: -8px;
max-height: 5.5rem;
overflow: auto;
+ div {
+ grid-area: unset;
+ }
}
.selected-colors::after {
diff --git a/frontend/src/app/main/ui/components/color_bullet_new.cljs b/frontend/src/app/main/ui/components/color_bullet_new.cljs
index f396af1896..33cf9ba9f2 100644
--- a/frontend/src/app/main/ui/components/color_bullet_new.cljs
+++ b/frontend/src/app/main/ui/components/color_bullet_new.cljs
@@ -13,7 +13,7 @@
(mf/defc color-bullet
{::mf/wrap [mf/memo]
::mf/wrap-props false}
- [{:keys [color on-click mini?]}]
+ [{:keys [color on-click mini? area]}]
(let [on-click (mf/use-fn
(mf/deps color on-click)
(fn [event]
@@ -34,7 +34,9 @@
:is-library-color (some? id)
:is-not-library-color (nil? id)
:is-gradient (some? gradient)
- :is-transparent (and opacity (> 1 opacity)))
+ :is-transparent (and opacity (> 1 opacity))
+ :grid-area area)
+
:on-click on-click}
(if (some? gradient)
diff --git a/frontend/src/app/main/ui/components/color_bullet_new.scss b/frontend/src/app/main/ui/components/color_bullet_new.scss
index ea0276cb0d..763c90b557 100644
--- a/frontend/src/app/main/ui/components/color_bullet_new.scss
+++ b/frontend/src/app/main/ui/components/color_bullet_new.scss
@@ -12,9 +12,13 @@
flex-direction: row;
width: var(--bullet-size, $s-24);
height: var(--bullet-size, $s-24);
- margin-top: $s-4;
+ min-width: var(--bullet-size, $s-24);
+ min-height: var(--bullet-size, $s-24);
border: $s-2 solid var(--color-bullet-border-color);
border-radius: $br-circle;
+ &.grid-area {
+ grid-area: color;
+ }
&.mini {
width: var(--bullet-size, $s-16);
height: var(--bullet-size, $s-16);
diff --git a/frontend/src/app/main/ui/components/color_input.cljs b/frontend/src/app/main/ui/components/color_input.cljs
index f8d193b5f6..45509a3410 100644
--- a/frontend/src/app/main/ui/components/color_input.cljs
+++ b/frontend/src/app/main/ui/components/color_input.cljs
@@ -32,6 +32,7 @@
on-blur (obj/get props "onBlur")
on-focus (obj/get props "onFocus")
select-on-focus? (d/nilv (unchecked-get props "selectOnFocus") true)
+ class (d/nilv (unchecked-get props "className") "color-input")
;; We need a ref pointing to the input dom element, but the user
;; of this component may provide one (that is forwarded here).
@@ -132,6 +133,7 @@
(obj/unset! "selectOnFocus")
(obj/set! "value" mf/undefined)
(obj/set! "onChange" mf/undefined)
+ (obj/set! "className" class)
(obj/set! "type" "text")
(obj/set! "ref" ref)
;; (obj/set! "list" list-id)
diff --git a/frontend/src/app/main/ui/components/context_menu_a11y.scss b/frontend/src/app/main/ui/components/context_menu_a11y.scss
index 7dfe7c3f4c..f19a4d355b 100644
--- a/frontend/src/app/main/ui/components/context_menu_a11y.scss
+++ b/frontend/src/app/main/ui/components/context_menu_a11y.scss
@@ -82,12 +82,12 @@
&:hover .context-menu-action {
background-color: var(--menu-background-color-hover);
text-decoration: none;
- color: var(--menu-foreground-color-hover);
+ color: var(--menu-foreground-color);
&.submenu .submenu-icon svg {
- stroke: var(--menu-foreground-color-hover);
+ stroke: var(--menu-foreground-color);
}
&.submenu-back .submenu-icon-back svg {
- stroke: var(--menu-foreground-color-hover);
+ stroke: var(--menu-foreground-color);
}
}
&:focus {
diff --git a/frontend/src/app/main/ui/components/editable_select.cljs b/frontend/src/app/main/ui/components/editable_select.cljs
index 1ae7ee75ba..bd9931d28f 100644
--- a/frontend/src/app/main/ui/components/editable_select.cljs
+++ b/frontend/src/app/main/ui/components/editable_select.cljs
@@ -5,12 +5,15 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.components.editable-select
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
+ [app.common.data.macros :as dm]
[app.common.math :as mth]
[app.common.uuid :as uuid]
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.components.numeric-input :refer [numeric-input*]]
+ [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.keyboard :as kbd]
@@ -18,13 +21,21 @@
[rumext.v2 :as mf]))
(mf/defc editable-select
- [{:keys [value type options class on-change placeholder on-blur] :as params}]
- (let [state (mf/use-state {:id (uuid/next)
- :is-open? false
- :current-value value
- :top nil
- :left nil
- :bottom nil})
+ [{:keys [value type options class on-change placeholder on-blur input-class] :as params}]
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ state* (mf/use-state {:id (uuid/next)
+ :is-open? false
+ :current-value value
+ :top nil
+ :left nil
+ :bottom nil})
+ state (deref state*)
+ is-open? (:is-open? state)
+ current-value (:current-value state)
+ top-value (:top state)
+ left-value (:left state)
+ bottom-value (:bottom state)
+ element-id (:id state)
min-val (get params :min)
max-val (get params :max)
@@ -35,16 +46,28 @@
open-dropdown
(fn [event]
(dom/stop-propagation event)
- (swap! state assoc :is-open? true))
+ (swap! state* assoc :is-open? true))
+
+ toggle-dropdown
+ (mf/use-fn
+ (mf/deps state)
+ #(swap! state* update :is-open? not))
+
close-dropdown
(fn [event]
(dom/stop-propagation event)
- (swap! state assoc :is-open? false))
- select-item (fn [value]
- (fn [_]
- (swap! state assoc :current-value value)
- (when on-change (on-change value))
- (when on-blur (on-blur))))
+ (swap! state* assoc :is-open? false))
+
+ select-item
+ (mf/use-fn
+ (mf/deps on-change on-blur)
+ (fn [event]
+ (let [value (-> (dom/get-current-target event)
+ (dom/get-data "value")
+ (d/read-string))]
+ (swap! state* assoc :current-value value)
+ (when on-change (on-change value))
+ (when on-blur (on-blur)))))
as-key-value (fn [item] (if (map? item) [(:value item) (:label item)] [item item]))
labels-map (into {} (map as-key-value) options)
@@ -52,7 +75,7 @@
set-value
(fn [value]
- (swap! state assoc :current-value value)
+ (swap! state* assoc :current-value value)
(when on-change (on-change value)))
;; TODO: why this method supposes that all editable select
@@ -75,14 +98,14 @@
{:keys [left top height]} bounds
bottom (when (< (- window-height top) 300) (- window-height top))
top (when (>= (- window-height top) 300) (+ top height))]
- (swap! state
+ (swap! state*
assoc
:left left
:top top
:bottom bottom))))))
handle-key-down
- (mf/use-callback
+ (mf/use-fn
(mf/deps set-value)
(fn [event]
(when (= type "number")
@@ -113,12 +136,12 @@
(set-value new-value)))))))
handle-focus
- (mf/use-callback
+ (mf/use-fn
(fn []
(mf/set-ref-val! emit-blur? false)))
handle-blur
- (mf/use-callback
+ (mf/use-fn
(fn []
(mf/set-ref-val! emit-blur? true)
(timers/schedule
@@ -127,56 +150,101 @@
(when (and on-blur (mf/ref-val emit-blur?)) (on-blur))))))]
(mf/use-effect
- (mf/deps value (:current-value @state))
- #(when (not= (str value) (:current-value @state))
- (reset! state {:current-value value})))
+ (mf/deps value current-value)
+ #(when (not= (str value) current-value)
+ (reset! state* {:current-value value})))
- (mf/with-effect [(:is-open? @state)]
+ (mf/with-effect [is-open?]
(let [wrapper-node (mf/ref-val font-size-wrapper-ref)
node (dom/get-element-by-class "checked-element is-selected" wrapper-node)
nodes (dom/get-elements-by-class "checked-element-value" wrapper-node)
closest (fn [a b] (first (sort-by #(mth/abs (- % b)) a)))
closest-value (str (closest options value))]
- (when (:is-open? @state)
+ (when is-open?
(if (some? node)
(dom/scroll-into-view-if-needed! node)
(some->> nodes
(d/seek #(= closest-value (dom/get-inner-text %)))
(dom/scroll-into-view-if-needed!)))))
- (mf/set-ref-val! emit-blur? (not (:is-open? @state))))
+ (mf/set-ref-val! emit-blur? (not is-open?)))
- [:div.editable-select {:class class
- :ref on-node-load}
- (if (= type "number")
- [:> numeric-input* {:value (or (some-> @state :current-value value->label) "")
- :on-change set-value
- :on-focus handle-focus
- :on-blur handle-blur
- :placeholder placeholder}]
- [:input.input-text {:value (or (some-> @state :current-value value->label) "")
- :on-change handle-change-input
- :on-key-down handle-key-down
- :on-focus handle-focus
- :on-blur handle-blur
- :placeholder placeholder
- :type type}])
- [:span.dropdown-button {:on-click open-dropdown} i/arrow-down]
- [:& dropdown {:show (get @state :is-open? false)
- :on-close close-dropdown}
- [:ul.custom-select-dropdown {:style {:position "fixed"
- :top (:top @state)
- :left (:left @state)
- :bottom (:bottom @state)
- :ref font-size-wrapper-ref}}
- (for [[index item] (map-indexed vector options)]
- (if (= :separator item)
- [:hr {:key (str (:id @state) "-" index)}]
- (let [[value label] (as-key-value item)]
- [:li.checked-element
- {:key (str (:id @state) "-" index)
- :class (when (= (str value) (-> @state :current-value)) "is-selected")
- :on-click (select-item value)}
- [:span.check-icon i/tick]
- [:span.checked-element-value label]])))]]]))
+ (if new-css-system
+ [:div {:class (dm/str class " " (stl/css :editable-select))
+ :ref on-node-load}
+ (if (= type "number")
+ [:> numeric-input* {:value (or (some-> current-value value->label) "")
+ :className input-class
+ :on-change set-value
+ :on-focus handle-focus
+ :on-blur handle-blur
+ :placeholder placeholder}]
+ [:input {:value (or (some-> current-value value->label) "")
+ :class input-class
+ :on-change handle-change-input
+ :on-key-down handle-key-down
+ :on-focus handle-focus
+ :on-blur handle-blur
+ :placeholder placeholder
+ :type type}])
+
+ [:span {:class (stl/css :dropdown-button)
+ :on-click toggle-dropdown}
+ i/arrow-refactor]
+
+ [:& dropdown {:show (or is-open? false)
+ :on-close close-dropdown}
+ [:ul {:class (stl/css :custom-select-dropdown)
+ :ref font-size-wrapper-ref}
+ (for [[index item] (map-indexed vector options)]
+ (if (= :separator item)
+ [:li {:class (stl/css :separator)
+ :key (dm/str element-id "-" index)}]
+ (let [[value label] (as-key-value item)]
+ [:li
+ {:key (str element-id "-" index)
+ :class (stl/css-case :dropdown-element true
+ :is-selected (= value current-value))
+ :data-value value
+ :on-click select-item}
+ [:span {:class (stl/css :label)} label]
+ [:span {:class (stl/css :check-icon)}
+ i/tick-refactor]])))]]]
+
+
+ [:div.editable-select {:class class
+ :ref on-node-load}
+ (if (= type "number")
+ [:> numeric-input* {:value (or (some-> current-value value->label) "")
+ :on-change set-value
+ :on-focus handle-focus
+ :on-blur handle-blur
+ :placeholder placeholder}]
+ [:input.input-text {:value (or (some-> current-value value->label) "")
+ :on-change handle-change-input
+ :on-key-down handle-key-down
+ :on-focus handle-focus
+ :on-blur handle-blur
+ :placeholder placeholder
+ :type type}])
+ [:span.dropdown-button {:on-click open-dropdown} i/arrow-down]
+
+ [:& dropdown {:show (or is-open? false)
+ :on-close close-dropdown}
+ [:ul.custom-select-dropdown {:style {:position "fixed"
+ :top top-value
+ :left left-value
+ :bottom bottom-value}
+ :ref font-size-wrapper-ref}
+ (for [[index item] (map-indexed vector options)]
+ (if (= :separator item)
+ [:hr {:key (str element-id "-" index)}]
+ (let [[value label] (as-key-value item)]
+ [:li.checked-element
+ {:key (str element-id "-" index)
+ :class (when (= (str value) current-value) "is-selected")
+ :data-value value
+ :on-click select-item}
+ [:span.check-icon i/tick]
+ [:span.checked-element-value label]])))]]])))
diff --git a/frontend/src/app/main/ui/components/editable_select.scss b/frontend/src/app/main/ui/components/editable_select.scss
new file mode 100644
index 0000000000..06e3981e9f
--- /dev/null
+++ b/frontend/src/app/main/ui/components/editable_select.scss
@@ -0,0 +1,69 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.editable-select {
+ @extend .asset-element;
+ margin: 0;
+ padding: 0;
+ border: $s-1 solid var(--input-background-color);
+ position: relative;
+ display: flex;
+ height: $s-32;
+ width: 100%;
+ padding: $s-8;
+ border-radius: $br-8;
+ cursor: pointer;
+ .dropdown-button {
+ @include flexCenter;
+ svg {
+ @extend .button-icon;
+ transform: rotate(90deg);
+ stroke: var(--icon-foreground);
+ }
+ }
+
+ .custom-select-dropdown {
+ @extend .dropdown-wrapper;
+ max-height: $s-320;
+ .separator {
+ margin: 0;
+ height: $s-12;
+ }
+ .dropdown-element {
+ @extend .dropdown-element-base;
+ color: var(--menu-foreground-color);
+ .label {
+ flex-grow: 1;
+ width: 100%;
+ }
+
+ .check-icon {
+ @include flexCenter;
+ svg {
+ @extend .button-icon-small;
+ visibility: hidden;
+ stroke: var(--icon-foreground);
+ }
+ }
+
+ &.is-selected {
+ .check-icon svg {
+ stroke: var(--menu-foreground-color);
+ visibility: visible;
+ }
+ }
+ &:hover {
+ background-color: var(--menu-background-color-hover);
+ color: var(--menu-foreground-color-hover);
+ .check-icon svg {
+ stroke: var(--menu-foreground-color-hover);
+ }
+ }
+ }
+ }
+}
diff --git a/frontend/src/app/main/ui/components/radio_buttons.cljs b/frontend/src/app/main/ui/components/radio_buttons.cljs
index 52c384d9d8..bbad622154 100644
--- a/frontend/src/app/main/ui/components/radio_buttons.cljs
+++ b/frontend/src/app/main/ui/components/radio_buttons.cljs
@@ -66,6 +66,7 @@
icon (unchecked-get props "icon")
id (unchecked-get props "id")
value (unchecked-get props "value")
+ title (unchecked-get props "title")
disabled (unchecked-get props "disabled")
unique-key (unchecked-get props "unique-key")
icon-class (unchecked-get props "icon-class")
@@ -79,6 +80,7 @@
[:label {:for id
:key unique-key
+ :title title
:class (stl/css-case
:radio-icon true
:disabled disabled
@@ -142,3 +144,6 @@
[:div {:class (dm/str class " " (stl/css :radio-btn-wrapper))
:style {:width width}}
children]]))
+
+
+
diff --git a/frontend/src/app/main/ui/components/select.cljs b/frontend/src/app/main/ui/components/select.cljs
index 7c7fb8ff08..04a963d3b1 100644
--- a/frontend/src/app/main/ui/components/select.cljs
+++ b/frontend/src/app/main/ui/components/select.cljs
@@ -5,7 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.components.select
- (:require-macros [app.main.style :refer [css]])
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
@@ -23,7 +23,7 @@
[item item]))
(mf/defc select
- [{:keys [default-value options class is-open? on-change on-pointer-enter-option on-pointer-leave-option]}]
+ [{:keys [default-value options class is-open? on-change on-pointer-enter-option on-pointer-leave-option disabled]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
label-index (mf/with-memo [options]
(into {} (map as-key-value) options))
@@ -39,7 +39,13 @@
current-label (get label-index current-value)
is-open? (:is-open? state)
- open-dropdown (mf/use-fn #(swap! state* assoc :is-open? true))
+ open-dropdown
+ (mf/use-fn
+ (mf/deps disabled)
+ (fn[]
+ (when-not disabled
+ (swap! state* assoc :is-open? true))))
+
close-dropdown (mf/use-fn #(swap! state* assoc :is-open? false))
select-item
@@ -78,27 +84,29 @@
(swap! state* assoc :current-value default-value))
(if new-css-system
[:div {:on-click open-dropdown
- :class (dom/classnames (css class) true
- (css :custom-select) true)}
- [:span {:class (css :current-label)} current-label]
- [:span {:class (css :dropdown-button)} i/arrow-refactor]
+ :class (dm/str class " " (stl/css-case :custom-select true
+ :disabled disabled))}
+ [:span {:class (stl/css :current-label)} current-label]
+ [:span {:class (stl/css :dropdown-button)} i/arrow-refactor]
[:& dropdown {:show is-open? :on-close close-dropdown}
- [:ul {:class (css :custom-select-dropdown)}
+ [:ul {:class (stl/css :custom-select-dropdown)}
(for [[index item] (d/enumerate options)]
(if (= :separator item)
- [:hr {:key (dm/str current-id "-" index)}]
+ [:li {:class (dom/classnames (stl/css :separator) true)
+ :key (dm/str current-id "-" index)}]
(let [[value label] (as-key-value item)]
[:li
{:key (dm/str current-id "-" index)
:class (dom/classnames
- (css :checked-element) true
- (css :is-selected) (= value current-value))
+ (stl/css :checked-element) true
+ (stl/css :is-selected) (= value current-value))
:data-value (pr-str value)
:on-pointer-enter highlight-item
:on-pointer-leave unhighlight-item
:on-click select-item}
- [:span {:class (css :label)} label]
- [:span {:class (css :check-icon)} i/tick-refactor]])))]]]
+ [:span {:class (stl/css :label)} label]
+ [:span {:class (stl/css :check-icon)} i/tick-refactor]])))]]]
+
[:div.custom-select {:on-click open-dropdown :class class}
[:span current-label]
diff --git a/frontend/src/app/main/ui/components/select.scss b/frontend/src/app/main/ui/components/select.scss
index 4950456275..7fb9fcd37b 100644
--- a/frontend/src/app/main/ui/components/select.scss
+++ b/frontend/src/app/main/ui/components/select.scss
@@ -7,11 +7,18 @@
@import "refactor/common-refactor.scss";
.custom-select {
+ @include titleTipography;
position: relative;
display: flex;
+ align-items: center;
+ height: $s-32;
width: 100%;
+ margin: 0;
padding: $s-8;
border-radius: $br-8;
+ background-color: var(--menu-background-color);
+ border: $s-1 solid var(--menu-background-color);
+ color: var(--menu-foreground-color);
cursor: pointer;
.current-label {
width: 100%;
@@ -26,26 +33,15 @@
}
}
.custom-select-dropdown {
- @include menuShadow;
- position: absolute;
- top: $s-32;
- left: 0;
- width: 100%;
- padding: $s-2;
- margin: 0;
- margin-top: $s-4;
- border-radius: $br-8;
- z-index: $z-index-3;
- overflow-y: auto;
- background-color: var(--menu-background-color);
+ @extend .dropdown-wrapper;
+ .separator {
+ margin: 0;
+ height: $s-12;
+ }
}
.checked-element {
- display: flex;
- align-items: center;
- height: $s-32;
- padding: 0 $s-8;
- border-radius: $br-6;
- color: var(--menu-foreground-color);
+ @extend .dropdown-element-base;
+
.label {
flex-grow: 1;
width: 100%;
@@ -61,26 +57,35 @@
}
&.is-selected {
+ color: var(--menu-foreground-color);
.check-icon svg {
stroke: var(--menu-foreground-color);
visibility: visible;
}
}
- &:hover {
- background-color: var(--menu-background-color-hover);
- color: var(--menu-foreground-color-hover);
- .check-icon svg {
- stroke: var(--menu-foreground-color-hover);
- }
- }
}
&:hover {
+ background-color: var(--menu-background-color-hover);
+ border: $s-1 solid var(--menu-background-color-hover);
.dropdown-button {
- color: var(--menu-foreground-color-hover);
svg {
stroke: var(--menu-foreground-color-hover);
}
}
}
+ &:focus {
+ background-color: var(--menu-background-color-focus);
+ border: $s-1 solid var(--menu-border-color-focus);
+ }
+ &.disabled {
+ background-color: var(--menu-background-color-disabled);
+ color: var(--menu-foreground-color-disabled);
+ border: $s-1 solid var(--menu-border-color-disabled);
+ pointer-events: none;
+ cursor: default;
+ .dropdown-button svg {
+ stroke: var(--menu-foreground-color-disabled);
+ }
+ }
}
diff --git a/frontend/src/app/main/ui/components/tab_container.cljs b/frontend/src/app/main/ui/components/tab_container.cljs
index 2b11ec5f15..9b52965a56 100644
--- a/frontend/src/app/main/ui/components/tab_container.cljs
+++ b/frontend/src/app/main/ui/components/tab_container.cljs
@@ -5,9 +5,10 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.components.tab-container
- (:require-macros [app.main.style :refer [css]])
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
+ [app.common.data.macros :as dm]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
@@ -20,9 +21,7 @@
[props]
(let [children (unchecked-get props "children")
new-css-system (mf/use-ctx ctx/new-css-system)]
- [:div {:class (if new-css-system
- (dom/classnames (css :tab-element) true)
- (dom/classnames :tab-element true))}
+ [:div {:class (stl/css new-css-system :tab-element)}
children]))
(mf/defc tab-container
@@ -35,7 +34,7 @@
on-change (unchecked-get props "on-change-tab")
collapsable? (unchecked-get props "collapsable?")
handle-collapse (unchecked-get props "handle-collapse")
- klass (unchecked-get props "klass")
+ class (unchecked-get props "class")
content-class (unchecked-get props "content-class")
state (mf/use-state #(or selected (-> children first .-props .-id)))
@@ -45,31 +44,32 @@
(mf/use-fn
(mf/deps on-change)
(fn [event]
- (let [id (d/read-string (.. event -target -dataset -id))]
+ (let [id (-> event
+ (dom/get-current-target)
+ (dom/get-data "id")
+ (keyword))]
(reset! state id)
(when (fn? on-change) (on-change id)))))]
- [:div {:class (dom/classnames (css :tab-container) true)}
- [:div {:class (dom/classnames (css :tab-container-tabs) true
- klass true)}
+ [:div {:class (stl/css :tab-container)}
+ [:div {:class (dm/str class " "(stl/css :tab-container-tabs))}
(when collapsable?
[:button
{:on-click handle-collapse
- :class (dom/classnames (css :collapse-sidebar) true)
+ :class (stl/css :collapse-sidebar)
:aria-label (tr "workspace.sidebar.collapse")}
i/arrow-refactor])
- [:div {:class (dom/classnames (css :tab-container-tab-wrapper) true)}
+ [:div {:class (stl/css :tab-container-tab-wrapper)}
(for [tab children]
(let [props (.-props tab)
id (.-id props)
title (.-title props)]
[:div
{:key (str/concat "tab-" (d/name id))
- :data-id (pr-str id)
+ :data-id (d/name id)
:on-click select-fn
- :class (dom/classnames (css :tab-container-tab-title) true
- (css :current) (= selected id))}
+ :class (stl/css-case :tab-container-tab-title true
+ :current (= selected id))}
title]))]]
- [:div {:class (dom/classnames (css :tab-container-content) true
- content-class (some? content-class))}
+ [:div {:class (dm/str content-class " " (stl/css :tab-container-content ))}
(d/seek #(= selected (-> % .-props .-id)) children)]]))
diff --git a/frontend/src/app/main/ui/components/tab_container.scss b/frontend/src/app/main/ui/components/tab_container.scss
index 56c7dac401..00be5342eb 100644
--- a/frontend/src/app/main/ui/components/tab_container.scss
+++ b/frontend/src/app/main/ui/components/tab_container.scss
@@ -48,14 +48,24 @@
background-color: transparent;
color: var(--tab-foreground-color);
white-space: nowrap;
+ svg {
+ @extend .button-icon;
+ stroke: var(--tab-foreground-color);
+ }
&.current,
&.current:hover {
background: var(--tab-background-color-selected);
color: var(--tab-foreground-color-selected);
+ svg {
+ stroke: var(--tab-foreground-color-selected);
+ }
}
&:hover {
color: var(--tab-foreground-color-hover);
+ svg {
+ stroke: var(--tab-foreground-color-hover);
+ }
}
}
}
diff --git a/frontend/src/app/main/ui/debug/components_preview.cljs b/frontend/src/app/main/ui/debug/components_preview.cljs
index 3ba458132f..98d6fee926 100644
--- a/frontend/src/app/main/ui/debug/components_preview.cljs
+++ b/frontend/src/app/main/ui/debug/components_preview.cljs
@@ -95,7 +95,7 @@
(d/name color)]))]]
[:div {:class (stl/css :components-row)}
- [:h2 {:class(stl/css :title)} "Components"]
+ [:h2 {:class (stl/css :title)} "Components"]
[:div {:class (stl/css :components-wrapper)}
[:div {:class (stl/css :components-group)}
[:h3 "Titles"]
@@ -167,7 +167,7 @@
[:& search-bar {:on-change update-search
:value input-value
:placeholder "Test value"}
- [:button {:class (stl/css :test-button)
+ [:button {:class (stl/css :button-secondary)
:on-click on-btn-click}
"X"]]]]
@@ -246,4 +246,25 @@
[:& component-wrapper
{:title "Button tertiary with icon"}
[:button {:class (stl/css :button-tertiary)}
- i/add-refactor]]]]]]))
+ i/add-refactor]]]
+
+ [:div {:class (stl/css :components-group)}
+ [:h3 "Inputs"]
+ [:& component-wrapper
+ {:title "Only input"}
+ [:div {:class (stl/css :input-wrapper)}
+ [:input {:class (stl/css :basic-input)
+ :placeholder "----"}]]]
+ [:& component-wrapper
+ {:title "Input with label"}
+ [:div {:class (stl/css :input-wrapper)}
+ [:span {:class (stl/css :input-label)} "label"]
+ [:input {:class (stl/css :basic-input)
+ :placeholder "----"}]]]
+ [:& component-wrapper
+ {:title "Input with icon"}
+ [:div {:class (stl/css :input-wrapper)}
+ [:span {:class (stl/css :input-label)}
+ i/add-refactor]
+ [:input {:class (stl/css :basic-input)
+ :placeholder "----"}]]]]]]]))
diff --git a/frontend/src/app/main/ui/debug/components_preview.scss b/frontend/src/app/main/ui/debug/components_preview.scss
index d780a40901..a78e2e2dc8 100644
--- a/frontend/src/app/main/ui/debug/components_preview.scss
+++ b/frontend/src/app/main/ui/debug/components_preview.scss
@@ -84,11 +84,10 @@
display: flex;
flex-wrap: wrap;
gap: $s-20;
- .component-group {
+ .components-group {
@include flexCenter;
justify-content: flex-start;
flex-direction: column;
- // width: $s-256;
border-radius: $s-8;
h3 {
@include titleTipography;
@@ -129,5 +128,8 @@
@extend .button-icon;
}
}
+ .input-wrapper {
+ @extend .input-element;
+ }
}
}
diff --git a/frontend/src/app/main/ui/icons.cljs b/frontend/src/app/main/ui/icons.cljs
index 35a7dfca26..5d769b44eb 100644
--- a/frontend/src/app/main/ui/icons.cljs
+++ b/frontend/src/app/main/ui/icons.cljs
@@ -276,7 +276,6 @@
(def align-content-row-between-refactor (icon-xref :align-content-row-between-refactor))
(def align-content-row-evenly-refactor (icon-xref :align-content-row-evenly-refactor))
(def align-content-row-start-refactor (icon-xref :align-content-row-start-refactor))
-
(def align-horizontal-center-refactor (icon-xref :align-horizontal-center-refactor))
(def align-vertical-center-refactor (icon-xref :align-vertical-center-refactor))
(def align-items-row-center-refactor (icon-xref :align-items-row-center-refactor))
@@ -345,6 +344,7 @@
(def gap-vertical-refactor (icon-xref :gap-vertical-refactor))
(def hide-refactor (icon-xref :hide-refactor))
(def history-refactor (icon-xref :history-refactor))
+(def hsva-refactor (icon-xref :hsva-refactor))
(def hug-content-refactor (icon-xref :hug-content-refactor))
(def img-refactor (icon-xref :img-refactor))
(def icon-refactor (icon-xref :icon-refactor))
@@ -384,9 +384,12 @@
(def padding-extended-refactor (icon-xref :padding-extended-refactor))
(def path-refactor (icon-xref :path-refactor))
(def pentool-refactor (icon-xref :pentool-refactor))
+(def picker-refactor (icon-xref :picker-refactor))
(def play-refactor (icon-xref :play-refactor))
(def rectangle-refactor (icon-xref :rectangle-refactor))
(def remove-refactor (icon-xref :remove-refactor))
+(def rgba-refactor (icon-xref :rgba-refactor))
+(def rgba-complementary-refactor (icon-xref :rgba-complementary-refactor))
(def rotation-refactor (icon-xref :rotation-refactor))
(def row-reverse-refactor (icon-xref :row-reverse-refactor))
(def search-refactor (icon-xref :search-refactor))
@@ -400,12 +403,13 @@
(def stroke-size-refactor (icon-xref :stroke-size-refactor))
(def svg-refactor (icon-xref :svg-refactor))
(def swatches-refactor (icon-xref :swatches-refactor))
+(def switch-refactor (icon-xref :switch-refactor))
(def text-align-center-refactor (icon-xref :text-align-center-refactor))
(def text-align-left-refactor (icon-xref :text-align-left-refactor))
(def text-align-right-refactor (icon-xref :text-align-right-refactor))
(def text-auto-height-refactor (icon-xref :text-auto-height-refactor))
(def text-auto-width-refactor (icon-xref :text-auto-width-refactor))
-(def text-fixed-refactor (icon-xref :textfixed--refactor))
+(def text-fixed-refactor (icon-xref :text-fixed-refactor))
(def text-justify-refactor (icon-xref :text-justify-refactor))
(def text-letterspacing-refactor (icon-xref :text-letterspacing-refactor))
(def text-lineheight-refactor (icon-xref :text-lineheight-refactor))
@@ -420,7 +424,7 @@
(def text-mixed-refactor (icon-xref :text-mixed-refactor))
(def text-stroked-refactor (icon-xref :text-stroked-refactor))
(def text-top-refactor (icon-xref :text-top-refactor))
-(def text-underlined-refactor (icon-xref :text-undelined-refactor))
+(def text-underlined-refactor (icon-xref :text-underlined-refactor))
(def text-uppercase-refactor (icon-xref :text-uppercase-refactor))
(def tick-refactor (icon-xref :tick-refactor))
(def unlock-refactor (icon-xref :unlock-refactor))
diff --git a/frontend/src/app/main/ui/measurements.cljs b/frontend/src/app/main/ui/measurements.cljs
index a8f6b91c51..5a47afa4ba 100644
--- a/frontend/src/app/main/ui/measurements.cljs
+++ b/frontend/src/app/main/ui/measurements.cljs
@@ -825,21 +825,20 @@
(map create-cgdd)))]
[:g.gaps {:pointer-events "visible"}
- [:*
- (for [[index display-item] (d/enumerate (concat display-blocks display-children))]
- (let [gap-type (:gap-type display-item)]
- [:& gap-display {:key (str frame-id index)
- :frame-id frame-id
- :zoom zoom
- :gap-type gap-type
- :gap gap
- :on-pointer-enter (partial on-pointer-enter gap-type (get gap gap-type))
- :on-pointer-leave on-pointer-leave
- :rect-data display-item
- :hover? (= @hover gap-type)
- :selected? (= gap-selected gap-type)
- :mouse-pos mouse-pos
- :hover-value hover-value}]))]
+ (for [[index display-item] (d/enumerate (concat display-blocks display-children))]
+ (let [gap-type (:gap-type display-item)]
+ [:& gap-display {:key (str frame-id index)
+ :frame-id frame-id
+ :zoom zoom
+ :gap-type gap-type
+ :gap gap
+ :on-pointer-enter (partial on-pointer-enter gap-type (get gap gap-type))
+ :on-pointer-leave on-pointer-leave
+ :rect-data display-item
+ :hover? (= @hover gap-type)
+ :selected? (= gap-selected gap-type)
+ :mouse-pos mouse-pos
+ :hover-value hover-value}]))
(when @hover
[:& flex-display-pill {:height pill-height
diff --git a/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.scss b/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.scss
index 046b76b6cc..f43f09038b 100644
--- a/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.scss
+++ b/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.scss
@@ -9,8 +9,8 @@
.palette-menu {
position: absolute;
left: auto;
- max-width: $s-480;
bottom: $s-0;
+ max-width: $s-480;
padding: $s-4;
margin: 0 0 $s-4 0;
z-index: $z-index-3;
diff --git a/frontend/src/app/main/ui/workspace/colorpicker.cljs b/frontend/src/app/main/ui/workspace/colorpicker.cljs
index 9b912afd5a..28884c3634 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker.cljs
@@ -5,6 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.colorpicker
+ (:require-macros [app.main.style :as stl])
(:require
[app.main.data.modal :as modal]
[app.main.data.workspace.colors :as dc]
@@ -12,6 +13,8 @@
[app.main.data.workspace.undo :as dwu]
[app.main.refs :as refs]
[app.main.store :as st]
+ [app.main.ui.components.tab-container :refer [tab-container tab-element]]
+ [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.workspace.colorpicker.color-inputs :refer [color-inputs]]
[app.main.ui.workspace.colorpicker.gradients :refer [gradients]]
@@ -44,7 +47,8 @@
(mf/defc colorpicker
[{:keys [data disable-gradient disable-opacity on-change on-accept]}]
- (let [state (mf/deref refs/colorpicker)
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ state (mf/deref refs/colorpicker)
node-ref (mf/use-ref)
;; TODO: I think we need to put all this picking state under
@@ -58,15 +62,15 @@
active-tab (mf/use-state (dc/get-active-color-tab))
drag? (mf/use-state false)
-
+
set-tab!
(mf/use-fn
- (fn [event]
- (let [tab (-> (dom/get-current-target event)
- (dom/get-data "tab")
- (keyword))]
- (reset! active-tab tab)
- (dc/set-active-color-tab! tab))))
+ (fn [event]
+ (let [tab (-> (dom/get-current-target event)
+ (dom/get-data "tab")
+ (keyword))]
+ (reset! active-tab tab)
+ (dc/set-active-color-tab! tab))))
handle-change-color
(mf/use-fn
@@ -86,14 +90,17 @@
(fn []
(if picking-color?
(do (modal/disallow-click-outside!)
- (st/emit! (dc/stop-picker)))
+ (st/emit! (dc/stop-picker)))
(do (modal/allow-click-outside!)
- (st/emit! (dc/start-picker))))))
+ (st/emit! (dc/start-picker))))))
handle-change-stop
(mf/use-fn
- (fn [offset]
- (st/emit! (dc/select-colorpicker-gradient-stop offset))))
+ (fn [event]
+ (let [offset (-> (dom/get-current-target event)
+ (dom/get-data "value")
+ (int))]
+ (st/emit! (dc/select-colorpicker-gradient-stop offset)))))
on-select-library-color
(mf/use-fn
@@ -128,7 +135,7 @@
;; Click on a solid color -> This color is applied to the selected offset
;; Click on a color with transparency -> The same to solid color will happend
;; Click on any kind of gradient -> The color changes completly to new gradient
-
+
;; If we have a non gradient color the new color is applied without any change
(if (or (= :radial-gradient type-origin) (= :linear-gradient type-origin))
(if is-gradient?
@@ -150,15 +157,24 @@
on-start-drag
(mf/use-fn
+ (mf/deps drag? node-ref)
(fn []
(reset! drag? true)
(st/emit! (dwu/start-undo-transaction (mf/ref-val node-ref)))))
on-finish-drag
(mf/use-fn
+ (mf/deps drag? node-ref)
(fn []
(reset! drag? false)
- (st/emit! (dwu/commit-undo-transaction (mf/ref-val node-ref)))))]
+ (st/emit! (dwu/commit-undo-transaction (mf/ref-val node-ref)))))
+
+ on-color-accept
+ (mf/use-fn
+ (mf/deps state)
+ (fn []
+ (on-accept (dc/get-color-from-colorpicker-state state))
+ (modal/hide!)))]
;; Initialize colorpicker state
(mf/with-effect []
@@ -199,110 +215,200 @@
:h h :s s :v v
:alpha (/ alpha 255)}))))
- [:div.colorpicker {:ref node-ref
- :style {:touch-action "none"}}
- [:div.colorpicker-content
- [:div.top-actions
- [:button.picker-btn
- {:class (when picking-color? "active")
- :on-click handle-click-picker}
- i/picker]
+ (if new-css-system
+ [:div {:class (stl/css :colorpicker)
+ :ref node-ref
+ :style {:touch-action "none"}}
+ [:div {:class (stl/css :top-actions)}
+ [:button {:class (stl/css-case :picker-btn true
+ :selected picking-color?)
+ :on-click handle-click-picker}
+ i/picker-refactor]
+ (when (not disable-gradient)
+ [:div {:class (stl/css :gradient-buttons)}
+ [:button
+ {:on-click on-activate-linear-gradient
+ :class (stl/css-case :gradient-btn true
+ :linear-gradient-btn true
+ :selected (= :linear-gradient (:type state)))}]
- (when (not disable-gradient)
- [:div.gradients-buttons
- [:button.gradient.linear-gradient
- {:on-click on-activate-linear-gradient
- :class (when (= :linear-gradient (:type state)) "active")}]
+ [:button
+ {:on-click on-activate-radial-gradient
+ :class (stl/css-case :gradient-btn true
+ :radial-gradient-btn true
+ :selected (= :radial-gradient (:type state)))}]])]
- [:button.gradient.radial-gradient
- {:on-click on-activate-radial-gradient
- :class (when (= :radial-gradient (:type state)) "active")}]])]
+ (when (or (= (:type state) :linear-gradient)
+ (= (:type state) :radial-gradient))
+ [:& gradients
+ {:stops (:stops state)
+ :editing-stop (:editing-stop state)
+ :on-select-stop handle-change-stop}])
+ [:div {:class (stl/css :colorpicker-tabs)}
+ [:& tab-container
+ {:on-change-tab set-tab!
+ :selected @active-tab
+ :collapsable? false}
- (when (or (= (:type state) :linear-gradient)
- (= (:type state) :radial-gradient))
- [:& gradients
- {:stops (:stops state)
- :editing-stop (:editing-stop state)
- :on-select-stop handle-change-stop}])
+ [:& tab-element {:id :ramp :title i/rgba-refactor}
+ (if picking-color?
+ [:div {:class (stl/css :picker-detail-wrapper)}
+ [:div {:class (stl/css :center-circle)}]
+ [:canvas#picker-detail {:width 256 :height 140}]]
+ [:& ramp-selector
+ {:color current-color
+ :disable-opacity disable-opacity
+ :on-change handle-change-color
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}])]
- [:div.colorpicker-tabs
- [:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
- {:class (when (= @active-tab :ramp) "active")
- :alt (tr "workspace.libraries.colors.rgba")
- :on-click set-tab!
- :data-tab "ramp"} i/picker-ramp]
- [:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
- {:class (when (= @active-tab :harmony) "active")
- :alt (tr "workspace.libraries.colors.rgb-complementary")
- :on-click set-tab!
- :data-tab "harmony"} i/picker-harmony]
- [:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
- {:class (when (= @active-tab :hsva) "active")
- :alt (tr "workspace.libraries.colors.hsv")
- :on-click set-tab!
- :data-tab "hsva"} i/picker-hsv]]
+ [:& tab-element {:id :harmony :title i/rgba-complementary-refactor}
+ (if picking-color?
+ [:div {:class (stl/css :picker-detail-wrapper)}
+ [:div {:class (stl/css :center-circle)}]
+ [:canvas#picker-detail {:width 256 :height 140}]]
+ [:& harmony-selector
+ {:color current-color
+ :disable-opacity disable-opacity
+ :on-change handle-change-color
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}])]
- (if picking-color?
- [:div.picker-detail-wrapper
- [:div.center-circle]
- [:canvas#picker-detail {:width 200 :height 160}]]
- (case @active-tab
- :ramp
- [:& ramp-selector
- {:color current-color
- :disable-opacity disable-opacity
- :on-change handle-change-color
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
- :harmony
- [:& harmony-selector
- {:color current-color
- :disable-opacity disable-opacity
- :on-change handle-change-color
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
- :hsva
- [:& hsva-selector
- {:color current-color
- :disable-opacity disable-opacity
- :on-change handle-change-color
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
- nil))
+ [:& tab-element {:id :hsva :title i/hsva-refactor}
+ (if picking-color?
+ [:div {:class (stl/css :picker-detail-wrapper)}
+ [:div {:class (stl/css :center-circle)}]
+ [:canvas#picker-detail {:width 256 :height 140}]]
+ [:& hsva-selector
+ {:color current-color
+ :disable-opacity disable-opacity
+ :on-change handle-change-color
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}])]]]
- [:& color-inputs
- {:type (if (= @active-tab :hsva) :hsv :rgb)
- :disable-opacity disable-opacity
- :color current-color
- :on-change handle-change-color}]
+ [:& color-inputs
+ {:type (if (= @active-tab :hsva) :hsv :rgb)
+ :disable-opacity disable-opacity
+ :color current-color
+ :on-change handle-change-color}]
- [:& libraries
- {:state state
- :current-color current-color
- :disable-gradient disable-gradient
- :disable-opacity disable-opacity
- :on-select-color on-select-library-color
- :on-add-library-color on-add-library-color}]
+ [:& libraries
+ {:state state
+ :current-color current-color
+ :on-select-color on-select-library-color
+ :on-add-library-color on-add-library-color}]
- (when on-accept
- [:div.actions
- [:button.btn-primary.btn-large
- {:on-click (fn []
- (on-accept (dc/get-color-from-colorpicker-state state))
- (modal/hide!))}
- (tr "workspace.libraries.colors.save-color")]])]]))
+ (when on-accept
+ [:div {:class (stl/css :actions)}
+ [:button {:class (stl/css :accept-color)
+ :on-click on-color-accept}
+ (tr "workspace.libraries.colors.save-color")]])]
+
+ [:div.colorpicker {:ref node-ref
+ :style {:touch-action "none"}}
+ [:div.colorpicker-content
+ [:div.top-actions
+ [:button.picker-btn
+ {:class (when picking-color? "active")
+ :on-click handle-click-picker}
+ i/picker]
+
+ (when (not disable-gradient)
+ [:div.gradients-buttons
+ [:button.gradient.linear-gradient
+ {:on-click on-activate-linear-gradient
+ :class (when (= :linear-gradient (:type state)) "active")}]
+
+ [:button.gradient.radial-gradient
+ {:on-click on-activate-radial-gradient
+ :class (when (= :radial-gradient (:type state)) "active")}]])]
+
+ (when (or (= (:type state) :linear-gradient)
+ (= (:type state) :radial-gradient))
+
+ [:& gradients
+ {:stops (:stops state)
+ :editing-stop (:editing-stop state)
+ :on-select-stop handle-change-stop}])
+
+ [:div.colorpicker-tabs
+ [:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
+ {:class (when (= @active-tab :ramp) "active")
+ :alt (tr "workspace.libraries.colors.rgba")
+ :on-click set-tab!
+ :data-tab "ramp"} i/picker-ramp]
+ [:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
+ {:class (when (= @active-tab :harmony) "active")
+ :alt (tr "workspace.libraries.colors.rgb-complementary")
+ :on-click set-tab!
+ :data-tab "harmony"} i/picker-harmony]
+ [:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
+ {:class (when (= @active-tab :hsva) "active")
+ :alt (tr "workspace.libraries.colors.hsv")
+ :on-click set-tab!
+ :data-tab "hsva"} i/picker-hsv]]
+
+ (if picking-color?
+ [:div.picker-detail-wrapper
+ [:div.center-circle]
+ [:canvas#picker-detail {:width 200 :height 160}]]
+ (case @active-tab
+ :ramp
+ [:& ramp-selector
+ {:color current-color
+ :disable-opacity disable-opacity
+ :on-change handle-change-color
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]
+ :harmony
+ [:& harmony-selector
+ {:color current-color
+ :disable-opacity disable-opacity
+ :on-change handle-change-color
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]
+ :hsva
+ [:& hsva-selector
+ {:color current-color
+ :disable-opacity disable-opacity
+ :on-change handle-change-color
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]
+ nil))
+
+ [:& color-inputs
+ {:type (if (= @active-tab :hsva) :hsv :rgb)
+ :disable-opacity disable-opacity
+ :color current-color
+ :on-change handle-change-color}]
+
+ [:& libraries
+ {:state state
+ :current-color current-color
+ :disable-gradient disable-gradient
+ :disable-opacity disable-opacity
+ :on-select-color on-select-library-color
+ :on-add-library-color on-add-library-color}]
+
+ (when on-accept
+ [:div.actions
+ [:button.btn-primary.btn-large
+ {:on-click on-color-accept}
+ (tr "workspace.libraries.colors.save-color")]])]])))
(defn calculate-position
"Calculates the style properties for the given coordinates and position"
- [{vh :height} position x y]
+ [{vh :height} position x y new-css-system]
(let [;; picker height in pixels
- h 430
+ h(if new-css-system 510 430)
;; Checks for overflow outside the viewport height
- overflow-fix (max 0 (+ y (- 50) h (- vh)))]
+ overflow-fix (max 0 (+ y (- 50) h (- vh)))
+
+ x-pos (if new-css-system 325 250)]
(cond
(or (nil? x) (nil? y)) {:left "auto" :right "16rem" :top "4rem"}
- (= position :left) {:left (str (- x 250) "px")
+ (= position :left) {:left (str (- x x-pos) "px")
:top (str (- y 50 overflow-fix) "px")}
:else {:left (str (+ x 80) "px")
:top (str (- y 70 overflow-fix) "px")})))
@@ -315,11 +421,12 @@
disable-gradient
disable-opacity
on-change on-close on-accept] :as props}]
- (let [vport (mf/deref viewport)
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ vport (mf/deref viewport)
dirty? (mf/use-var false)
last-change (mf/use-var nil)
position (or position :left)
- style (calculate-position vport position x y)
+ style (calculate-position vport position x y new-css-system)
handle-change
(fn [new-data]
@@ -333,8 +440,8 @@
#(when (and @dirty? @last-change on-close)
(on-close @last-change))))
- [:div.colorpicker-tooltip
- {:style (clj->js style)}
+ [:div {:class (stl/css new-css-system :colorpicker-tooltip)
+ :style (clj->js style)}
[:& colorpicker {:data data
:disable-gradient disable-gradient
:disable-opacity disable-opacity
diff --git a/frontend/src/app/main/ui/workspace/colorpicker.scss b/frontend/src/app/main/ui/workspace/colorpicker.scss
new file mode 100644
index 0000000000..f030e5a399
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/colorpicker.scss
@@ -0,0 +1,124 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.colorpicker-tooltip {
+ @extend .modal-background;
+ top: $s-100;
+ left: calc(10 * $s-140);
+ width: auto;
+ .colorpicker {
+ border-radius: $br-8;
+ width: $s-260;
+ & > * {
+ width: $s-260;
+ }
+ .top-actions {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ height: $s-28;
+ .picker-btn {
+ @include buttonStyle;
+ @include flexCenter;
+ border-radius: $br-8;
+ background-color: transparent;
+ border: $s-1 solid transparent;
+ height: $s-20;
+ width: $s-20;
+ border-radius: $br-4;
+ padding: 0;
+ svg {
+ @extend .button-icon;
+ stroke: var(--button-tertiary-foreground-color-rest);
+ }
+ &:hover {
+ svg {
+ stroke: var(--button-tertiary-foreground-color-focus);
+ }
+ }
+ &:focus,
+ &:focus-visible {
+ outline: none;
+ svg {
+ stroke: var(--button-secondary-foreground-color-hover);
+ }
+ }
+ &:active {
+ outline: none;
+ border: $s-1 solid transparent;
+ svg {
+ stroke: var(--button-tertiary-foreground-color-active);
+ }
+ }
+ &.selected {
+ svg {
+ stroke: var(--button-tertiary-foreground-color-active);
+ }
+ }
+ }
+ .gradient-buttons {
+ display: flex;
+ align-items: center;
+ gap: $s-8;
+ .gradient-btn {
+ @extend .button-tertiary;
+ height: $s-20;
+ width: $s-20;
+ border-radius: $br-4;
+ border: $s-2 solid transparent;
+ &:hover {
+ border: $s-2 solid var(--colorpicker-details-color-selected);
+ }
+ }
+ .linear-gradient-btn {
+ background: linear-gradient(180deg, var(--color-foreground-secondary), transparent);
+ &.selected {
+ background: linear-gradient(to bottom, rgba(126, 255, 245, 1) 0%, rgba(126, 255, 245, 0.2) 100%);
+ border: $s-2 solid var(--colorpicker-details-color-selected);
+ }
+ }
+
+ .radial-gradient-btn {
+ background: radial-gradient(transparent, var(--color-foreground-secondary));
+ &.selected {
+ background: radial-gradient(rgba(126, 255, 245, 1) 0%, rgba(126, 255, 245, 0.2) 100%);
+ border: $s-2 solid var(--colorpicker-details-color-selected);
+ }
+ }
+ }
+ }
+ .actions {
+ display: flex;
+ gap: $s-4;
+ .accept-color {
+ @include titleTipography;
+ @extend .button-secondary;
+ width: 100%;
+ height: $s-32;
+ margin-top: $s-8;
+ }
+ }
+ }
+ .colorpicker-tabs {
+ .picker-detail-wrapper {
+ @include flexCenter;
+ position: relative;
+ margin: $s-12 0 $s-8 0;
+ .center-circle {
+ width: $s-24;
+ height: $s-24;
+ border: $s-2 solid var(--colorpicker-details-color);
+ border-radius: $br-circle;
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(calc(-1 * $s-12), calc(-1 * $s-12));
+ }
+ }
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/color_inputs.cljs b/frontend/src/app/main/ui/workspace/colorpicker/color_inputs.cljs
index dad0b71e73..b7bb1e5797 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/color_inputs.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker/color_inputs.cljs
@@ -5,9 +5,11 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.colorpicker.color-inputs
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.math :as mth]
+ [app.main.ui.context :as ctx]
[app.util.color :as uc]
[app.util.dom :as dom]
[rumext.v2 :as mf]))
@@ -27,7 +29,8 @@
(* (/ val 255) 100))
(mf/defc color-inputs [{:keys [type color disable-opacity on-change]}]
- (let [{red :r green :g blue :b
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ {red :r green :g blue :b
hue :h saturation :s value :v
hex :hex alpha :alpha} color
@@ -108,84 +111,169 @@
property-val)]
(dom/set-value! node new-val))))))))
- [:div.color-values
- {:class (when disable-opacity "disable-opacity")}
- [:input {:id "hex-value"
- :ref (:hex refs)
- :default-value hex
- :on-change on-change-hex
- :on-blur on-blur-hex}]
+ (if new-css-system
+ [:div {:class (stl/css-case :color-values true
+ :disable-opacity disable-opacity)}
- (if (= type :rgb)
- [:*
- [:input {:id "red-value"
- :ref (:r refs)
- :type "number"
- :min 0
- :max 255
- :default-value red
- :on-change (on-change-property :r 255)}]
+ [:div {:class (stl/css :colors-row)}
+ (if (= type :rgb)
+ [:*
+ [:div {:class (stl/css :input-wrapper)}
+ [:span {:class (stl/css :input-label)} "R"]
+ [:input {:id "red-value"
+ :ref (:r refs)
+ :type "number"
+ :min 0
+ :max 255
+ :default-value red
+ :on-change (on-change-property :r 255)}]]
+ [:div {:class (stl/css :input-wrapper)}
+ [:span {:class (stl/css :input-label)} "G"]
+ [:input {:id "green-value"
+ :ref (:g refs)
+ :type "number"
+ :min 0
+ :max 255
+ :default-value green
+ :on-change (on-change-property :g 255)}]]
+ [:div {:class (stl/css :input-wrapper)}
+ [:span {:class (stl/css :input-label)} "B"]
+ [:input {:id "blue-value"
+ :ref (:b refs)
+ :type "number"
+ :min 0
+ :max 255
+ :default-value blue
+ :on-change (on-change-property :b 255)}]]]
- [:input {:id "green-value"
- :ref (:g refs)
- :type "number"
- :min 0
- :max 255
- :default-value green
- :on-change (on-change-property :g 255)}]
+ [:*
+ [:div {:class (stl/css :input-wrapper)}
+ [:span {:class (stl/css :input-label)} "H"]
+ [:input {:id "hue-value"
+ :ref (:h refs)
+ :type "number"
+ :min 0
+ :max 360
+ :default-value hue
+ :on-change (on-change-property :h 360)}]]
+ [:div {:class (stl/css :input-wrapper)}
+ [:span {:class (stl/css :input-label)} "S"]
+ [:input {:id "saturation-value"
+ :ref (:s refs)
+ :type "number"
+ :min 0
+ :max 100
+ :step 1
+ :default-value saturation
+ :on-change (on-change-property :s 100)}]]
+ [:div {:class (stl/css :input-wrapper)}
+ [:span {:class (stl/css :input-label)} "V"]
+ [:input {:id "value-value"
+ :ref (:v refs)
+ :type "number"
+ :min 0
+ :max 100
+ :default-value value
+ :on-change (on-change-property :v 100)}]]])]
+ [:div {:class (stl/css :hex-alpha-wrapper)}
+ [:div {:class (stl/css-case :input-wrapper true
+ :hex true)}
+ [:span {:class (stl/css :input-label)} "HEX"]
+ [:input {:id "hex-value"
+ :ref (:hex refs)
+ :default-value hex
+ :on-change on-change-hex
+ :on-blur on-blur-hex}]]
+ (when (not disable-opacity)
+ [:div {:class (stl/css-case :input-wrapper true)}
+ [:span {:class (stl/css :input-label)} "A"]
+ [:input {:id "alpha-value"
+ :ref (:alpha refs)
+ :type "number"
+ :min 0
+ :step 1
+ :max 100
+ :default-value (if (= alpha :multiple) "" alpha)
+ :on-change on-change-opacity}]])]]
- [:input {:id "blue-value"
- :ref (:b refs)
- :type "number"
- :min 0
- :max 255
- :default-value blue
- :on-change (on-change-property :b 255)}]]
- [:*
- [:input {:id "hue-value"
- :ref (:h refs)
- :type "number"
- :min 0
- :max 360
- :default-value hue
- :on-change (on-change-property :h 360)}]
+ [:div.color-values
+ {:class (when disable-opacity "disable-opacity")}
+ [:input {:id "hex-value"
+ :ref (:hex refs)
+ :default-value hex
+ :on-change on-change-hex
+ :on-blur on-blur-hex}]
- [:input {:id "saturation-value"
- :ref (:s refs)
- :type "number"
- :min 0
- :max 100
- :step 1
- :default-value saturation
- :on-change (on-change-property :s 100)}]
+ (if (= type :rgb)
+ [:*
+ [:input {:id "red-value"
+ :ref (:r refs)
+ :type "number"
+ :min 0
+ :max 255
+ :default-value red
+ :on-change (on-change-property :r 255)}]
- [:input {:id "value-value"
- :ref (:v refs)
- :type "number"
- :min 0
- :max 100
- :default-value value
- :on-change (on-change-property :v 100)}]])
+ [:input {:id "green-value"
+ :ref (:g refs)
+ :type "number"
+ :min 0
+ :max 255
+ :default-value green
+ :on-change (on-change-property :g 255)}]
- (when (not disable-opacity)
- [:input.alpha-value {:id "alpha-value"
- :ref (:alpha refs)
- :type "number"
- :min 0
- :step 1
- :max 100
- :default-value (if (= alpha :multiple) "" alpha)
- :on-change on-change-opacity}])
+ [:input {:id "blue-value"
+ :ref (:b refs)
+ :type "number"
+ :min 0
+ :max 255
+ :default-value blue
+ :on-change (on-change-property :b 255)}]]
+ [:*
+ [:input {:id "hue-value"
+ :ref (:h refs)
+ :type "number"
+ :min 0
+ :max 360
+ :default-value hue
+ :on-change (on-change-property :h 360)}]
- [:label.hex-label {:for "hex-value"} "HEX"]
- (if (= type :rgb)
- [:*
- [:label.red-label {:for "red-value"} "R"]
- [:label.green-label {:for "green-value"} "G"]
- [:label.blue-label {:for "blue-value"} "B"]]
- [:*
- [:label.red-label {:for "hue-value"} "H"]
- [:label.green-label {:for "saturation-value"} "S"]
- [:label.blue-label {:for "value-value"} "V"]])
- (when (not disable-opacity)
- [:label.alpha-label {:for "alpha-value"} "A"])]))
+ [:input {:id "saturation-value"
+ :ref (:s refs)
+ :type "number"
+ :min 0
+ :max 100
+ :step 1
+ :default-value saturation
+ :on-change (on-change-property :s 100)}]
+
+ [:input {:id "value-value"
+ :ref (:v refs)
+ :type "number"
+ :min 0
+ :max 100
+ :default-value value
+ :on-change (on-change-property :v 100)}]])
+
+ (when (not disable-opacity)
+ [:input.alpha-value {:id "alpha-value"
+ :ref (:alpha refs)
+ :type "number"
+ :min 0
+ :step 1
+ :max 100
+ :default-value (if (= alpha :multiple) "" alpha)
+ :on-change on-change-opacity}])
+
+ [:label.hex-label {:for "hex-value"} "HEX"]
+ (if (= type :rgb)
+ [:*
+ [:label.red-label {:for "red-value"} "R"]
+ [:label.green-label {:for "green-value"} "G"]
+ [:label.blue-label {:for "blue-value"} "B"]]
+ [:*
+ [:label.red-label {:for "hue-value"} "H"]
+ [:label.green-label {:for "saturation-value"} "S"]
+ [:label.blue-label {:for "value-value"} "V"]])
+ (when (not disable-opacity)
+ [:label.alpha-label {:for "alpha-value"} "A"])])))
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/color_inputs.scss b/frontend/src/app/main/ui/workspace/colorpicker/color_inputs.scss
new file mode 100644
index 0000000000..e66b883eeb
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/colorpicker/color_inputs.scss
@@ -0,0 +1,37 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.color-values {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ &.disable-opacity {
+ grid-template-columns: 3.5rem repeat(3, 1fr);
+ }
+ .colors-row {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .input-wrapper {
+ @extend .input-element;
+ width: $s-84;
+ }
+ }
+ .hex-alpha-wrapper {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .input-wrapper {
+ @extend .input-element;
+ width: $s-84;
+ &.hex {
+ width: $s-172;
+ }
+ }
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/gradients.cljs b/frontend/src/app/main/ui/workspace/colorpicker/gradients.cljs
index 43a4f768b6..4242861de6 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/gradients.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker/gradients.cljs
@@ -5,8 +5,10 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.colorpicker.gradients
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data.macros :as dm]
+ [app.main.ui.context :as ctx]
[cuerdas.core :as str]
[rumext.v2 :as mf]))
@@ -20,17 +22,40 @@
(mf/defc gradients
[{:keys [stops editing-stop on-select-stop]}]
- [:div.gradient-stops
- [:div.gradient-background-wrapper
- [:div.gradient-background {:style {:background (gradient->string stops)}}]]
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)]
+ (if new-css-system
+ [:div {:class (stl/css :gradient-stops)}
+ [:div {:class (stl/css :gradient-background-wrapper)}
+ [:div {:class (stl/css :gradient-background)
+ :style {:background (gradient->string stops)}}]]
- [:div.gradient-stop-wrapper
- (for [{:keys [offset hex r g b alpha] :as value} stops]
- [:div.gradient-stop
- {:class (when (= editing-stop offset) "active")
- :on-click (partial on-select-stop offset)
- :style {:left (dm/str (* offset 100) "%")}
- :key (dm/str offset)}
+ [:div {:class (stl/css :gradient-stop-wrapper)}
+ (for [{:keys [offset hex r g b alpha] :as value} stops]
+ [:button {:class (stl/css-case :gradient-stop true
+ :selected (= editing-stop offset))
+ :data-value offset
+ :on-click on-select-stop
+ :style {:left (dm/str (* offset 100) "%")
+ :backgroundColor hex}
+ :key (dm/str offset)}
- [:div.gradient-stop-color {:style {:background-color hex}}]
- [:div.gradient-stop-alpha {:style {:background-color (str/ffmt "rgba(%1, %2, %3, %4)" r g b alpha)}}]])]])
+ [:div {:class (stl/css :gradient-stop-color)
+ :style {:background-color hex}}]
+ [:div {:class (stl/css :gradient-stop-alpha)
+ :style {:background-color (str/ffmt "rgba(%1, %2, %3, %4)" r g b alpha)}}]])]]
+
+ [:div.gradient-stops
+ [:div.gradient-background-wrapper
+ [:div.gradient-background {:style {:background (gradient->string stops)}}]]
+
+ [:div.gradient-stop-wrapper
+ (for [{:keys [offset hex r g b alpha] :as value} stops]
+ [:div.gradient-stop
+ {:class (when (= editing-stop offset) "active")
+ :data-value offset
+ :on-click on-select-stop
+ :style {:left (dm/str (* offset 100) "%")}
+ :key (dm/str offset)}
+
+ [:div.gradient-stop-color {:style {:background-color hex}}]
+ [:div.gradient-stop-alpha {:style {:background-color (str/ffmt "rgba(%1, %2, %3, %4)" r g b alpha)}}]])]])))
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/gradients.scss b/frontend/src/app/main/ui/workspace/colorpicker/gradients.scss
new file mode 100644
index 0000000000..78932650dd
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/colorpicker/gradients.scss
@@ -0,0 +1,51 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.gradient-stops {
+ display: flex;
+ height: $s-20;
+ width: 100%;
+ margin: $s-12 0;
+ background-color: var(--colorpicker-handlers-color);
+ border-radius: $br-6;
+
+ .gradient-background-wrapper {
+ height: 100%;
+ width: 100%;
+ border-radius: $br-6;
+ background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=")
+ left center;
+
+ .gradient-background {
+ height: 100%;
+ width: 100%;
+ border-radius: $br-6;
+ border: $s-2 solid var(--colorpicker-details-color);
+ }
+ }
+ .gradient-stop-wrapper {
+ position: absolute;
+ width: calc(100% - 2rem);
+ .gradient-stop {
+ position: absolute;
+ display: grid;
+ grid-template-columns: 50% 50%;
+ width: $s-16;
+ height: $s-24;
+ border-radius: $br-4;
+ margin-top: calc(-1 * $s-2);
+ margin-left: calc(-1 * $s-8);
+ border: $s-2 solid var(--colorpicker-handlers-color);
+ background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=")
+ left center;
+ &.selected {
+ border: $s-2 solid var(--colorpicker-details-color-selected);
+ }
+ }
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs b/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs
index 119faa933d..1c1d9b30a2 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs
@@ -5,9 +5,11 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.colorpicker.harmony
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.geom.point :as gpt]
[app.common.math :as mth]
+ [app.main.ui.context :as ctx]
[app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]]
[app.util.color :as uc]
[app.util.dom :as dom]
@@ -57,13 +59,16 @@
(gpt/point x y)))
(mf/defc harmony-selector [{:keys [color disable-opacity on-change on-start-drag on-finish-drag]}]
- (let [canvas-ref (mf/use-ref nil)
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ canvas-ref (mf/use-ref nil)
+ canvas-side (if new-css-system
+ 192
+ 152)
{hue :h saturation :s value :v alpha :alpha} color
- canvas-side 152
- pos-current (color->point canvas-side hue saturation)
+ pos-current (color->point canvas-side hue saturation)
pos-complement (color->point canvas-side (mod (+ hue 180) 360) saturation)
- dragging? (mf/use-state false)
+ dragging? (mf/use-state false)
calculate-pos (fn [ev]
(let [{:keys [left right top bottom]} (-> ev dom/get-target dom/get-bounding-rect)
@@ -75,7 +80,7 @@
py (- (* 2 py) 1)
angle (mth/degrees (mth/atan2 px py))
- new-hue (mod (- angle 90 ) 360)
+ new-hue (mod (- angle 90) 360)
new-saturation (mth/clamp (mth/distance [px py] [0 0]) 0 1)
hex (uc/hsv->hex [new-hue new-saturation value])
[r g b] (uc/hex->rgb hex)]
@@ -123,41 +128,83 @@
(mf/deps canvas-ref)
(fn [] (when canvas-ref
(create-color-wheel (mf/ref-val canvas-ref)))))
-
- [:div.harmony-selector
- [:div.hue-wheel-wrapper
- [:canvas.hue-wheel
- {:ref canvas-ref
- :width canvas-side
- :height canvas-side
- :on-pointer-down handle-start-drag
- :on-pointer-up handle-stop-drag
- :on-lost-pointer-capture handle-stop-drag
- :on-click calculate-pos
- :on-pointer-move #(when @dragging? (calculate-pos %))}]
- [:div.handler {:style {:pointer-events "none"
- :left (:x pos-current)
- :top (:y pos-current)}}]
- [:div.handler.complement {:style {:left (:x pos-complement)
- :top (:y pos-complement)
- :cursor "pointer"}
- :on-click on-complement-click}]]
- [:div.handlers-wrapper
- [:& slider-selector {:class "value"
- :vertical? true
- :reverse? true
- :value value
- :max-value 255
- :vertical true
- :on-change on-change-value
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
- (when (not disable-opacity)
- [:& slider-selector {:class "opacity"
+ (if new-css-system
+ [:div {:class (stl/css :harmony-selector)}
+ [:div {:class (stl/css :handlers-wrapper)}
+ [:& slider-selector {:type :value
:vertical? true
- :value alpha
- :max-value 1
+ :reverse? true
+ :value value
+ :max-value 255
:vertical true
- :on-change on-change-opacity
+ :on-change on-change-value
:on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}])]]))
+ :on-finish-drag on-finish-drag}]
+ (when (not disable-opacity)
+ [[:& slider-selector {:type :opacity
+ :vertical? true
+ :value alpha
+ :max-value 1
+ :vertical true
+ :on-change on-change-opacity
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]])]
+
+ [:div {:class (stl/css :hue-wheel-wrapper)}
+ [:canvas {:class (stl/css :hue-wheel)
+ :ref canvas-ref
+ :width canvas-side
+ :height canvas-side
+ :on-pointer-down handle-start-drag
+ :on-pointer-up handle-stop-drag
+ :on-lost-pointer-capture handle-stop-drag
+ :on-click calculate-pos
+ :on-pointer-move #(when @dragging? (calculate-pos %))}]
+ [:div {:class (stl/css :handler)
+ :style {:pointer-events "none"
+ :left (:x pos-current)
+ :top (:y pos-current)}}]
+ [:div {:class (stl/css-case :handler true
+ :complement true)
+ :style {:left (:x pos-complement)
+ :top (:y pos-complement)
+ :cursor "pointer"}
+ :on-click on-complement-click}]]]
+
+ [:div.harmony-selector
+ [:div.hue-wheel-wrapper
+ [:canvas.hue-wheel
+ {:ref canvas-ref
+ :width canvas-side
+ :height canvas-side
+ :on-pointer-down handle-start-drag
+ :on-pointer-up handle-stop-drag
+ :on-lost-pointer-capture handle-stop-drag
+ :on-click calculate-pos
+ :on-pointer-move #(when @dragging? (calculate-pos %))}]
+ [:div.handler {:style {:pointer-events "none"
+ :left (:x pos-current)
+ :top (:y pos-current)}}]
+ [:div.handler.complement {:style {:left (:x pos-complement)
+ :top (:y pos-complement)
+ :cursor "pointer"}
+ :on-click on-complement-click}]]
+ [:div.handlers-wrapper
+ [:& slider-selector {:class "value"
+ :vertical? true
+ :reverse? true
+ :value value
+ :max-value 255
+ :vertical true
+ :on-change on-change-value
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]
+ (when (not disable-opacity)
+ [:& slider-selector {:class "opacity"
+ :vertical? true
+ :value alpha
+ :max-value 1
+ :vertical true
+ :on-change on-change-opacity
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}])]])))
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/harmony.scss b/frontend/src/app/main/ui/workspace/colorpicker/harmony.scss
new file mode 100644
index 0000000000..970c9ed5b5
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/colorpicker/harmony.scss
@@ -0,0 +1,45 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.harmony-selector {
+ display: flex;
+ align-items: center;
+ gap: $s-8;
+ margin-top: $s-12;
+ margin-bottom: $s-8;
+ .hue-wheel-wrapper {
+ @include flexCenter;
+ position: relative;
+
+ .hue-wheel {
+ width: $s-196;
+ height: $s-196;
+ }
+
+ .handler {
+ @extend .colorpicker-handler;
+ height: $s-16;
+ width: $s-16;
+ border: $s-2 solid var(--colorpicker-handlers-color);
+ }
+
+ .handler.complement {
+ background-color: var(--colorpicker-handlers-color);
+ border: $s-2 solid var(--colorpicker-handlers-color);
+ }
+ }
+
+ .handlers-wrapper {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ height: $s-200;
+ width: $s-52;
+ flex-grow: 1;
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/hsva.cljs b/frontend/src/app/main/ui/workspace/colorpicker/hsva.cljs
index 6933baeb3a..2b06676078 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/hsva.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker/hsva.cljs
@@ -5,13 +5,16 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.colorpicker.hsva
+ (:require-macros [app.main.style :as stl])
(:require
+ [app.main.ui.context :as ctx]
[app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]]
[app.util.color :as uc]
[rumext.v2 :as mf]))
(mf/defc hsva-selector [{:keys [color disable-opacity on-change on-start-drag on-finish-drag]}]
- (let [{hue :h saturation :s value :v alpha :alpha} color
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ {hue :h saturation :s value :v alpha :alpha} color
handle-change-slider (fn [key]
(fn [new-value]
(let [change (hash-map key new-value)
@@ -22,42 +25,87 @@
{:hex hex
:r r :g g :b b})))))
on-change-opacity (fn [new-alpha] (on-change {:alpha new-alpha}))]
- [:div.hsva-selector
- [:span.hsva-selector-label "H"]
- [:& slider-selector
- {:class "hue"
- :max-value 360
- :value hue
- :on-change (handle-change-slider :h)
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
-
- [:span.hsva-selector-label "S"]
- [:& slider-selector
- {:class "saturation"
- :max-value 1
- :value saturation
- :on-change (handle-change-slider :s)
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
-
- [:span.hsva-selector-label "V"]
- [:& slider-selector
- {:class "value"
- :reverse? false
- :max-value 255
- :value value
- :on-change (handle-change-slider :v)
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
-
- (when (not disable-opacity)
- [:*
- [:span.hsva-selector-label "A"]
+ (if new-css-system
+ [:div {:class (stl/css :hsva-selector)}
+ [:div {:class (stl/css :hsva-row)}
+ [:span {:class (stl/css :hsva-selector-label)} "H"]
[:& slider-selector
- {:class "opacity"
- :max-value 1
- :value alpha
- :on-change on-change-opacity
+ {:class (stl/css :hsva-bar)
+ :type :hue
+ :max-value 360
+ :value hue
+ :on-change (handle-change-slider :h)
:on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]])]))
+ :on-finish-drag on-finish-drag}]]
+ [:div {:class (stl/css :hsva-row)}
+ [:span {:class (stl/css :hsva-selector-label)} "S"]
+ [:& slider-selector
+ {:class (stl/css :hsva-bar)
+ :type :saturation
+ :max-value 1
+ :value saturation
+ :on-change (handle-change-slider :s)
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]]
+ [:div {:class (stl/css :hsva-row)}
+ [:span {:class (stl/css :hsva-selector-label)} "V"]
+ [:& slider-selector
+ {:class (stl/css :hsva-bar)
+ :type :value
+ :reverse? false
+ :max-value 255
+ :value value
+ :on-change (handle-change-slider :v)
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]]
+ (when (not disable-opacity)
+ [:div {:class (stl/css :hsva-row)}
+ [:span {:class (stl/css :hsva-selector-label)} "A"]
+ [:& slider-selector
+ {:class (stl/css :hsva-bar)
+ :type :opacity
+ :max-value 1
+ :value alpha
+ :on-change on-change-opacity
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]])]
+
+ [:div.hsva-selector
+ [:span.hsva-selector-label "H"]
+ [:& slider-selector
+ {:class "hue"
+ :max-value 360
+ :value hue
+ :on-change (handle-change-slider :h)
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]
+
+ [:span.hsva-selector-label "S"]
+ [:& slider-selector
+ {:class "saturation"
+ :max-value 1
+ :value saturation
+ :on-change (handle-change-slider :s)
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]
+ [:span.hsva-selector-label "V"]
+ [:& slider-selector
+ {:class "value"
+ :reverse? false
+ :max-value 255
+ :value value
+ :on-change (handle-change-slider :v)
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]
+
+ (when (not disable-opacity)
+ [:*
+ [:span.hsva-selector-label "A"]
+ [:& slider-selector
+ {:class "opacity"
+ :max-value 1
+ :value alpha
+ :on-change on-change-opacity
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]])])
+ ))
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/hsva.scss b/frontend/src/app/main/ui/workspace/colorpicker/hsva.scss
new file mode 100644
index 0000000000..49e5f2e9e8
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/colorpicker/hsva.scss
@@ -0,0 +1,30 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.hsva-selector {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ padding: $s-4;
+ grid-row-gap: $s-8;
+ margin-bottom: $s-8;
+ .hsva-row {
+ display: flex;
+ align-items: center;
+ .hsva-selector-label {
+ @include tabTitleTipography;
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+ width: $s-32;
+ }
+ .hsva-bar {
+ width: $s-228;
+ }
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs b/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs
index ba6a8b28e1..7a6690eba1 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs
@@ -5,7 +5,9 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.colorpicker.libraries
+ (:require-macros [app.main.style :as stl])
(:require
+ [app.common.data :as d]
[app.common.data.macros :as dm]
[app.main.data.events :as ev]
[app.main.data.workspace :as dw]
@@ -13,6 +15,9 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.color-bullet :refer [color-bullet]]
+ [app.main.ui.components.color-bullet-new :as cb]
+ [app.main.ui.components.select :refer [select]]
+ [app.main.ui.context :as ctx]
[app.main.ui.hooks :as h]
[app.main.ui.hooks.resize :as r]
[app.main.ui.icons :as i]
@@ -23,7 +28,8 @@
(mf/defc libraries
[{:keys [state on-select-color on-add-library-color disable-gradient disable-opacity]}]
- (let [selected (h/use-shared-state mdc/colorpicker-selected-broadcast-key :recent)
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ selected (h/use-shared-state mdc/colorpicker-selected-broadcast-key :recent)
current-colors (mf/use-state [])
shared-libs (mf/deref refs/workspace-libraries)
@@ -34,7 +40,9 @@
on-library-change
(mf/use-fn
(fn [event]
- (let [val (dom/get-target-val event)]
+ (let [val (if new-css-system
+ event
+ (dom/get-target-val event))]
(reset! selected
(if (or (= val "recent")
(= val "file"))
@@ -44,7 +52,30 @@
check-valid-color?
(fn [color]
(and (or (not disable-gradient) (not (:gradient color)))
- (or (not disable-opacity) (= 1 (:opacity color)))))]
+ (or (not disable-opacity) (= 1 (:opacity color)))))
+
+ toggle-palette
+ (mf/use-fn
+ (fn []
+ (r/set-resize-type! :bottom)
+ (dom/add-class! (dom/get-element-by-class "color-palette") "fade-out-down")
+ (ts/schedule 300 #(st/emit! (dw/remove-layout-flag :textpalette)
+ (-> (dw/toggle-layout-flag :colorpalette)
+ (vary-meta assoc ::ev/origin "workspace-colorpicker"))))))
+
+ shared-libs-options (mapv (fn[lib] {:value (d/name (:id lib)) :label (:name lib)} ) (vals shared-libs))
+
+
+ library-options [{:value "recent" :label (tr "workspace.libraries.colors.recent-colors")}
+ {:value "file" :label (tr "workspace.libraries.colors.file-library")}]
+
+ options (concat library-options shared-libs-options)
+
+ on-color-click
+ (mf/use-fn
+ (mf/deps state)
+ (fn[event]
+ (on-select-color state event)))]
;; Load library colors when the select is changed
(mf/with-effect [@selected recent-colors file-colors]
@@ -71,33 +102,59 @@
(let [colors (vals file-colors)]
(reset! current-colors (into [] (filter check-valid-color?) colors)))))
- [:div.libraries
- [:select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :on-change on-library-change
- :value (name @selected)}
- [:option {:value "recent"} (tr "workspace.libraries.colors.recent-colors")]
- [:option {:value "file"} (tr "workspace.libraries.colors.file-library")]
+ (if new-css-system
+ [:div {:class (stl/css :libraries)}
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select
+ {:class (stl/css :shadow-type-select)
+ :default-value (or (name @selected) "recent")
+ :options options
+ :on-change on-library-change}]]
- (for [[_ {:keys [name id]}] shared-libs]
- [:option {:key id :value id} name])]
+ [:div {:class (stl/css :selected-colors)}
+ (when (= @selected :file)
+ [:button {:class (stl/css :add-color-btn)
+ :on-click on-add-library-color}
+ i/add-refactor])
- [:div.selected-colors
- (when (= @selected :file)
- [:div.color-bullet.button.plus-button {:style {:background-color "var(--color-white)"}
- :on-click on-add-library-color}
- i/plus])
+ [:button {:class (stl/css :palette-btn)
+ :on-click toggle-palette}
+ i/swatches-refactor]
- [:div.color-bullet.button {:style {:background-color "var(--color-white)"}
- :on-click(fn []
- (r/set-resize-type! :bottom)
- (dom/add-class! (dom/get-element-by-class "color-palette") "fade-out-down")
- (ts/schedule 300 #(st/emit! (dw/remove-layout-flag :textpalette)
- (-> (dw/toggle-layout-flag :colorpalette)
- (vary-meta assoc ::ev/origin "workspace-colorpicker")))))}
- i/palette]
+ (for [[idx color] (map-indexed vector @current-colors)]
+ [:& cb/color-bullet
+ {:key (dm/str "color-" idx)
+ :color color
+ :on-click on-color-click}])]]
- (for [[idx color] (map-indexed vector @current-colors)]
- [:& color-bullet
- {:key (dm/str "color-" idx)
- :color color
- :on-click (partial on-select-color state)}])]]))
+
+ [:div.libraries
+ [:select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
+ :on-change on-library-change
+ :value (name @selected)}
+ [:option {:value "recent"} (tr "workspace.libraries.colors.recent-colors")]
+ [:option {:value "file"} (tr "workspace.libraries.colors.file-library")]
+
+ (for [[_ {:keys [name id]}] shared-libs]
+ [:option {:key id :value id} name])]
+
+ [:div.selected-colors
+ (when (= @selected :file)
+ [:div.color-bullet.button.plus-button {:style {:background-color "var(--color-white)"}
+ :on-click on-add-library-color}
+ i/plus])
+
+ [:div.color-bullet.button {:style {:background-color "var(--color-white)"}
+ :on-click (fn []
+ (r/set-resize-type! :bottom)
+ (dom/add-class! (dom/get-element-by-class "color-palette") "fade-out-down")
+ (ts/schedule 300 #(st/emit! (dw/remove-layout-flag :textpalette)
+ (-> (dw/toggle-layout-flag :colorpalette)
+ (vary-meta assoc ::ev/origin "workspace-colorpicker")))))}
+ i/palette]
+
+ (for [[idx color] (map-indexed vector @current-colors)]
+ [:& color-bullet
+ {:key (dm/str "color-" idx)
+ :color color
+ :on-click on-color-click}])]])))
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/libraries.scss b/frontend/src/app/main/ui/workspace/colorpicker/libraries.scss
new file mode 100644
index 0000000000..2ae39c7f01
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/colorpicker/libraries.scss
@@ -0,0 +1,36 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.libraries {
+ margin-top: $s-8;
+ width: 100%;
+
+ .selected-colors {
+ display: grid;
+ grid-template-columns: repeat(8, 1fr);
+ gap: $s-4;
+ justify-content: space-between;
+ overflow: auto;
+ margin-top: $s-8;
+ .add-color-btn,
+ .palette-btn {
+ @extend .button-secondary;
+ height: $s-24;
+ width: $s-24;
+ border-radius: $br-circle;
+ padding: 0;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ .selected-colors::after {
+ content: "";
+ flex: auto;
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs b/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs
index 0a839324a8..4adfb44638 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs
@@ -5,16 +5,20 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.colorpicker.ramp
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.math :as mth]
[app.main.ui.components.color-bullet :refer [color-bullet]]
+ [app.main.ui.components.color-bullet-new :as cb]
+ [app.main.ui.context :as ctx]
[app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]]
[app.util.color :as uc]
[app.util.dom :as dom]
[rumext.v2 :as mf]))
(mf/defc value-saturation-selector [{:keys [saturation value on-change on-start-drag on-finish-drag]}]
- (let [dragging? (mf/use-state false)
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ dragging? (mf/use-state false)
calculate-pos
(fn [ev]
(let [{:keys [left right top bottom]} (-> ev dom/get-target dom/get-bounding-rect)
@@ -37,21 +41,33 @@
(fn [event]
(dom/release-pointer event)
(reset! dragging? false)
- (on-finish-drag)))
- ]
- [:div.value-saturation-selector
- {:on-pointer-down handle-start-drag
- :on-pointer-up handle-stop-drag
- :on-lost-pointer-capture handle-stop-drag
- :on-click calculate-pos
- :on-pointer-move #(when @dragging? (calculate-pos %))}
- [:div.handler {:style {:pointer-events "none"
- :left (str (* 100 saturation) "%")
- :top (str (* 100 (- 1 (/ value 255))) "%")}}]]))
+ (on-finish-drag)))]
+ (if new-css-system
+ [:div {:class (stl/css :value-saturation-selector)
+ :on-pointer-down handle-start-drag
+ :on-pointer-up handle-stop-drag
+ :on-lost-pointer-capture handle-stop-drag
+ :on-click calculate-pos
+ :on-pointer-move #(when @dragging? (calculate-pos %))}
+ [:div {:class (stl/css :handler)
+ :style {:pointer-events "none"
+ :left (str (* 100 saturation) "%")
+ :top (str (* 100 (- 1 (/ value 255))) "%")}}]]
+
+ [:div.value-saturation-selector
+ {:on-pointer-down handle-start-drag
+ :on-pointer-up handle-stop-drag
+ :on-lost-pointer-capture handle-stop-drag
+ :on-click calculate-pos
+ :on-pointer-move #(when @dragging? (calculate-pos %))}
+ [:div.handler {:style {:pointer-events "none"
+ :left (str (* 100 saturation) "%")
+ :top (str (* 100 (- 1 (/ value 255))) "%")}}]])))
(mf/defc ramp-selector [{:keys [color disable-opacity on-change on-start-drag on-finish-drag]}]
- (let [{hex :hex
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ {hex :hex
hue :h saturation :s value :v alpha :alpha} color
on-change-value-saturation
@@ -69,34 +85,65 @@
[r g b] (uc/hex->rgb hex)]
(on-change {:hex hex
:r r :g g :b b
- :h new-hue} )))
+ :h new-hue})))
on-change-opacity
(fn [new-opacity]
- (on-change {:alpha new-opacity} ))]
- [:*
- [:& value-saturation-selector
- {:hue hue
- :saturation saturation
- :value value
- :on-change on-change-value-saturation
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
+ (on-change {:alpha new-opacity}))]
+ (if new-css-system
+ [:*
+ [:& value-saturation-selector
+ {:hue hue
+ :saturation saturation
+ :value value
+ :on-change on-change-value-saturation
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]
- [:div.shade-selector
- [:& color-bullet {:color {:color hex
- :opacity alpha}}]
- [:& slider-selector {:class "hue"
- :max-value 360
- :value hue
- :on-change on-change-hue
- :on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}]
+ [:div {:class (stl/css new-css-system :shade-selector)
+ :style #js {"--bullet-size" "52px"}}
+ [:& cb/color-bullet {:color {:color hex
+ :opacity alpha}
+ :area true}]
+ [:div {:class (stl/css :sliders-wrapper)}
+ [:& slider-selector {:type :hue
+ :max-value 360
+ :value hue
+ :on-change on-change-hue
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]
- (when (not disable-opacity)
- [:& slider-selector {:class "opacity"
- :max-value 1
- :value alpha
- :on-change on-change-opacity
+ (when (not disable-opacity)
+ [:& slider-selector {:type :opacity
+ :max-value 1
+ :value alpha
+ :on-change on-change-opacity
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}])]]]
+
+ [:*
+ [:& value-saturation-selector
+ {:hue hue
+ :saturation saturation
+ :value value
+ :on-change on-change-value-saturation
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}]
+
+ [:div.shade-selector
+ [:& color-bullet {:color {:color hex
+ :opacity alpha}}]
+ [:& slider-selector {:class "hue"
+ :max-value 360
+ :value hue
+ :on-change on-change-hue
:on-start-drag on-start-drag
- :on-finish-drag on-finish-drag}])]]))
+ :on-finish-drag on-finish-drag}]
+
+ (when (not disable-opacity)
+ [:& slider-selector {:class "opacity"
+ :max-value 1
+ :value alpha
+ :on-change on-change-opacity
+ :on-start-drag on-start-drag
+ :on-finish-drag on-finish-drag}])]])))
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/ramp.scss b/frontend/src/app/main/ui/workspace/colorpicker/ramp.scss
new file mode 100644
index 0000000000..dc788dbb86
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/colorpicker/ramp.scss
@@ -0,0 +1,46 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.value-saturation-selector {
+ background-color: rgba(var(--hue-rgb));
+ position: relative;
+ height: $s-140;
+ width: $s-256;
+ margin-top: $s-12;
+ margin-bottom: $s-6;
+ cursor: pointer;
+
+ .handler {
+ @extend .colorpicker-handler;
+ height: $s-16;
+ width: $s-16;
+ border: $s-2 solid var(--colorpicker-handlers-color);
+ }
+
+ &::before {
+ content: "";
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ background: linear-gradient(to right, #fff, rgba(255, 255, 255, 0));
+ }
+
+ &::after {
+ content: "";
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ background: linear-gradient(to top, #000, rgba(0, 0, 0, 0));
+ }
+}
+.shade-selector {
+ display: flex;
+ gap: $s-4;
+ height: $s-52;
+ cursor: pointer;
+}
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.cljs b/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.cljs
index 7b5af5bae6..ddf475744d 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.cljs
@@ -5,15 +5,19 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.colorpicker.slider-selector
+ (:require-macros [app.main.style :as stl])
(:require
+ [app.common.data.macros :as dm]
[app.common.math :as mth]
+ [app.main.ui.context :as ctx]
[app.util.dom :as dom]
[app.util.object :as obj]
[rumext.v2 :as mf]))
(mf/defc slider-selector
- [{:keys [value class min-value max-value vertical? reverse? on-change on-start-drag on-finish-drag]}]
- (let [min-value (or min-value 0)
+ [{:keys [value class min-value max-value vertical? reverse? on-change on-start-drag on-finish-drag type]}]
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ min-value (or min-value 0)
max-value (or max-value 1)
dragging? (mf/use-state false)
@@ -49,23 +53,49 @@
value (+ min-value (* unit-value (- max-value min-value)))]
(on-change value))))]
- [:div.slider-selector
- {:class (str (if vertical? "vertical " "") class)
- :on-pointer-down handle-start-drag
- :on-pointer-up handle-stop-drag
- :on-lost-pointer-capture handle-stop-drag
- :on-click calculate-pos
- :on-pointer-move #(when @dragging? (calculate-pos %))}
+ (if new-css-system
+ [:div {:class (stl/css-case :opacity-wrapper (= type :opacity))}
+ [:div {:class (dm/str class (stl/css-case :vertical vertical?
+ :slider-selector true
+ :hue (= type :hue)
+ :opacity (= type :opacity)
+ :value (= type :value)))
+ :on-pointer-down handle-start-drag
+ :on-pointer-up handle-stop-drag
+ :on-lost-pointer-capture handle-stop-drag
+ :on-click calculate-pos
+ :on-pointer-move #(when @dragging? (calculate-pos %))}
+ (let [value-percent (* (/ (- value min-value)
+ (- max-value min-value)) 100)
- (let [value-percent (* (/ (- value min-value)
- (- max-value min-value)) 100)
+ value-percent (if reverse?
+ (mth/abs (- value-percent 100))
+ value-percent)
+ value-percent-str (str value-percent "%")
- value-percent (if reverse?
- (mth/abs (- value-percent 100))
- value-percent)
- value-percent-str (str value-percent "%")
+ style-common #js {:pointerEvents "none"}
+ style-horizontal (obj/merge! #js {:left value-percent-str} style-common)
+ style-vertical (obj/merge! #js {:bottom value-percent-str} style-common)]
+ [:div {:class (stl/css :handler)
+ :style (if vertical? style-vertical style-horizontal)}])]]
- style-common #js {:pointerEvents "none"}
- style-horizontal (obj/merge! #js {:left value-percent-str} style-common)
- style-vertical (obj/merge! #js {:bottom value-percent-str} style-common)]
- [:div.handler {:style (if vertical? style-vertical style-horizontal)}])]))
+ [:div.slider-selector
+ {:class (str (if vertical? "vertical " "") class)
+ :on-pointer-down handle-start-drag
+ :on-pointer-up handle-stop-drag
+ :on-lost-pointer-capture handle-stop-drag
+ :on-click calculate-pos
+ :on-pointer-move #(when @dragging? (calculate-pos %))}
+
+ (let [value-percent (* (/ (- value min-value)
+ (- max-value min-value)) 100)
+
+ value-percent (if reverse?
+ (mth/abs (- value-percent 100))
+ value-percent)
+ value-percent-str (str value-percent "%")
+
+ style-common #js {:pointerEvents "none"}
+ style-horizontal (obj/merge! #js {:left value-percent-str} style-common)
+ style-vertical (obj/merge! #js {:bottom value-percent-str} style-common)]
+ [:div.handler {:style (if vertical? style-vertical style-horizontal)}])])))
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.scss b/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.scss
new file mode 100644
index 0000000000..65d2ae287b
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.scss
@@ -0,0 +1,117 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.slider-selector {
+ --gradient-direction: 90deg;
+ --background-repeat: left;
+
+ &.vertical {
+ --gradient-direction: 0deg;
+ --background-repeat: top;
+ }
+ position: relative;
+ align-self: center;
+ height: $s-24;
+ width: $s-200;
+ border: $s-2 solid var(--colorpicker-details-color);
+ border-radius: $br-6;
+ background: linear-gradient(
+ var(--gradient-direction),
+ rgba(var(--color), 0) 0%,
+ rgba(var(--color), 1) 100%
+ );
+ cursor: pointer;
+
+ &.vertical {
+ width: $s-24;
+ height: $s-200;
+ }
+
+ &.hue {
+ background: linear-gradient(
+ var(--gradient-direction),
+ #f00 0%,
+ #ff0 17%,
+ #0f0 33%,
+ #0ff 50%,
+ #00f 67%,
+ #f0f 83%,
+ #f00 100%
+ );
+ }
+
+ &.saturation {
+ background: linear-gradient(
+ var(--gradient-direction),
+ var(--saturation-grad-from) 0%,
+ var(--saturation-grad-to) 100%
+ );
+ }
+
+ &.opacity {
+ background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=")
+ var(--background-repeat) center;
+
+ &::after {
+ content: "";
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ background: linear-gradient(
+ var(--gradient-direction),
+ rgba(var(--color), 0) 0%,
+ rgba(var(--color), 1) 100%
+ );
+ }
+ }
+
+ &.value {
+ background: linear-gradient(var(--gradient-direction), #000 0%, #fff 100%);
+ }
+
+ .handler {
+ position: absolute;
+ left: 50%;
+ width: calc($s-8 + $s-2);
+ height: calc($s-24 + $s-1);
+ border-radius: $br-4;
+ z-index: $z-index-1;
+ transform: translate(-4px, -3px);
+ background-color: var(--colorpicker-handlers-color);
+ }
+
+ &.vertical .handler {
+ height: calc($s-8 + $s-2);
+ width: calc($s-24 + $s-1);
+ transform: translate(-12px, 5px);
+ }
+}
+
+.opacity-wrapper {
+ background-color: var(--colorpicker-handlers-color);
+ border-radius: $br-8;
+}
+
+.slider-selector.hue {
+ grid-area: hue;
+}
+
+.slider-selector.opacity {
+ grid-area: opacity;
+}
+
+.slider-selector.value {
+ background: linear-gradient(var(--gradient-direction), #000 0%, #fff 100%);
+}
+.slider-selector.saturation {
+ background: linear-gradient(
+ var(--gradient-direction),
+ var(--saturation-grad-from) 0%,
+ var(--saturation-grad-to) 100%
+ );
+}
diff --git a/frontend/src/app/main/ui/workspace/left_header.scss b/frontend/src/app/main/ui/workspace/left_header.scss
index cc1a5d275e..665b7c7795 100644
--- a/frontend/src/app/main/ui/workspace/left_header.scss
+++ b/frontend/src/app/main/ui/workspace/left_header.scss
@@ -83,9 +83,9 @@
}
.menu {
@extend .menu-dropdown;
- position: absolute;
top: $s-48;
left: calc(var(--width, $s-256) - $s-16);
+ width: $s-192;
margin: 0;
.menu-item {
@@ -125,9 +125,9 @@
}
.sub-menu {
@extend .menu-dropdown;
- position: absolute;
left: calc(var(--width, $s-256) + $s-180);
- min-width: 270px;
+ width: $s-192;
+ min-width: calc($s-272 - $s-2);
width: 110%;
.shortcut {
@extend .shortcut;
diff --git a/frontend/src/app/main/ui/workspace/right_header.scss b/frontend/src/app/main/ui/workspace/right_header.scss
index ccd1c804f8..b16d32f458 100644
--- a/frontend/src/app/main/ui/workspace/right_header.scss
+++ b/frontend/src/app/main/ui/workspace/right_header.scss
@@ -63,7 +63,6 @@
}
.dropdown {
@extend .menu-dropdown;
- position: absolute;
right: 0;
top: $s-48;
width: $s-280;
diff --git a/frontend/src/app/main/ui/workspace/sidebar.cljs b/frontend/src/app/main/ui/workspace/sidebar.cljs
index 653bb08e38..437993c685 100644
--- a/frontend/src/app/main/ui/workspace/sidebar.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar.cljs
@@ -94,7 +94,7 @@
:shortcuts? shortcuts?
:collapsable? true
:handle-collapse handle-collapse
- :klass :tab-spacing}
+ :class :tab-spacing}
[:& tab-element {:id :layers :title (tr "workspace.sidebar.layers")}
[:div {:class (stl/css :layers-tab)}
[:& sitemap {:layout layout}]
diff --git a/frontend/src/app/main/ui/workspace/sidebar.scss b/frontend/src/app/main/ui/workspace/sidebar.scss
index 5f18a54962..544083bf31 100644
--- a/frontend/src/app/main/ui/workspace/sidebar.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar.scss
@@ -20,10 +20,10 @@ $width-settings-bar-max: $s-500;
.resize-area {
position: absolute;
- right: -8px;
+ right: calc(-1 * $s-8);
z-index: $z-index-3;
width: $s-8;
- height: 100%;
+ height: calc(100vh - $s-52);
cursor: ew-resize;
}
.settings-bar-inside {
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs
index d5133270f1..d3a8194257 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs
@@ -652,7 +652,6 @@
:id "assets-group-component"
:option-handler on-group})
-
(when (and components-v2 (not multi-assets?))
{:option-name (tr "workspace.shape.menu.show-main")
:id "assets-show-main-component"
diff --git a/frontend/src/app/main/ui/workspace/sidebar/layers.scss b/frontend/src/app/main/ui/workspace/sidebar/layers.scss
index 7bc6f141dc..8af16fd149 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/layers.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/layers.scss
@@ -160,11 +160,12 @@
}
}
}
+
.filters-container {
@extend .menu-dropdown;
- position: absolute;
top: $s-44;
left: $s-12;
+ width: $s-192;
.filter-menu-item {
@include titleTipography;
display: flex;
@@ -201,16 +202,16 @@
.filter-menu-item-name-wrapper {
.filter-menu-item-icon {
svg {
- stroke: var(--menu-foreground-color-selected);
+ stroke: var(--menu-foreground-color);
}
}
.filter-menu-item-name {
- color: var(--menu-foreground-color-selected);
+ color: var(--menu-foreground-color);
}
}
.filter-menu-item-tick {
svg {
- stroke: var(--menu-foreground-color-selected);
+ stroke: var(--menu-foreground-color);
}
}
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options.cljs b/frontend/src/app/main/ui/workspace/sidebar/options.cljs
index 3dda831366..96668717d9 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options.cljs
@@ -98,7 +98,7 @@
:selected section
:collapsable? false
:content-class (stl/css :content-class)
- :klass (stl/css :tab-spacing)}
+ :class (stl/css :tab-spacing)}
[:& tab-element {:id :design
:title (tr "workspace.options.design")}
[:div {:class (stl/css :element-options)}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options.scss b/frontend/src/app/main/ui/workspace/sidebar/options.scss
index c2eebfa4e2..9bb5aa9902 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options.scss
@@ -22,6 +22,7 @@
overflow-y: auto;
overflow-x: hidden;
height: calc(100vh - $s-96);
+ scrollbar-gutter: stable;
}
.element-options {
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/common.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/common.cljs
index 00f081aeed..dbe756c224 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/common.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/common.cljs
@@ -5,21 +5,30 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.common
+ (:require-macros [app.main.style :as stl])
(:require
+ [app.common.data.macros :as dm]
+ [app.main.ui.context :as ctx]
[app.util.dom :as dom]
[rumext.v2 :as mf]))
-(mf/defc advanced-options [{:keys [visible? children]}]
- (let [ref (mf/use-ref nil)]
+(mf/defc advanced-options [{:keys [visible? class children]}]
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ ref (mf/use-ref nil)]
(mf/use-effect
(mf/deps visible?)
(fn []
(when-let [node (mf/ref-val ref)]
(when visible?
(dom/scroll-into-view-if-needed! node)))))
+ (if new-css-system
+ (when visible?
+ [:div {:class (dm/str class " " (stl/css :advanced-options-wrapper))
+ :ref ref}
+ children])
- (when visible?
- [:div.advanced-options-wrapper {:ref ref}
- [:div.advanced-options {}
- children]])))
+ (when visible?
+ [:div.advanced-options-wrapper {:ref ref}
+ [:div.advanced-options {}
+ children]]))))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/common.scss b/frontend/src/app/main/ui/workspace/sidebar/options/common.scss
new file mode 100644
index 0000000000..6bd6984180
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/common.scss
@@ -0,0 +1,13 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.advanced-options-wrapper {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/blur.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/blur.cljs
index 8b6eb78952..0919d573a5 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/blur.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/blur.cljs
@@ -5,10 +5,14 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.menus.blur
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.uuid :as uuid]
[app.main.data.workspace.changes :as dch]
[app.main.store :as st]
+ [app.main.ui.components.numeric-input :refer [numeric-input*]]
+ [app.main.ui.components.title-bar :refer [title-bar]]
+ [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.rows.input-row :refer [input-row]]
[app.util.i18n :as i18n :refer [tr]]
@@ -24,9 +28,26 @@
:hidden false}))
(mf/defc blur-menu [{:keys [ids type values]}]
- (let [blur (:blur values)
- has-value? (not (nil? blur))
- multiple? (= blur :multiple)
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ blur (:blur values)
+ has-value? (not (nil? blur))
+ multiple? (= blur :multiple)
+
+ state* (mf/use-state {:show-content true
+ :show-more-options false})
+
+ state (deref state*)
+
+ open? (:show-content state)
+ more-options? (:show-more-options state)
+
+
+ toggle-content
+ (mf/use-fn #(swap! state* update :show-content not))
+
+ toggle-more-options
+ (mf/use-fn #(swap! state* update :show-more-options not))
+
change!
(mf/use-callback
@@ -63,28 +84,74 @@
(fn []
(change! #(update-in % [:blur :hidden] not))))]
- [:div.element-set
- [:div.element-set-title
- [:span
- (case type
- :multiple (tr "workspace.options.blur-options.title.multiple")
- :group (tr "workspace.options.blur-options.title.group")
- (tr "workspace.options.blur-options.title"))]
+ (if new-css-system
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? true
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title (case type
+ :multiple (tr "workspace.options.blur-options.title.multiple")
+ :group (tr "workspace.options.blur-options.title.group")
+ (tr "workspace.options.blur-options.title"))
+ :class (stl/css :title-spacing-blur)}
- [:div.element-set-title-actions
- (when (and has-value? (not multiple?))
- [:div.add-page {:on-click handle-toggle-visibility} (if (:hidden blur) i/eye-closed i/eye)])
+ (when-not has-value?
+ [:button {:class (stl/css :add-blur)
+ :on-click handle-add} i/add-refactor])]]
- (if has-value?
- [:div.add-page {:on-click handle-delete} i/minus]
- [:div.add-page {:on-click handle-add} i/close])]]
+ (when (and open? has-value?)
+ [:div {:class (stl/css :element-set-content)}
+ [:div {:class (stl/css :first-row)}
+ [:div {:class (stl/css :blur-info)}
+ [:button {:class (stl/css-case :show-more true
+ :selected more-options?)
+ :on-click toggle-more-options}
+ i/menu-refactor]
+ [:span {:class (stl/css :label)}
+ (tr "workspace.options.blur-options.title")]]
+ [:div {:class (stl/css :actions)}
+ [:button {:class (stl/css :action-btn)
+ :on-click handle-toggle-visibility}
+ (if (:hidden blur)
+ i/hide-refactor
+ i/shown-refactor)]
+ [:button {:class (stl/css :action-btn)
+ :on-click handle-delete} i/remove-refactor]]]
+ (when more-options?
+ [:div {:class (stl/css :second-row)}
+ [:span {:class (stl/css :label)}
+ (tr "inspect.attributes.blur.value")]
+ [:> numeric-input*
+ {:className (stl/css :numeric-input)
+ :placeholder "--"
+ :min "0"
+ :on-change handle-change
+ :value (:value blur)}]])])]
- (cond
- has-value?
- [:div.element-set-content
- [:& input-row {:label "Value"
- :class "pixels"
- :min "0"
- :value (:value blur)
- :placeholder (tr "settings.multiple")
- :on-change handle-change}]])]))
+
+ [:div.element-set
+ [:div.element-set-title
+ [:span
+ (case type
+ :multiple (tr "workspace.options.blur-options.title.multiple")
+ :group (tr "workspace.options.blur-options.title.group")
+ (tr "workspace.options.blur-options.title"))]
+
+ [:div.element-set-title-actions
+ (when (and has-value? (not multiple?))
+ [:div.add-page {:on-click handle-toggle-visibility} (if (:hidden blur) i/eye-closed i/eye)])
+
+ (if has-value?
+ [:div.add-page {:on-click handle-delete} i/minus]
+ [:div.add-page {:on-click handle-add} i/close])]]
+
+ (cond
+ has-value?
+ [:div.element-set-content
+ [:& input-row {:label "Value"
+ :class "pixels"
+ :min "0"
+ :value (:value blur)
+ :placeholder (tr "settings.multiple")
+ :on-change handle-change}]])])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/blur.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/blur.scss
new file mode 100644
index 0000000000..f9960fa801
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/blur.scss
@@ -0,0 +1,85 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.element-set {
+ .element-title {
+ .add-blur {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ .element-set-content {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ margin-bottom: $s-4;
+ .first-row {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ width: 100%;
+ .blur-info {
+ display: flex;
+ align-items: center;
+ gap: $s-1;
+ flex-grow: 1;
+ border-radius: $br-8;
+ background-color: var(--input-details-color);
+ .show-more {
+ @extend .button-secondary;
+ height: $s-32;
+ width: $s-28;
+ border-radius: $br-8 0 0 $br-8;
+ svg {
+ @extend .button-icon;
+ }
+ &.selected {
+ background-color: var(--button-secondary-background-color-active);
+ color: var(--button-secondary-foreground-color-active);
+ svg {
+ stroke: var(--button-secondary-foreground-color-active);
+ }
+ }
+ }
+ .label {
+ @include tabTitleTipography;
+ flex-grow: 1;
+ display: flex;
+ align-items: center;
+ height: $s-32;
+ padding: 0 $s-8;
+ border-radius: 0 $br-8 $br-8 0;
+ background-color: var(--input-background-color);
+ }
+ }
+ .actions {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .action-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ }
+ .second-row {
+ @extend .input-element;
+ gap: $s-4;
+ width: $s-92;
+ padding-left: $s-8;
+ }
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs
index 87bc5af239..63a4d66237 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs
@@ -5,6 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.menus.color-selection
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
@@ -12,6 +13,8 @@
[app.main.data.workspace.colors :as dc]
[app.main.data.workspace.selection :as dws]
[app.main.store :as st]
+ [app.main.ui.components.title-bar :refer [title-bar]]
+ [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
[app.util.i18n :as i18n :refer [tr]]
@@ -151,8 +154,15 @@
(mf/defc color-selection-menu
{::mf/wrap [#(mf/memo' % (mf/check-props ["shapes"]))]}
[{:keys [shapes file-id shared-libs] :as props}]
- (let [{:keys [ grouped-colors library-colors colors]} (mf/with-memo [shapes file-id shared-libs]
- (prepare-colors shapes file-id shared-libs))
+ (let [{:keys [grouped-colors library-colors colors]} (mf/with-memo [shapes file-id shared-libs]
+ (prepare-colors shapes file-id shared-libs))
+ new-css-system (mf/use-ctx ctx/new-css-system)
+
+ state* (mf/use-state true)
+ open? (deref state*)
+
+ toggle-content (mf/use-fn #(swap! state* not))
+
expand-lib-color (mf/use-state false)
expand-color (mf/use-state false)
@@ -202,26 +212,72 @@
(mf/with-effect [grouped-colors]
(reset! grouped-colors* grouped-colors))
- [:div.element-set
- [:div.element-set-title
- [:span (tr "workspace.options.selection-color")]]
- [:div.element-set-content
- [:div.selected-colors
- (for [[index color] (d/enumerate (take 3 library-colors))]
- [:& color-row {:key (dm/str "library-color-" (:color color))
- :color color
- :index index
- :on-detach on-detach
- :select-only select-only
- :on-change #(on-change %1 color %2)
- :on-open on-open
- :on-close on-close}])
- (when (and (false? @expand-lib-color) (< 3 (count library-colors)))
- [:div.expand-colors {:on-click #(reset! expand-lib-color true)}
- [:span i/actions]
- [:span.text (tr "workspace.options.more-lib-colors")]])
- (when @expand-lib-color
- (for [[index color] (d/enumerate (drop 3 library-colors))]
+ (if new-css-system
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? true
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title (tr "workspace.options.selection-color")
+ :class (stl/css :title-spacing-selected-colors)}]]
+
+ (when open?
+ [:div {:class (stl/css :element-content)}
+ [:div {:class (stl/css :selected-color-group)}
+ (for [[index color] (d/enumerate (take 3 library-colors))]
+ [:& color-row {:key (dm/str "library-color-" (:color color))
+ :color color
+ :index index
+ :on-detach on-detach
+ :select-only select-only
+ :on-change #(on-change %1 color %2)
+ :on-open on-open
+ :on-close on-close}])
+ (when (and (false? @expand-lib-color) (< 3 (count library-colors)))
+ [:button {:class (stl/css :more-colors-btn)
+ :on-click #(reset! expand-lib-color true)}
+ (tr "workspace.options.more-lib-colors")])
+ (when @expand-lib-color
+ (for [[index color] (d/enumerate (drop 3 library-colors))]
+ [:& color-row {:key (dm/str "library-color-" (:color color))
+ :color color
+ :index index
+ :on-detach on-detach
+ :select-only select-only
+ :on-change #(on-change %1 color %2)
+ :on-open on-open
+ :on-close on-close}]))]
+ [:div {:class (stl/css :selected-color-group)}
+ (for [[index color] (d/enumerate (take 3 colors))]
+ [:& color-row {:key (dm/str "color-" index)
+ :color color
+ :index index
+ :select-only select-only
+ :on-change #(on-change %1 color %2)
+ :on-open on-open
+ :on-close on-close}])
+ (when (and (false? @expand-color) (< 3 (count colors)))
+ [:button {:class (stl/css :more-colors-btn)
+ :on-click #(reset! expand-color true)}
+ (tr "workspace.options.more-colors")])
+
+ (when @expand-color
+ (for [[index color] (d/enumerate (drop 3 colors))]
+ [:& color-row {:key (dm/str "color-" (:color color))
+ :color color
+ :index index
+ :select-only select-only
+ :on-change #(on-change %1 color %2)
+ :on-open on-open
+ :on-close on-close}]))]])]
+
+
+ [:div.element-set
+ [:div.element-set-title
+ [:span (tr "workspace.options.selection-color")]]
+ [:div.element-set-content
+ [:div.selected-colors
+ (for [[index color] (d/enumerate (take 3 library-colors))]
[:& color-row {:key (dm/str "library-color-" (:color color))
:color color
:index index
@@ -229,27 +285,41 @@
:select-only select-only
:on-change #(on-change %1 color %2)
:on-open on-open
- :on-close on-close}]))]
+ :on-close on-close}])
+ (when (and (false? @expand-lib-color) (< 3 (count library-colors)))
+ [:div.expand-colors {:on-click #(reset! expand-lib-color true)}
+ [:span i/actions]
+ [:span.text (tr "workspace.options.more-lib-colors")]])
+ (when @expand-lib-color
+ (for [[index color] (d/enumerate (drop 3 library-colors))]
+ [:& color-row {:key (dm/str "library-color-" (:color color))
+ :color color
+ :index index
+ :on-detach on-detach
+ :select-only select-only
+ :on-change #(on-change %1 color %2)
+ :on-open on-open
+ :on-close on-close}]))]
- [:div.selected-colors
- (for [[index color] (d/enumerate (take 3 colors))]
- [:& color-row {:key (dm/str "color-" index)
- :color color
- :index index
- :select-only select-only
- :on-change #(on-change %1 color %2)
- :on-open on-open
- :on-close on-close}])
- (when (and (false? @expand-color) (< 3 (count colors)))
- [:div.expand-colors {:on-click #(reset! expand-color true)}
- [:span i/actions]
- [:span.text (tr "workspace.options.more-colors")]])
- (when @expand-color
- (for [[index color] (d/enumerate (drop 3 colors))]
- [:& color-row {:key (dm/str "color-" (:color color))
+ [:div.selected-colors
+ (for [[index color] (d/enumerate (take 3 colors))]
+ [:& color-row {:key (dm/str "color-" index)
:color color
:index index
:select-only select-only
:on-change #(on-change %1 color %2)
:on-open on-open
- :on-close on-close}]))]]]))
+ :on-close on-close}])
+ (when (and (false? @expand-color) (< 3 (count colors)))
+ [:div.expand-colors {:on-click #(reset! expand-color true)}
+ [:span i/actions]
+ [:span.text (tr "workspace.options.more-colors")]])
+ (when @expand-color
+ (for [[index color] (d/enumerate (drop 3 colors))]
+ [:& color-row {:key (dm/str "color-" (:color color))
+ :color color
+ :index index
+ :select-only select-only
+ :on-change #(on-change %1 color %2)
+ :on-open on-open
+ :on-close on-close}]))]]])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.scss
new file mode 100644
index 0000000000..4301877b02
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.scss
@@ -0,0 +1,35 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.element-set {
+ .element-title {
+ .add-fill {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ .element-content {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ .selected-color-group {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ .more-colors-btn {
+ @extend .button-secondary;
+ @include tabTitleTipography;
+ height: $s-32;
+ }
+ }
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs
index 43bfa6b68e..bcb09fca49 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs
@@ -5,6 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.menus.component
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.pages.helpers :as cph]
[app.common.types.component :as ctk]
@@ -16,6 +17,8 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.context-menu :refer [context-menu]]
+ [app.main.ui.components.dropdown :refer [dropdown]]
+ [app.main.ui.components.title-bar :refer [title-bar]]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
@@ -143,7 +146,8 @@
(mf/defc component-menu
[{:keys [ids values shape] :as props}]
- (let [current-file-id (mf/use-ctx ctx/current-file-id)
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ current-file-id (mf/use-ctx ctx/current-file-id)
components-v2 (mf/use-ctx ctx/components-v2)
objects (deref refs/workspace-page-objects)
@@ -151,10 +155,16 @@
can-update-main? (or (not components-v2) touched?)
id (first ids)
- local (mf/use-state {:menu-open false})
+ state* (mf/use-state {:show-content true
+ :menu-open false})
+ state (deref state*)
+ open? (:show-content state)
+ menu-open? (:menu-open state)
+
+ toggle-content
+ (mf/use-fn #(swap! state* update :show-content not))
shape-name (:name shape)
-
component-id (:component-id values)
library-id (:component-file values)
show? (some? component-id)
@@ -165,6 +175,7 @@
lacks-annotation? (nil? (:annotation values))
local-component? (= library-id current-file-id)
+
workspace-data (deref refs/workspace-data)
workspace-libraries (deref refs/workspace-libraries)
component (if local-component?
@@ -174,17 +185,16 @@
lib-exists? (and (not local-component?)
(some? (get workspace-libraries library-id)))
-
on-menu-click
- (mf/use-callback
+ (mf/use-fn
(fn [event]
(dom/prevent-default event)
(dom/stop-propagation event)
- (swap! local assoc :menu-open true)))
+ (swap! state* update :menu-open not)))
on-menu-close
(mf/use-callback
- #(swap! local assoc :menu-open false))
+ #(swap! state* assoc :menu-open false))
do-detach-component
#(st/emit! (dwl/detach-component id))
@@ -217,59 +227,171 @@
do-create-annotation #(st/emit! (dw/set-annotations-id-for-create id))
do-navigate-component-file #(st/emit! (dwl/nav-to-component-file library-id))]
(when show?
- [:div.element-set
- [:div.element-set-title
- [:span (tr "workspace.options.component")]
- [:span (if main-instance?
- (tr "workspace.options.component.main")
- (tr "workspace.options.component.copy"))]
- ]
- [:div.element-set-content
- [:div.row-flex.component-row
- (if main-instance?
- i/component
- i/component-copy)
- [:div.component-name shape-name]
- [:div.row-actions
- {:on-click on-menu-click}
- i/actions
- ;; WARNING: this menu is the same as the shape context menu.
- ;; If you change it, you must change equally the file
- ;; app/main/ui/workspace/context_menu.cljs
- [:& context-menu {:on-close on-menu-close
- :show (:menu-open @local)
- :options
- (if main-component?
- [[(tr "workspace.shape.menu.show-in-assets") do-show-in-assets]
- (when (and components-v2 local-component? lacks-annotation?)
- [(tr "workspace.shape.menu.create-annotation") do-create-annotation])]
- (if local-component?
- (if is-dangling?
- [[(tr "workspace.shape.menu.detach-instance") do-detach-component]
- (when can-update-main?
- [(tr "workspace.shape.menu.reset-overrides") do-reset-component])
- (when components-v2
- [(tr "workspace.shape.menu.restore-main") do-restore-component])]
+ (if new-css-system
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? true
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title (tr "workspace.options.component")
+ :class (stl/css :title-spacing-component)}]]
- [[(tr "workspace.shape.menu.detach-instance") do-detach-component]
- (when can-update-main?
- [(tr "workspace.shape.menu.reset-overrides") do-reset-component])
- (when can-update-main?
- [(tr "workspace.shape.menu.update-main") do-update-component])
- [(tr "workspace.shape.menu.show-main") do-show-component]])
+ (when open?
+ [:div {:class (stl/css :element-content)}
+ [:div {:class (stl/css :component-wrapper)}
+ [:div {:class (stl/css :component-name-wrapper)}
+ [:span {:class (stl/css :component-icon)}
+ (if main-instance?
+ i/component-refactor
+ i/copy-refactor)]
- (if is-dangling?
- [[(tr "workspace.shape.menu.detach-instance") do-detach-component]
- (when can-update-main?
- [(tr "workspace.shape.menu.reset-overrides") do-reset-component])
- (when (and components-v2 lib-exists?)
- [(tr "workspace.shape.menu.restore-main") do-restore-component])]
- [[(tr "workspace.shape.menu.detach-instance") do-detach-component]
- (when can-update-main?
- [(tr "workspace.shape.menu.reset-overrides") do-reset-component])
- (when can-update-main?
- [(tr "workspace.shape.menu.update-main") do-update-remote-component])
- [(tr "workspace.shape.menu.go-main") do-navigate-component-file]])))}]]]
+ [:div {:class (stl/css :component-name)} shape-name]]
- (when components-v2
- [:& component-annotation {:id id :values values :shape shape :component component}])]])))
+ [:div {:class (stl/css :component-actions)}
+ [:button {:class (stl/css :menu-btn)
+ :on-click on-menu-click}
+ i/menu-refactor]
+
+ [:& dropdown {:show menu-open?
+ :on-close on-menu-close}
+ [:ul {:class (stl/css :custom-select-dropdown)}
+ (if main-component?
+ [:*
+ [:li {:class (stl/css :dropdown-element)
+ :on-click do-show-in-assets}
+ [:span {:class (stl/css :dropdown-label)}
+ (tr "workspace.shape.menu.show-in-assets")]]
+ (when (and components-v2 local-component? lacks-annotation?)
+ [:li {:class (stl/css :dropdown-element)
+ :on-click do-create-annotation}
+ [:span {:class (stl/css :dropdown-label)}
+ (tr "workspace.shape.menu.create-annotation")]])]
+
+ (if local-component?
+ (if is-dangling?
+ [:*
+ [:li {:class (stl/css :dropdown-element)
+ :on-click do-detach-component}
+ [:span {:class (stl/css :dropdown-label)}
+ (tr "workspace.shape.menu.detach-instance")]]
+ (when can-update-main?
+ [:li {:class (stl/css :dropdown-element)
+ :on-click do-reset-component}
+ [:span {:class (stl/css :dropdown-label)}
+ (tr "workspace.shape.menu.reset-overrides")]])
+ (when components-v2
+ [:li {:class (stl/css :dropdown-element)
+ :on-click do-restore-component}
+ [:span {:class (stl/css :dropdown-label)}
+ (tr "workspace.shape.menu.restore-main")]])]
+
+ [:*
+ [:li {:class (stl/css :dropdown-element)
+ :on-click do-detach-component}
+ [:span {:class (stl/css :dropdown-label)}
+ (tr "workspace.shape.menu.detach-instance")]]
+ (when can-update-main?
+ [:li {:class (stl/css :dropdown-element)
+ :on-click do-reset-component}
+ [:span {:class (stl/css :dropdown-label)}
+ (tr "workspace.shape.menu.reset-overrides")]]
+ [:li {:class (stl/css :dropdown-element)
+ :on-click do-update-component}
+ [:span {:class (stl/css :dropdown-label)}
+ (tr "workspace.shape.menu.update-main")]])
+ [:li {:class (stl/css :dropdown-element)
+ :on-click do-show-component}
+ [:span {:class (stl/css :dropdown-label)}
+ (tr "workspace.shape.menu.show-main")]]])
+ (if is-dangling?
+ [:*
+ [:li {:class (stl/css :dropdown-element)
+ :on-click do-detach-component}
+ [:span {:class (stl/css :dropdown-label)}
+ (tr "workspace.shape.menu.detach-instance")]]
+ (when can-update-main?
+ [:li {:class (stl/css :dropdown-element)
+ :on-click do-reset-component}
+ [:span {:class (stl/css :dropdown-label)}
+ (tr "workspace.shape.menu.reset-overrides")]])
+
+ (when (and components-v2 lib-exists?)
+ [:li {:class (stl/css :dropdown-element)
+ :on-click do-restore-component}
+ [:span {:class (stl/css :dropdown-label)}
+ (tr "workspace.shape.menu.restore-main")]])]
+ [:*
+ [:li {:class (stl/css :dropdown-element)
+ :on-click do-detach-component}
+ [:span {:class (stl/css :dropdown-label)}
+ (tr "workspace.shape.menu.detach-instance")]]
+ (when can-update-main?
+ [:li {:class (stl/css :dropdown-element)
+ :on-click do-reset-component}
+ [:span {:class (stl/css :dropdown-label)}
+ (tr "workspace.shape.menu.reset-overrides")]]
+ [:li {:class (stl/css :dropdown-element)
+ :on-click do-update-remote-component}
+ [:span {:class (stl/css :dropdown-label)}
+ (tr "workspace.shape.menu.update-main")]])
+ [:li {:class (stl/css :dropdown-element)
+ :on-click do-navigate-component-file}
+ [:span {:class (stl/css :dropdown-label)}
+ (tr "workspace.shape.menu.go-main")]]])))]]]]
+ (when components-v2
+ [:& component-annotation {:id id :values values :shape shape :component component}])])]
+
+ [:div.element-set
+ [:div.element-set-title
+ [:span (tr "workspace.options.component")]
+ [:span (if main-instance?
+ (tr "workspace.options.component.main")
+ (tr "workspace.options.component.copy"))]]
+ [:div.element-set-content
+ [:div.row-flex.component-row
+ (if main-instance?
+ i/component
+ i/component-copy)
+ [:div.component-name shape-name]
+ [:div.row-actions
+ {:on-click on-menu-click}
+ i/actions
+ ;; WARNING: this menu is the same as the shape context menu.
+ ;; If you change it, you must change equally the file
+ ;; app/main/ui/workspace/context_menu.cljs
+ [:& context-menu {:on-close on-menu-close
+ :show menu-open?
+ :options (if main-component?
+ [[(tr "workspace.shape.menu.show-in-assets") do-show-in-assets]
+ (when (and components-v2 local-component? lacks-annotation?)
+ [(tr "workspace.shape.menu.create-annotation") do-create-annotation])]
+ (if local-component?
+ (if is-dangling?
+ [[(tr "workspace.shape.menu.detach-instance") do-detach-component]
+ (when can-update-main?
+ [(tr "workspace.shape.menu.reset-overrides") do-reset-component])
+ (when components-v2
+ [(tr "workspace.shape.menu.restore-main") do-restore-component])]
+
+ [[(tr "workspace.shape.menu.detach-instance") do-detach-component]
+ (when can-update-main?
+ [(tr "workspace.shape.menu.reset-overrides") do-reset-component])
+ (when can-update-main?
+ [(tr "workspace.shape.menu.update-main") do-update-component])
+ [(tr "workspace.shape.menu.show-main") do-show-component]])
+
+ (if is-dangling?
+ [[(tr "workspace.shape.menu.detach-instance") do-detach-component]
+ (when can-update-main?
+ [(tr "workspace.shape.menu.reset-overrides") do-reset-component])
+ (when (and components-v2 lib-exists?)
+ [(tr "workspace.shape.menu.restore-main") do-restore-component])]
+ [[(tr "workspace.shape.menu.detach-instance") do-detach-component]
+ (when can-update-main?
+ [(tr "workspace.shape.menu.reset-overrides") do-reset-component])
+ (when can-update-main?
+ [(tr "workspace.shape.menu.update-main") do-update-remote-component])
+ [(tr "workspace.shape.menu.go-main") do-navigate-component-file]])))}]]]
+
+ (when components-v2
+ [:& component-annotation {:id id :values values :shape shape :component component}])]]))))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.scss
new file mode 100644
index 0000000000..5d74ad3444
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.scss
@@ -0,0 +1,59 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+.element-set {
+ .element-content {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ .component-wrapper {
+ display: flex;
+ gap: $s-4;
+ .component-name-wrapper {
+ @extend .asset-element;
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ flex-grow: 1;
+ .component-icon {
+ @include flexCenter;
+ height: $s-24;
+ width: $s-24;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
+ }
+ }
+ .component-name {
+ @include titleTipography;
+ flex-grow: 1;
+ }
+ }
+ .component-actions {
+ position: relative;
+
+ .menu-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ .custom-select-dropdown {
+ @extend .dropdown-wrapper;
+ right: 0;
+ left: unset;
+ width: $s-252;
+ .dropdown-element {
+ @extend .dropdown-element-base;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs
index 94ebe5c781..a61c6314a3 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs
@@ -5,6 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.menus.constraints
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.geom.rect :as grc]
@@ -13,6 +14,9 @@
[app.main.data.workspace.changes :as dch]
[app.main.refs :as refs]
[app.main.store :as st]
+ [app.main.ui.components.select :refer [select]]
+ [app.main.ui.components.title-bar :refer [title-bar]]
+ [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@@ -27,8 +31,15 @@
(mf/defc constraints-menu
[{:keys [ids values] :as props}]
- (let [old-shapes (deref (refs/objects-by-id ids))
- frames (map #(deref (refs/object-by-id (:frame-id %))) old-shapes)
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+
+ state* (mf/use-state true)
+ open? (deref state*)
+
+ toggle-content (mf/use-fn #(swap! state* not))
+
+ old-shapes (deref (refs/objects-by-id ids))
+ frames (map #(deref (refs/object-by-id (:frame-id %))) old-shapes)
shapes (as-> old-shapes $
(map gsh/translate-to-frame $ frames))
@@ -53,127 +64,261 @@
constraints-h (or (get values :constraints-h) (gsh/default-constraints-h values))
constraints-v (or (get values :constraints-v) (gsh/default-constraints-v values))
- on-constraint-button-clicked
- (mf/use-callback
- (mf/deps [ids values])
- (fn [button]
- (fn [_]
- (let [constraints-h (get values :constraints-h :scale)
- constraints-v (get values :constraints-v :scale)
- [constraint new-value]
- (case button
- :top (case constraints-v
- :top [:constraints-v :scale]
- :topbottom [:constraints-v :bottom]
- :bottom [:constraints-v :topbottom]
- [:constraints-v :top])
- :bottom (case constraints-v
- :bottom [:constraints-v :scale]
- :topbottom [:constraints-v :top]
- :top [:constraints-v :topbottom]
- [:constraints-v :bottom])
- :left (case constraints-h
- :left [:constraints-h :scale]
- :leftright [:constraints-h :right]
- :right [:constraints-h :leftright]
- [:constraints-h :left])
- :right (case constraints-h
- :right [:constraints-h :scale]
- :leftright [:constraints-h :left]
- :left [:constraints-h :leftright]
- [:constraints-h :right])
- :centerv (case constraints-v
- :center [:constraints-v :scale]
- [:constraints-v :center])
- :centerh (case constraints-h
- :center [:constraints-h :scale]
- [:constraints-h :center]))]
- (st/emit! (dch/update-shapes
- ids
- #(assoc % constraint new-value)))))))
+ on-constraint-button-clicked
+ (mf/use-fn
+ (mf/deps ids values)
+ (fn [event]
+ (let [button (-> (dom/get-current-target event)
+ (dom/get-data "value")
+ (keyword))
+ constraints-h (get values :constraints-h :scale)
+ constraints-v (get values :constraints-v :scale)
+
+ [constraint new-value]
+ (case button
+ :top (case constraints-v
+ :top [:constraints-v :scale]
+ :topbottom [:constraints-v :bottom]
+ :bottom [:constraints-v :topbottom]
+ [:constraints-v :top])
+ :bottom (case constraints-v
+ :bottom [:constraints-v :scale]
+ :topbottom [:constraints-v :top]
+ :top [:constraints-v :topbottom]
+ [:constraints-v :bottom])
+ :left (case constraints-h
+ :left [:constraints-h :scale]
+ :leftright [:constraints-h :right]
+ :right [:constraints-h :leftright]
+ [:constraints-h :left])
+ :right (case constraints-h
+ :right [:constraints-h :scale]
+ :leftright [:constraints-h :left]
+ :left [:constraints-h :leftright]
+ [:constraints-h :right])
+ :centerv (case constraints-v
+ :center [:constraints-v :scale]
+ [:constraints-v :center])
+ :centerh (case constraints-h
+ :center [:constraints-h :scale]
+ [:constraints-h :center])
+ nil ())]
+
+ (st/emit! (dch/update-shapes
+ ids
+ #(assoc % constraint new-value))))))
on-constraint-select-changed
- (mf/use-callback
- (mf/deps [ids values])
- (fn [constraint]
- (fn [event]
- (let [value (-> (dom/get-target-val event) (keyword))]
- (when-not (str/empty? value)
- (st/emit! (dch/update-shapes
- ids
- #(assoc % constraint value))))))))
+ (mf/use-fn
+ (mf/deps ids)
+ (fn [event]
+ (let [constraint (-> (dom/get-current-target event)
+ (dom/get-data "value")
+ (keyword))
+ value (-> (dom/get-target-val event) (keyword))]
+ (when-not (str/empty? value)
+ (st/emit! (dch/update-shapes
+ ids
+ #(assoc % constraint value)))))))
+
+ on-constraint-h-select-changed
+ (mf/use-fn
+ (mf/deps ids)
+ (fn [value]
+ (when-not (str/empty? value)
+ (st/emit! (dch/update-shapes
+ ids
+ #(assoc % :constraints-h (keyword value)))))))
+
+ on-constraint-v-select-changed
+ (mf/use-fn
+ (mf/deps ids)
+ (fn [value]
+ (when-not (str/empty? value)
+ (st/emit! (dch/update-shapes
+ ids
+ #(assoc % :constraints-v (keyword value)))))))
on-fixed-scroll-clicked
- (mf/use-callback
- (mf/deps [ids values])
+ (mf/use-fn
+ (mf/deps ids)
(fn [_]
- (st/emit! (dch/update-shapes ids #(update % :fixed-scroll not)))))]
+ (st/emit! (dch/update-shapes ids #(update % :fixed-scroll not)))))
- ;; CONSTRAINTS
- (when in-frame?
- [:div.element-set
- [:div.element-set-title
- [:span (tr "workspace.options.constraints")]]
+ options-h
+ (mf/with-memo [constraints-h]
+ (d/concat-vec
+ (when (= constraints-h :multiple)
+ [{:value "" :label (tr "settings.multiple")}])
+ [{:value "left" :label (tr "workspace.options.constraints.left")}
+ {:value "right" :label (tr "workspace.options.constraints.right")}
+ {:value "leftright" :label (tr "workspace.options.constraints.leftright")}
+ {:value "center" :label (tr "workspace.options.constraints.center")}
+ {:value "scale" :label (tr "workspace.options.constraints.scale")}]))
- [:div.element-set-content
- [:div.row-flex.align-top
+ options-v
+ (mf/with-memo [constraints-v]
+ (d/concat-vec
+ (when (= constraints-v :multiple)
+ [{:value "" :label (tr "settings.multiple")}])
+ [{:value "top" :label (tr "workspace.options.constraints.top")}
+ {:value "bottom" :label (tr "workspace.options.constraints.bottom")}
+ {:value "topbottom" :label (tr "workspace.options.constraints.topbottom")}
+ {:value "center" :label (tr "workspace.options.constraints.center")}
+ {:value "scale" :label (tr "workspace.options.constraints.scale")}]))]
- [:div.constraints-widget
- [:div.constraints-box]
- [:div.constraint-button.top
- {:class (dom/classnames :active (or (= constraints-v :top)
- (= constraints-v :topbottom)))
- :on-click (on-constraint-button-clicked :top)}]
- [:div.constraint-button.bottom
- {:class (dom/classnames :active (or (= constraints-v :bottom)
- (= constraints-v :topbottom)))
- :on-click (on-constraint-button-clicked :bottom)}]
- [:div.constraint-button.left
- {:class (dom/classnames :active (or (= constraints-h :left)
- (= constraints-h :leftright)))
- :on-click (on-constraint-button-clicked :left)}]
- [:div.constraint-button.right
- {:class (dom/classnames :active (or (= constraints-h :right)
- (= constraints-h :leftright)))
- :on-click (on-constraint-button-clicked :right)}]
- [:div.constraint-button.centerv
- {:class (dom/classnames :active (= constraints-v :center))
- :on-click (on-constraint-button-clicked :centerv)}]
- [:div.constraint-button.centerh
- {:class (dom/classnames :active (= constraints-h :center))
- :on-click (on-constraint-button-clicked :centerh)}]]
- [:div.constraints-form
- [:div.row-flex
- [:span.left-right i/full-screen]
- [:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :on-change (on-constraint-select-changed :constraints-h)
- :value (d/name constraints-h "scale")}
- (when (= constraints-h :multiple)
- [:option {:value ""} (tr "settings.multiple")])
- [:option {:value "left"} (tr "workspace.options.constraints.left")]
- [:option {:value "right"} (tr "workspace.options.constraints.right")]
- [:option {:value "leftright"} (tr "workspace.options.constraints.leftright")]
- [:option {:value "center"} (tr "workspace.options.constraints.center")]
- [:option {:value "scale"} (tr "workspace.options.constraints.scale")]]]
- [:div.row-flex
- [:span.top-bottom i/full-screen]
- [:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :on-change (on-constraint-select-changed :constraints-v)
- :value (d/name constraints-v "scale")}
- (when (= constraints-v :multiple)
- [:option {:value ""} (tr "settings.multiple")])
- [:option {:value "top"} (tr "workspace.options.constraints.top")]
- [:option {:value "bottom"} (tr "workspace.options.constraints.bottom")]
- [:option {:value "topbottom"} (tr "workspace.options.constraints.topbottom")]
- [:option {:value "center"} (tr "workspace.options.constraints.center")]
- [:option {:value "scale"} (tr "workspace.options.constraints.scale")]]]
- (when first-level?
- [:div.row-flex
- [:div.fix-when {:class (dom/classnames :active (:fixed-scroll values))
- :on-click on-fixed-scroll-clicked}
- (if (:fixed-scroll values)
- i/pin-fill
- i/pin)
- [:span (tr "workspace.options.constraints.fix-when-scrolling")]]])]]]])))
+ ;; CONSTRAINTS
+ (when in-frame?
+ (if new-css-system
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? true
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title (tr "workspace.options.constraints")}]]
+ (when open?
+ [:div {:class (stl/css :element-set-content)}
+ [:div {:class (stl/css :constraints-widget)}
+ [:div {:class (stl/css :constraints-top)}
+ [:button {:class (stl/css-case :constraint-btn true
+ :active (or (= constraints-v :top)
+ (= constraints-v :topbottom)))
+ :data-value :top
+ :on-click on-constraint-button-clicked}
+ [:span {:class (stl/css :resalted-area)}]]]
+ [:div {:class (stl/css :constraints-left)}
+ [:button {:class (stl/css-case :constraint-btn true
+ :constraint-btn-rotated true
+ :active (or (= constraints-h :left)
+ (= constraints-h :leftright)))
+ :data-value :left
+ :on-click on-constraint-button-clicked}
+ [:span {:class (stl/css :resalted-area)}]]]
+ [:div {:class (stl/css :constraints-center)}
+ [:button {:class (stl/css-case :constraint-btn true
+ :active (= constraints-h :center))
+ :data-value :centerh
+ :on-click on-constraint-button-clicked}
+ [:span {:class (stl/css :resalted-area)}]]
+ [:button {:class (stl/css-case :constraint-btn-special true
+ :constraint-btn-rotated true
+ :active (= constraints-v :center))
+ :data-value :centerv
+ :on-click on-constraint-button-clicked}
+ [:span {:class (stl/css :resalted-area)}]]]
+ [:div {:class (stl/css :constraints-right)}
+ [:button {:class (stl/css-case :constraint-btn true
+ :constraint-btn-rotated true
+ :active (or (= constraints-h :right)
+ (= constraints-h :leftright)))
+ :data-value :right
+ :on-click on-constraint-button-clicked}
+ [:span {:class (stl/css :resalted-area)}]]]
+ [:div {:class (stl/css :constraints-bottom)}
+ [:button {:class (stl/css-case :constraint-btn true
+ :active (or (= constraints-v :bottom)
+ (= constraints-v :topbottom)))
+ :data-value :bottom
+ :on-click on-constraint-button-clicked}
+ [:span {:class (stl/css :resalted-area)}]]]]
+ [:div {:class (stl/css :contraints-selects)}
+ [:div {:class (stl/css :horizontal-select)}
+ [:& select
+ {:default-value (d/name constraints-h "scale")
+ :options options-h
+ :on-change on-constraint-h-select-changed}]]
+ [:div {:class (stl/css :vertical-select)}
+ [:& select
+ {:default-value (d/name constraints-v "scale")
+ :options options-v
+ :on-change on-constraint-v-select-changed}]]
+ (when first-level?
+ [:div {:class (stl/css :checkbox)}
+
+ [:label {:for "fixed-on-scroll"
+ :class (stl/css-case :checked (:fixed-scroll values))}
+ [:span {:class (stl/css-case :check-mark true
+ :checked (:fixed-scroll values))}
+ (when (:fixed-scroll values)
+ i/status-tick-refactor)]
+ (tr "workspace.options.constraints.fix-when-scrolling")
+ [:input {:type "checkbox"
+ :id "fixed-on-scroll"
+ :checked (:fixed-scroll values)
+ :on-change on-fixed-scroll-clicked}]]])]])]
+
+
+ [:div.element-set
+ [:div.element-set-title
+ [:span (tr "workspace.options.constraints")]]
+
+ [:div.element-set-content
+ [:div.row-flex.align-top
+ [:div.constraints-widget
+ [:div.constraints-box]
+ [:div.constraint-button.top
+ {:class (dom/classnames :active (or (= constraints-v :top)
+ (= constraints-v :topbottom)))
+ :data-value :top
+ :on-click on-constraint-button-clicked}]
+ [:div.constraint-button.bottom
+ {:class (dom/classnames :active (or (= constraints-v :bottom)
+ (= constraints-v :topbottom)))
+ :data-value :bottom
+ :on-click on-constraint-button-clicked}]
+ [:div.constraint-button.left
+ {:class (dom/classnames :active (or (= constraints-h :left)
+ (= constraints-h :leftright)))
+ :data-value :left
+ :on-click on-constraint-button-clicked}]
+ [:div.constraint-button.right
+ {:class (dom/classnames :active (or (= constraints-h :right)
+ (= constraints-h :leftright)))
+ :data-value :right
+ :on-click on-constraint-button-clicked}]
+ [:div.constraint-button.centerv
+ {:class (dom/classnames :active (= constraints-v :center))
+ :data-value :centerv
+ :on-click on-constraint-button-clicked}]
+ [:div.constraint-button.centerh
+ {:class (dom/classnames :active (= constraints-h :center))
+ :data-value :centerh
+ :on-click on-constraint-button-clicked}]]
+
+ [:div.constraints-form
+ [:div.row-flex
+ [:span.left-right i/full-screen]
+ [:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
+ :data-value :constraints-h
+ :on-change on-constraint-select-changed
+ :value (d/name constraints-h "scale")}
+ (when (= constraints-h :multiple)
+ [:option {:value ""} (tr "settings.multiple")])
+ [:option {:value "left"} (tr "workspace.options.constraints.left")]
+ [:option {:value "right"} (tr "workspace.options.constraints.right")]
+ [:option {:value "leftright"} (tr "workspace.options.constraints.leftright")]
+ [:option {:value "center"} (tr "workspace.options.constraints.center")]
+ [:option {:value "scale"} (tr "workspace.options.constraints.scale")]]]
+ [:div.row-flex
+ [:span.top-bottom i/full-screen]
+ [:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
+ :data-value :constraints-v
+ :on-change on-constraint-select-changed
+ :value (d/name constraints-v "scale")}
+ (when (= constraints-v :multiple)
+ [:option {:value ""} (tr "settings.multiple")])
+ [:option {:value "top"} (tr "workspace.options.constraints.top")]
+ [:option {:value "bottom"} (tr "workspace.options.constraints.bottom")]
+ [:option {:value "topbottom"} (tr "workspace.options.constraints.topbottom")]
+ [:option {:value "center"} (tr "workspace.options.constraints.center")]
+ [:option {:value "scale"} (tr "workspace.options.constraints.scale")]]]
+ (when first-level?
+ [:div.row-flex
+ [:div.fix-when {:class (dom/classnames :active (:fixed-scroll values))
+ :on-click on-fixed-scroll-clicked}
+ (if (:fixed-scroll values)
+ i/pin-fill
+ i/pin)
+ [:span (tr "workspace.options.constraints.fix-when-scrolling")]]])]]]]))))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/constraints.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/constraints.scss
new file mode 100644
index 0000000000..c822e9129d
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/constraints.scss
@@ -0,0 +1,151 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.element-set {
+ .element-set-content {
+ display: flex;
+ gap: $s-4;
+ .constraints-widget {
+ background-color: var(--constraint-widget-background-color);
+ display: grid;
+ grid-template-columns: $s-24 $s-72 $s-24;
+ grid-template-rows: $s-24 $s-72 $s-24;
+ grid-template-areas:
+ "top top top"
+ "left center right"
+ "bottom bottom bottom";
+ height: $s-120;
+ width: $s-120;
+ border-radius: $br-8;
+ .constraints-top,
+ .constraints-left,
+ .constraints-center,
+ .constraints-right,
+ .constraints-bottom {
+ @include flexCenter;
+ grid-area: top;
+ .constraint-btn,
+ .constraint-btn-special,
+ .constraint-btn-rotated {
+ @include buttonStyle;
+ @include flexCenter;
+ width: 100%;
+ height: 100%;
+ .resalted-area {
+ width: $s-40;
+ height: $s-4;
+ border-radius: $br-8;
+ background-color: var(--button-constraint-background-color-rest);
+ padding: 0;
+ margin: 0;
+ }
+ &.active .resalted-area {
+ outline: $s-4 solid var(--button-constraint-border-color-hover);
+ background-color: var(--button-constraint-background-color-hover);
+ }
+ &:hover .resalted-area,
+ &:focus .resalted-area {
+ outline: $s-4 solid var(--button-constraint-border-color-hover);
+ background-color: var(--button-constraint-background-color-hover);
+ }
+ }
+ }
+ .constraints-left {
+ grid-area: left;
+ .constraint-btn-rotated {
+ height: $s-72;
+ width: $s-24;
+ .resalted-area {
+ height: $s-40;
+ width: $s-4;
+ }
+ }
+ }
+ .constraints-center {
+ grid-area: center;
+ position: relative;
+ background-color: var(--constraint-center-area-background-color);
+ border-radius: $br-8;
+ .constraint-btn {
+ width: $s-72;
+ height: $s-24;
+ .resalted-area {
+ width: $s-40;
+ height: $s-4;
+ }
+ }
+ .constraint-btn-special {
+ position: absolute;
+ height: $s-72;
+ width: $s-24;
+ .resalted-area {
+ height: $s-40;
+ width: $s-4;
+ }
+ }
+ }
+ .constraints-right {
+ grid-area: right;
+ .constraint-btn-rotated {
+ height: $s-72;
+ width: $s-24;
+ .resalted-area {
+ height: $s-40;
+ width: $s-4;
+ }
+ }
+ }
+ .constraints-bottom {
+ grid-area: bottom;
+ }
+ }
+ .contraints-selects {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+
+ .horizontal-select,
+ .vertical-select {
+ width: $s-124;
+ padding: 0;
+ }
+
+ .checkbox {
+ display: flex;
+ align-items: center;
+ margin-bottom: $s-8;
+ margin-top: $s-8;
+ padding-left: 0;
+ input {
+ margin: 0;
+ }
+ label {
+ @include titleTipography;
+ display: flex;
+ align-items: center;
+ gap: $s-2;
+ cursor: pointer;
+ .check-mark {
+ @include flexCenter;
+ width: $s-16;
+ height: $s-16;
+ border-radius: $br-6;
+ background-color: var(--input-background-color);
+ &.checked {
+ background-color: var(--input-border-color-active);
+ svg {
+ @extend .button-icon-small;
+ stroke: var(--input-details-color);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.cljs
index 9fe6cad425..66492c6e01 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.cljs
@@ -5,6 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.menus.exports
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.main.data.exports :as de]
@@ -12,6 +13,9 @@
[app.main.data.workspace.state-helpers :as wsh]
[app.main.refs :as refs]
[app.main.store :as st]
+ [app.main.ui.components.select :refer [select]]
+ [app.main.ui.components.title-bar :refer [title-bar]]
+ [app.main.ui.context :as ctx]
[app.main.ui.export]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
@@ -26,7 +30,13 @@
(mf/defc exports-menu
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "type" "page-id" "file-id"]))]}
[{:keys [ids type values page-id file-id] :as props}]
- (let [exports (:exports values [])
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ exports (:exports values [])
+
+ comp-state* (mf/use-state true)
+ open? (deref comp-state*)
+
+ toggle-content (mf/use-fn #(swap! comp-state* not))
state (mf/deref refs/export)
in-progress? (:in-progress state)
@@ -107,19 +117,23 @@
(mf/use-callback
(mf/deps ids)
(fn [index event]
- (let [target (dom/get-target event)
- value (dom/get-value target)
- value (d/parse-double value)]
+ (let [scale (if new-css-system
+ (d/parse-double event)
+ (-> event
+ (dom/get-target-val)
+ (d/parse-double)))]
(st/emit! (dch/update-shapes ids
(fn [shape]
- (assoc-in shape [:exports index :scale] value)))))))
+ (assoc-in shape [:exports index :scale] scale)))))))
on-suffix-change
(mf/use-callback
(mf/deps ids)
- (fn [index event]
- (let [target (dom/get-target event)
- value (dom/get-value target)]
+ (fn [event]
+ (let [value (dom/get-target-val event)
+ index (-> (dom/get-current-target event)
+ (dom/get-data "value")
+ (int))]
(st/emit! (dch/update-shapes ids
(fn [shape]
(assoc-in shape [:exports index :suffix] value)))))))
@@ -128,12 +142,14 @@
(mf/use-callback
(mf/deps ids)
(fn [index event]
- (let [target (dom/get-target event)
- value (dom/get-value target)
- value (keyword value)]
+ (let [type (if new-css-system
+ (keyword event)
+ (-> event
+ (dom/get-target-val)
+ (keyword)))]
(st/emit! (dch/update-shapes ids
(fn [shape]
- (assoc-in shape [:exports index :type] value)))))))
+ (assoc-in shape [:exports index :type] type)))))))
on-remove-all
(mf/use-callback
@@ -147,58 +163,135 @@
(fn [event]
(let [esc? (kbd/esc? event)]
(when esc?
- (dom/blur! (dom/get-target event))))))]
+ (dom/blur! (dom/get-target event))))))
- [:div.element-set.exports-options
- [:div.element-set-title
- [:span (tr (if (> (count ids) 1) "workspace.options.export-multiple" "workspace.options.export"))]
- (when (not (= :multiple exports))
- [:div.add-page {:on-click add-export} i/close])]
+ size-options [{:value "0.5" :label "0.5x"}
+ {:value "0.75" :label "0.75x"}
+ {:value "1" :label "1x"}
+ {:value "1.5" :label "1.5x"}
+ {:value "2" :label "2x"}
+ {:value "4" :label "4x"}
+ {:value "6" :label "6"}]
- (cond
- (= :multiple exports)
- [:div.element-set-options-group
- [:div.element-set-label (tr "settings.multiple")]
- [:div.element-set-actions
- [:div.element-set-actions-button {:on-click on-remove-all}
- i/minus]]]
+ format-options [{:value "png" :label "PNG"}
+ {:value "jpeg" :label "JPE"}
+ {:value "svg" :label "SVG"}
+ {:value "pdf" :label "PDF"}]]
- (seq exports)
- [:div.element-set-content
- (for [[index export] (d/enumerate exports)]
- [:div.element-set-options-group
- {:key index}
- (when (scale-enabled? export)
+ (if new-css-system
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? true
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title (tr (if (> (count ids) 1) "workspace.options.export-multiple" "workspace.options.export"))
+ :class (stl/css :title-spacing-export)}
+ [:button {:class (stl/css :add-export)
+ :on-click add-export} i/add-refactor]]]
+ (when open?
+ [:div {:class (stl/css :element-set-content)}
+
+ (cond
+ (= :multiple exports)
+ [:div {:class (stl/css :multiple-exports)}
+ [:div {:class (stl/css :label)} (tr "settings.multiple")]
+ [:div {:class (stl/css :actions)}
+ [:button {:class (stl/css :action-btn)
+ :on-click on-remove-all}
+ i/remove-refactor]]]
+
+ (seq exports)
+ [:*
+ (for [[index export] (d/enumerate exports)]
+ [:div {:class (stl/css :element-group)
+ :key index}
+ [:div {:class (stl/css :input-wrapper)}
+ [:div {:class (stl/css :format-select)}
+ [:& select
+ {:default-value (d/name (:type export))
+ :options format-options
+ :on-change (partial on-type-change index)}]]
+ (when (scale-enabled? export)
+ [:div {:class (stl/css :size-select)}
+ [:& select
+ {:default-value (str (:scale export))
+ :options size-options
+ :on-change (partial on-scale-change index)}]])
+ [:div {:class (stl/css :suffix-input)}
+ [:input {:class (stl/css :type-input)
+ :value (:suffix export)
+ :placeholder (tr "workspace.options.export.suffix")
+ :data-value index
+ :on-change on-suffix-change
+ :on-key-down manage-key-down}]]]
+
+ [:button {:class (stl/css :action-btn)
+ :on-click (partial delete-export index)}
+ i/remove-refactor]])])
+
+ (when (or (= :multiple exports) (seq exports))
+ [:button
+ {:on-click (when-not in-progress? on-download)
+ :class (stl/css-case
+ :export-btn true
+ :btn-disabled in-progress?)
+ :disabled in-progress?}
+ (if in-progress?
+ (tr "workspace.options.exporting-object")
+ (tr "workspace.options.export-object" (c (count shapes-with-exports))))])])]
+
+
+ [:div.element-set.exports-options
+ [:div.element-set-title
+ [:span (tr (if (> (count ids) 1) "workspace.options.export-multiple" "workspace.options.export"))]
+ (when (not (= :multiple exports))
+ [:div.add-page {:on-click add-export} i/close])]
+
+ (cond
+ (= :multiple exports)
+ [:div.element-set-options-group
+ [:div.element-set-label (tr "settings.multiple")]
+ [:div.element-set-actions
+ [:div.element-set-actions-button {:on-click on-remove-all}
+ i/minus]]]
+
+ (seq exports)
+ [:div.element-set-content
+ (for [[index export] (d/enumerate exports)]
+ [:div.element-set-options-group
+ {:key index}
+ (when (scale-enabled? export)
+ [:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
+ :on-change (partial on-scale-change index)
+ :value (:scale export)}
+ [:option {:value "0.5"} "0.5x"]
+ [:option {:value "0.75"} "0.75x"]
+ [:option {:value "1"} "1x"]
+ [:option {:value "1.5"} "1.5x"]
+ [:option {:value "2"} "2x"]
+ [:option {:value "4"} "4x"]
+ [:option {:value "6"} "6x"]])
+ [:input.input-text {:value (:suffix export)
+ :placeholder (tr "workspace.options.export.suffix")
+ :data-value index
+ :on-change on-suffix-change
+ :on-key-down manage-key-down}]
[:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :on-change (partial on-scale-change index)
- :value (:scale export)}
- [:option {:value "0.5"} "0.5x"]
- [:option {:value "0.75"} "0.75x"]
- [:option {:value "1"} "1x"]
- [:option {:value "1.5"} "1.5x"]
- [:option {:value "2"} "2x"]
- [:option {:value "4"} "4x"]
- [:option {:value "6"} "6x"]])
- [:input.input-text {:value (:suffix export)
- :placeholder (tr "workspace.options.export.suffix")
- :on-change (partial on-suffix-change index)
- :on-key-down manage-key-down}]
- [:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (d/name (:type export))
- :on-change (partial on-type-change index)}
- [:option {:value "png"} "PNG"]
- [:option {:value "jpeg"} "JPEG"]
- [:option {:value "svg"} "SVG"]
- [:option {:value "pdf"} "PDF"]]
- [:div.delete-icon {:on-click (partial delete-export index)}
- i/minus]])])
+ :value (d/name (:type export))
+ :on-change (partial on-type-change index)}
+ [:option {:value "png"} "PNG"]
+ [:option {:value "jpeg"} "JPEG"]
+ [:option {:value "svg"} "SVG"]
+ [:option {:value "pdf"} "PDF"]]
+ [:div.delete-icon {:on-click (partial delete-export index)}
+ i/minus]])])
- (when (or (= :multiple exports) (seq exports))
- [:div.btn-icon-dark.download-button
- {:on-click (when-not in-progress? on-download)
- :class (dom/classnames
- :btn-disabled in-progress?)
- :disabled in-progress?}
- (if in-progress?
- (tr "workspace.options.exporting-object")
- (tr "workspace.options.export-object" (c (count shapes-with-exports))))])]))
+ (when (or (= :multiple exports) (seq exports))
+ [:div.btn-icon-dark.download-button
+ {:on-click (when-not in-progress? on-download)
+ :class (dom/classnames
+ :btn-disabled in-progress?)
+ :disabled in-progress?}
+ (if in-progress?
+ (tr "workspace.options.exporting-object")
+ (tr "workspace.options.export-object" (c (count shapes-with-exports))))])])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.scss
new file mode 100644
index 0000000000..3c43629b87
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.scss
@@ -0,0 +1,85 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.element-set {
+ .element-title {
+ .add-export {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ .element-set-content {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ margin-bottom: $s-4;
+ .multiple-exports {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .label {
+ @extend .mixed-bar;
+ }
+ .actions {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .action-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ }
+ .element-group {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .input-wrapper {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .format-select {
+ width: $s-60;
+ padding: 0;
+ }
+ .size-select {
+ width: $s-60;
+ padding: 0;
+ }
+ .suffix-input {
+ @extend .input-element;
+ min-width: $s-92;
+ padding: 0 $s-8;
+ flex-grow: 1;
+ }
+ }
+ .action-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ .export-btn {
+ @extend .button-secondary;
+ @include tabTitleTipography;
+ height: $s-32;
+ width: $s-252;
+ }
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.cljs
index 94631c9d4c..cedfbaa1bf 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.cljs
@@ -5,12 +5,15 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.menus.fill
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.colors :as clr]
[app.common.data :as d]
[app.common.types.shape.attrs :refer [default-color]]
[app.main.data.workspace.colors :as dc]
[app.main.store :as st]
+ [app.main.ui.components.title-bar :refer [title-bar]]
+ [app.main.ui.context :as ctx]
[app.main.ui.hooks :as h]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
@@ -41,11 +44,17 @@
(mf/defc fill-menu
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values"]))]}
[{:keys [ids type values disable-remove?] :as props}]
- (let [label (case type
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ label (case type
:multiple (tr "workspace.options.selection-fill")
:group (tr "workspace.options.group-fill")
(tr "workspace.options.fill"))
+ state* (mf/use-state true)
+ open? (deref state*)
+
+ toggle-content (mf/use-fn #(swap! state* not))
+
;; Excluding nil values
values (d/without-nils values)
@@ -103,20 +112,81 @@
disable-drag (mf/use-state false)
on-focus (fn [_]
- (reset! disable-drag true))
+ (reset! disable-drag true))
on-blur (fn [_]
(reset! disable-drag false))]
(mf/use-layout-effect
- (mf/deps hide-fill-on-export?)
- #(let [checkbox (mf/ref-val checkbox-ref)]
- (when checkbox
+ (mf/deps hide-fill-on-export?)
+ #(let [checkbox (mf/ref-val checkbox-ref)]
+ (when checkbox
;; Note that the "indeterminate" attribute only may be set by code, not as a static attribute.
;; See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#attr-indeterminate
- (if (= hide-fill-on-export? :multiple)
- (dom/set-attribute! checkbox "indeterminate" true)
- (dom/remove-attribute! checkbox "indeterminate")))))
+ (if (= hide-fill-on-export? :multiple)
+ (dom/set-attribute! checkbox "indeterminate" true)
+ (dom/remove-attribute! checkbox "indeterminate")))))
+
+ (if new-css-system
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? true
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title label
+ :class (stl/css :title-spacing-fill)}
+
+ (when (and (not disable-remove?) (not (= :multiple (:fills values))))
+ [:button {:class (stl/css :add-fill)
+ :on-click on-add} i/add-refactor])]]
+
+ (when open?
+ [:div {:class (stl/css :element-content)}
+ (cond
+ (= :multiple (:fills values))
+ [:div {:class (stl/css :element-set-options-group)}
+ [:div {:class (stl/css :group-label)}
+ (tr "settings.multiple")]
+ [:button {:on-click on-remove-all
+ :class (stl/css :remove-btn)}
+ i/remove-refactor]]
+
+ (seq (:fills values))
+ [:& h/sortable-container {}
+ (for [[index value] (d/enumerate (:fills values []))]
+ [:& color-row {:color {:color (:fill-color value)
+ :opacity (:fill-opacity value)
+ :id (:fill-color-ref-id value)
+ :file-id (:fill-color-ref-file value)
+ :gradient (:fill-color-gradient value)}
+ :key index
+ :index index
+ :title (tr "workspace.options.fill")
+ :on-change (on-change index)
+ :on-reorder (on-reorder index)
+ :on-detach (on-detach index)
+ :on-remove (on-remove index)
+ :disable-drag disable-drag
+ :on-focus on-focus
+ :select-on-focus (not @disable-drag)
+ :on-blur on-blur}])])
+
+ (when (or (= type :frame)
+ (and (= type :multiple) (some? (:hide-fill-on-export values))))
+ [:div {:class (stl/css :checkbox)}
+
+ [:label {:for "show-fill-on-export"
+ :class (stl/css-case :checked (not hide-fill-on-export?))}
+ [:span {:class (stl/css-case :check-mark true
+ :checked (not hide-fill-on-export?))}
+ (when(not hide-fill-on-export?)
+ i/status-tick-refactor)]
+ (tr "workspace.options.show-fill-on-export")
+ [:input {:type "checkbox"
+ :id "show-fill-on-export"
+ :ref checkbox-ref
+ :checked (not hide-fill-on-export?)
+ :on-change on-change-show-fill-on-export}]]])])]
[:div.element-set
[:div.element-set-title
@@ -164,4 +234,4 @@
:on-change on-change-show-fill-on-export}]
[:label {:for "show-fill-on-export"}
- (tr "workspace.options.show-fill-on-export")]])]]))
+ (tr "workspace.options.show-fill-on-export")]])]])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.scss
new file mode 100644
index 0000000000..477343ed7c
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.scss
@@ -0,0 +1,72 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.element-set {
+ .element-title {
+ .add-fill {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ .element-content {
+ display: flex;
+ flex-direction: column;
+ gap: $s-12;
+ .element-set-options-group {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .group-label {
+ @extend .mixed-bar;
+ }
+ .remove-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ .checkbox {
+ display: flex;
+ align-items: center;
+ margin-bottom: $s-8;
+ margin-top: calc(-1 * $s-4);
+ padding-left: $s-8;
+ input {
+ margin: 0;
+ }
+ label {
+ @include titleTipography;
+ display: flex;
+ align-items: center;
+ gap: $s-6;
+ cursor: pointer;
+ .check-mark {
+ @include flexCenter;
+ width: $s-16;
+ height: $s-16;
+ border-radius: $br-6;
+ background-color: var(--input-background-color);
+ &.checked {
+ background-color: var(--input-border-color-active);
+ svg {
+ @extend .button-icon-small;
+ stroke: var(--input-details-color);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs
index 654244c60f..b1dc4cd9f8 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs
@@ -5,6 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.menus.frame-grid
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.geom.grid :as gg]
[app.main.data.workspace.grid :as dw]
@@ -13,6 +14,8 @@
[app.main.ui.components.editable-select :refer [editable-select]]
[app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.components.select :refer [select]]
+ [app.main.ui.components.title-bar :refer [title-bar]]
+ [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.common :refer [advanced-options]]
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
@@ -32,17 +35,28 @@
(mf/defc grid-options
{::mf/wrap [mf/memo]}
[{:keys [shape-id index grid frame-width frame-height default-grid-params]}]
- (let [on-change (mf/use-fn (mf/deps shape-id index) #(st/emit! (dw/set-frame-grid shape-id index %)))
- on-remove (mf/use-fn (mf/deps shape-id index) #(st/emit! (dw/remove-frame-grid shape-id index)))
- on-save-default (mf/use-fn #(st/emit! (dw/set-default-grid (:type %) (:params %))))
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ on-change (mf/use-fn (mf/deps shape-id index) #(st/emit! (dw/set-frame-grid shape-id index %)))
+ on-remove (mf/use-fn (mf/deps shape-id index) #(st/emit! (dw/remove-frame-grid shape-id index)))
+ on-save-default (mf/use-fn #(st/emit! (dw/set-default-grid (:type %) (:params %))))
- size-options (mf/use-memo get-size-options)
- state (mf/use-state {:show-advanced-options false})
+ size-options (mf/use-memo get-size-options)
+ state* (mf/use-state {:show-advanced-options false
+ :show-more-options false})
+ state (deref state*)
+
+ open? (:show-advanced-options state)
+ show-more-options? (:show-more-options state)
+
+ is-hidden? (not (:display grid))
{:keys [type display params]} grid
toggle-advanced-options
- (mf/use-fn #(swap! state update :show-advanced-options not))
+ (mf/use-fn #(swap! state* update :show-advanced-options not))
+
+ toggle-more-options
+ (mf/use-fn #(swap! state* update :show-more-options not))
handle-toggle-visibility
(mf/use-fn
@@ -119,146 +133,314 @@
(mf/use-fn (mf/deps grid) #(on-save-default grid))
is-default (= (->> grid :params)
- (->> grid :type default-grid-params))
+ (->> grid :type default-grid-params))]
- open? (:show-advanced-options @state)]
+ (if new-css-system
+ [:div {:class (stl/css :grid-option)}
+ [:div {:class (stl/css :grid-title)}
+ [:div {:class (stl/css-case :option-row true
+ :hidden is-hidden?)}
+ [:button {:class (stl/css-case :show-options true
+ :selected open?)
+ :on-click toggle-advanced-options}
+ i/menu-refactor]
+ [:div {:class (stl/css :type-select-wrapper)}
+ [:& select
+ {:class (stl/css :grid-type-select)
+ :default-value type
+ :options [{:value :square :label (tr "workspace.options.grid.square")}
+ {:value :column :label (tr "workspace.options.grid.column")}
+ {:value :row :label (tr "workspace.options.grid.row")}]
+ :on-change handle-change-type}]]
+ (if (= type :square)
+ [:div {:class (stl/css :grid-size)
+ :title (tr "workspace.options.size")}
+ [:> numeric-input* {:min 0.01
+ :value (or (:size params) "")
+ :no-validate true
+ :className (stl/css :numeric-input)
+ :on-change (handle-change :params :size)}]]
- [:div.grid-option
- [:div.grid-option-main {:style {:display (when open? "none")}}
- [:button.custom-button {:class (when open? "is-active")
- :on-click toggle-advanced-options} i/actions]
+ [:div {:class (stl/css :editable-select-wrapper)}
+ [:& editable-select {:value (:size params)
+ :type "number"
+ :class (stl/css :column-select)
+ :input-class (stl/css :numeric-input)
+ :min 1
+ :options size-options
+ :placeholder "Auto"
+ :on-change handle-change-size}]])]
- [:& select
- {:class "flex-grow"
- :default-value type
- :options [{:value :square :label (tr "workspace.options.grid.square")}
- {:value :column :label (tr "workspace.options.grid.column")}
- {:value :row :label (tr "workspace.options.grid.row")}]
- :on-change handle-change-type}]
+ [:div {:class (stl/css :actions)}
+ [:button {:class (stl/css :action-btn)
+ :on-click handle-toggle-visibility}
+ (if display i/shown-refactor i/hide-refactor)]
+ [:button {:class (stl/css :action-btn)
+ :on-click on-remove}
+ i/remove-refactor]]]
- (if (= type :square)
- [:div.input-element.pixels {:title (tr "workspace.options.size")}
- [:> numeric-input* {:min 0.01
- :value (or (:size params) "")
- :no-validate true
- :on-change (handle-change :params :size)}]]
+ [:& advanced-options {:class (stl/css :grid-advanced-options)
+ :visible? open?
+ :on-close toggle-advanced-options}
+ ;; square
+ (when (= :square type)
+ [:div {:class (stl/css :square-row)}
+ [:div {:class (stl/css :advanced-row)}
+ [:& color-row {:color (:color params)
+ :title (tr "workspace.options.grid.params.color")
+ :disable-gradient true
+ :on-change handle-change-color
+ :on-detach handle-detach-color}]
+ [:button {:class (stl/css :show-more-options)
+ :on-click toggle-more-options}
+ i/menu-refactor]]
+ (when show-more-options?
+ [:div {:class (stl/css :second-row)}
+ [:button {:class (stl/css-case :btn-options true
+ :disabled is-default)
+ :disabled is-default
+ :on-click handle-use-default}
+ [:span (tr "workspace.options.grid.params.use-default")]]
+ [:button {:class (stl/css-case :btn-options true
+ :disabled is-default)
+ :disabled is-default
+ :on-click handle-set-as-default}
+ [:span (tr "workspace.options.grid.params.set-default")]]])])
- [:& editable-select {:value (:size params)
- :type "number"
- :class "input-option"
- :min 1
- :options size-options
- :placeholder "Auto"
- :on-change handle-change-size}])
+ (when (or (= :column type) (= :row type))
+ [:div {:class (stl/css :column-row)}
+ [:div {:class (stl/css :advanced-row)}
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
+ :default-value (:type params)
+ :class (stl/css :orientation)
+ :options [{:value :stretch :label (tr "workspace.options.grid.params.type.stretch")}
+ {:value :left :label (if (= type :row)
+ (tr "workspace.options.grid.params.type.top")
+ (tr "workspace.options.grid.params.type.left"))}
+ {:value :center :label (tr "workspace.options.grid.params.type.center")}
+ {:value :right :label (if (= type :row)
+ (tr "workspace.options.grid.params.type.bottom")
+ (tr "workspace.options.grid.params.type.right"))}]
+ :on-change (handle-change :params :type)}]]
- [:div.grid-option-main-actions
- [:button.custom-button {:on-click handle-toggle-visibility} (if display i/eye i/eye-closed)]
- [:button.custom-button {:on-click on-remove} i/minus]]]
+ [:div {:class (stl/css :color-wrapper)}
+ [:& color-row {:color (:color params)
+ :title (tr "workspace.options.grid.params.color")
+ :disable-gradient true
+ :on-change handle-change-color
+ :on-detach handle-detach-color}]]]
- [:& advanced-options {:visible? open? :on-close toggle-advanced-options}
- [:button.custom-button {:on-click toggle-advanced-options} i/actions]
- (when (= :square type)
- [:& input-row {:label (tr "workspace.options.grid.params.size")
- :class "pixels"
- :min 0.01
- :value (:size params)
- :on-change (handle-change :params :size)}])
+ [:div {:class (stl/css :advanced-row)}
+ [:div {:class (stl/css :height)
+ :title (if (= :row type)
+ (tr "workspace.options.grid.params.height")
+ (tr "workspace.options.grid.params.width"))}
+ [:span {:class (stl/css :icon-text)}
+ (if (= :row type)
+ "H"
+ "W")]
+ [:> numeric-input* {:placeholder "Auto"
+ :on-change handle-change-item-length
+ :nillable true
+ :className (stl/css :numeric-input)
+ :value (or (:item-length params) "")}]]
- (when (= :row type)
- [:& input-row {:label (tr "workspace.options.grid.params.rows")
- :type :editable-select
- :options size-options
- :value (:size params)
- :min 1
- :placeholder "Auto"
- :on-change handle-change-size}])
+ [:div {:class (stl/css :gutter)
+ :title (tr "workspace.options.grid.params.gutter")}
+ [:span {:class (stl/css-case :icon true
+ :rotated (= type :row))} i/gap-horizontal-refactor]
+ [:> numeric-input* {:placeholder "0"
+ :on-change (handle-change :params :gutter)
+ :nillable true
+ :className (stl/css :numeric-input)
+ :value (or (:gutter params) 0)}]]
- (when (= :column type)
- [:& input-row {:label (tr "workspace.options.grid.params.columns")
- :type :editable-select
- :options size-options
- :value (:size params)
- :min 1
- :placeholder "Auto"
- :on-change handle-change-size}])
+ [:div {:class (stl/css :margin)
+ :title (tr "workspace.options.grid.params.margin")}
+ [:span {:class (stl/css-case :icon true
+ :rotated (= type :column))} i/grid-margin-refactor]
+ [:> numeric-input* {:placeholder "0"
+ :on-change (handle-change :params :margin)
+ :nillable true
+ :className (stl/css :numeric-input)
+ :value (or (:margin params) 0)}]]
- (when (#{:row :column} type)
- [:& input-row {:label (tr "workspace.options.grid.params.type")
- :type :select
- :options [{:value :stretch :label (tr "workspace.options.grid.params.type.stretch")}
- {:value :left :label (if (= type :row)
- (tr "workspace.options.grid.params.type.top")
- (tr "workspace.options.grid.params.type.left"))}
- {:value :center :label (tr "workspace.options.grid.params.type.center")}
- {:value :right :label (if (= type :row)
- (tr "workspace.options.grid.params.type.bottom")
- (tr "workspace.options.grid.params.type.right"))}]
- :value (:type params)
- :on-change (handle-change :params :type)}])
+ [:button {:class (stl/css :show-more-options)
+ :on-click toggle-more-options}
+ i/menu-refactor]
+ (when show-more-options?
+ [:div {:class (stl/css :more-options)}
+ [:button {:disabled is-default
+ :class (stl/css :option-btn)
+ :on-click handle-use-default} (tr "workspace.options.grid.params.use-default")]
+ [:button {:disabled is-default
+ :class (stl/css :option-btn)
+ :on-click handle-set-as-default} (tr "workspace.options.grid.params.set-default")]])]])]]
- (when (#{:row :column} type)
- [:& input-row-v2
- {:class "pixels"
- :label (if (= :row type)
- (tr "workspace.options.grid.params.height")
- (tr "workspace.options.grid.params.width"))}
- [:> numeric-input*
- {:placeholder "Auto"
- :value (or (:item-length params) "")
- :nillable true
- :on-change handle-change-item-length}]])
+ [:div.grid-option
+ [:div.grid-option-main {:style {:display (when open? "none")}}
+ [:button.custom-button {:class (when open? "is-active")
+ :on-click toggle-advanced-options} i/actions]
+ [:& select
+ {:class "flex-grow"
+ :default-value type
+ :options [{:value :square :label (tr "workspace.options.grid.square")}
+ {:value :column :label (tr "workspace.options.grid.column")}
+ {:value :row :label (tr "workspace.options.grid.row")}]
+ :on-change handle-change-type}]
- (when (#{:row :column} type)
- [:*
- [:& input-row {:label (tr "workspace.options.grid.params.gutter")
- :class "pixels"
- :value (:gutter params)
- :min 0
- :nillable true
- :default 0
- :placeholder "0"
- :on-change (handle-change :params :gutter)}]
- [:& input-row {:label (tr "workspace.options.grid.params.margin")
- :class "pixels"
- :min 0
- :nillable true
- :default 0
- :placeholder "0"
- :value (:margin params)
- :on-change (handle-change :params :margin)}]])
+ (if (= type :square)
+ [:div.input-element.pixels {:title (tr "workspace.options.size")}
+ [:> numeric-input* {:min 0.01
+ :value (or (:size params) "")
+ :no-validate true
+ :on-change (handle-change :params :size)}]]
- [:& color-row {:color (:color params)
- :title (tr "workspace.options.grid.params.color")
- :disable-gradient true
- :on-change handle-change-color
- :on-detach handle-detach-color}]
- [:div.row-flex
- [:button.btn-options {:disabled is-default
- :on-click handle-use-default} (tr "workspace.options.grid.params.use-default")]
- [:button.btn-options {:disabled is-default
- :on-click handle-set-as-default} (tr "workspace.options.grid.params.set-default")]]]]))
+ [:& editable-select {:value (:size params)
+ :type "number"
+ :class "input-option"
+ :min 1
+ :options size-options
+ :placeholder "Auto"
+ :on-change handle-change-size}])
+
+ [:div.grid-option-main-actions
+ [:button.custom-button {:on-click handle-toggle-visibility} (if display i/eye i/eye-closed)]
+ [:button.custom-button {:on-click on-remove} i/minus]]]
+
+ [:& advanced-options {:visible? open? :on-close toggle-advanced-options}
+ [:button.custom-button {:on-click toggle-advanced-options} i/actions]
+ (when (= :square type)
+ [:& input-row {:label (tr "workspace.options.grid.params.size")
+ :class "pixels"
+ :min 0.01
+ :value (:size params)
+ :on-change (handle-change :params :size)}])
+
+ (when (= :row type)
+ [:& input-row {:label (tr "workspace.options.grid.params.rows")
+ :type :editable-select
+ :options size-options
+ :value (:size params)
+ :min 1
+ :placeholder "Auto"
+ :on-change handle-change-size}])
+
+ (when (= :column type)
+ [:& input-row {:label (tr "workspace.options.grid.params.columns")
+ :type :editable-select
+ :options size-options
+ :value (:size params)
+ :min 1
+ :placeholder "Auto"
+ :on-change handle-change-size}])
+
+ (when (#{:row :column} type)
+ [:& input-row {:label (tr "workspace.options.grid.params.type")
+ :type :select
+ :options [{:value :stretch :label (tr "workspace.options.grid.params.type.stretch")}
+ {:value :left :label (if (= type :row)
+ (tr "workspace.options.grid.params.type.top")
+ (tr "workspace.options.grid.params.type.left"))}
+ {:value :center :label (tr "workspace.options.grid.params.type.center")}
+ {:value :right :label (if (= type :row)
+ (tr "workspace.options.grid.params.type.bottom")
+ (tr "workspace.options.grid.params.type.right"))}]
+ :value (:type params)
+ :on-change (handle-change :params :type)}])
+
+ (when (#{:row :column} type)
+ [:& input-row-v2
+ {:class "pixels"
+ :label (if (= :row type)
+ (tr "workspace.options.grid.params.height")
+ (tr "workspace.options.grid.params.width"))}
+ [:> numeric-input*
+ {:placeholder "Auto"
+ :value (or (:item-length params) "")
+ :nillable true
+ :on-change handle-change-item-length}]])
+
+ (when (#{:row :column} type)
+ [:*
+ [:& input-row {:label (tr "workspace.options.grid.params.gutter")
+ :class "pixels"
+ :value (:gutter params)
+ :min 0
+ :nillable true
+ :default 0
+ :placeholder "0"
+ :on-change (handle-change :params :gutter)}]
+ [:& input-row {:label (tr "workspace.options.grid.params.margin")
+ :class "pixels"
+ :min 0
+ :nillable true
+ :default 0
+ :placeholder "0"
+ :value (:margin params)
+ :on-change (handle-change :params :margin)}]])
+
+ [:& color-row {:color (:color params)
+ :title (tr "workspace.options.grid.params.color")
+ :disable-gradient true
+ :on-change handle-change-color
+ :on-detach handle-detach-color}]
+ [:div.row-flex
+ [:button.btn-options {:disabled is-default
+ :on-click handle-use-default} (tr "workspace.options.grid.params.use-default")]
+ [:button.btn-options {:disabled is-default
+ :on-click handle-set-as-default} (tr "workspace.options.grid.params.set-default")]]]])))
(mf/defc frame-grid
[{:keys [shape]}]
- (let [id (:id shape)
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ state* (mf/use-state true)
+ open? (deref state*)
+
+ toggle-content (mf/use-fn #(swap! state* not))
+ id (:id shape)
saved-grids (mf/deref workspace-saved-grids)
default-grid-params (mf/use-memo (mf/deps saved-grids) #(merge dw/default-grid-params saved-grids))
handle-create-grid (mf/use-fn (mf/deps id) #(st/emit! (dw/add-frame-grid id)))]
- [:div.element-set
- [:div.element-set-title
- [:span (tr "workspace.options.grid.grid-title")]
- [:div.add-page {:on-click handle-create-grid} i/close]]
- (when (seq (:grids shape))
- [:div.element-set-content
- (for [[index grid] (map-indexed vector (:grids shape))]
- [:& grid-options {:key (str id "-" index)
- :shape-id id
- :grid grid
- :index index
- :frame-width (:width shape)
- :frame-height (:height shape)
- :default-grid-params default-grid-params
- }])])]))
+ (if new-css-system
+ [:div {:class (stl/css :element-set)}
+ [:& title-bar {:collapsable? true
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title (tr "workspace.options.grid.grid-title")}
+
+ [:button {:on-click handle-create-grid
+ :class (stl/css :add-grid)}
+ i/add-refactor]]
+
+ (when (and open? (seq (:grids shape)))
+ [:div {:class (stl/css :element-set-content)}
+ (for [[index grid] (map-indexed vector (:grids shape))]
+ [:& grid-options {:key (str id "-" index)
+ :shape-id id
+ :grid grid
+ :index index
+ :frame-width (:width shape)
+ :frame-height (:height shape)
+ :default-grid-params default-grid-params}])])]
+
+
+ [:div.element-set
+ [:div.element-set-title
+ [:span (tr "workspace.options.grid.grid-title")]
+ [:div.add-page {:on-click handle-create-grid} i/close]]
+
+ (when (seq (:grids shape))
+ [:div.element-set-content
+ (for [[index grid] (map-indexed vector (:grids shape))]
+ [:& grid-options {:key (str id "-" index)
+ :shape-id id
+ :grid grid
+ :index index
+ :frame-width (:width shape)
+ :frame-height (:height shape)
+ :default-grid-params default-grid-params}])])])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.scss
new file mode 100644
index 0000000000..3b46038922
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.scss
@@ -0,0 +1,240 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.element-set {
+ .add-grid {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ .element-set-content {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ .grid-option {
+ .grid-title {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .option-row {
+ display: flex;
+ align-items: center;
+ gap: $s-1;
+ border-radius: $br-8;
+ background-color: var(--input-details-color);
+ .show-options {
+ @extend .button-secondary;
+ height: $s-32;
+ width: $s-28;
+ border-radius: $br-8 0 0 $br-8;
+ svg {
+ @extend .button-icon;
+ }
+ &.selected {
+ background-color: var(--button-secondary-background-color-active);
+ color: var(--button-secondary-foreground-color-active);
+ svg {
+ stroke: var(--button-secondary-foreground-color-active);
+ }
+ }
+ }
+ .type-select-wrapper {
+ width: $s-96;
+ padding: 0;
+ border-radius: 0;
+ height: $s-32;
+ .grid-type-select {
+ border-radius: 0;
+ }
+ }
+ .grid-size {
+ @extend .asset-element;
+ width: $s-60;
+ margin: 0;
+ padding: 0;
+ padding-left: $s-8;
+ border-radius: 0 $br-8 $br-8 0;
+ .numeric-input {
+ @extend .input-base;
+ }
+ }
+ .editable-select-wrapper {
+ @extend .asset-element;
+ width: $s-60;
+ margin: 0;
+ padding: 0;
+ border: $s-1 solid var(--input-background-color);
+ position: relative;
+ border-radius: 0 $br-8 $br-8 0;
+ .column-select {
+ height: $s-32;
+ .numeric-input {
+ @extend .input-base;
+ margin: 0;
+ padding: 0;
+ }
+ span {
+ @include flexCenter;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ }
+
+ &.hidden {
+ .show-options,
+ .type-select-wrapper,
+ .editable-select-wrapper {
+ background-color: transparent;
+ border: $s-1 solid var(--input-border-color-disabled);
+ color: var(--input-foreground-color-disabled);
+ .column-select,
+ .grid-type-select {
+ background-color: transparent;
+ }
+ }
+ .grid-size {
+ background-color: transparent;
+ border: $s-1 solid var(--input-border-color-disabled);
+ color: var(--input-foreground-color-disabled);
+
+ .icon {
+ stroke: var(--input-foreground-color-disabled);
+ }
+ .numeric-input {
+ color: var(--input-foreground-color-disabled);
+ }
+ }
+ .actions {
+ .hidden-btn,
+ .lock-btn {
+ background-color: transparent;
+ svg {
+ stroke: var(--input-foreground-color-disabled);
+ }
+ }
+ }
+ }
+ }
+
+ .actions {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .action-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ }
+ }
+ .grid-advanced-options {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ margin-top: $s-4;
+ .column-row,
+ .square-row {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ position: relative;
+ .advanced-row {
+ position: relative;
+ display: flex;
+ gap: $s-4;
+ .select-wrapper {
+ width: $s-92;
+ padding: 0;
+ }
+ .color-wrapper {
+ width: $s-156;
+ }
+ .show-more-options {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-32;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ .height {
+ @extend .input-element;
+ width: $s-108;
+ padding-left: $s-8;
+ .icon-text {
+ padding-top: $s-1;
+ }
+ }
+ .gutter,
+ .margin {
+ @extend .input-element;
+ width: $s-108;
+ padding-left: $s-8;
+ .icon {
+ &.rotated svg {
+ transform: rotate(90deg);
+ }
+ }
+ }
+ .more-options {
+ @include menuShadow;
+ position: absolute;
+ top: $s-36;
+ right: 0;
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ width: $s-156;
+ max-height: $s-300;
+ padding: $s-2;
+ margin: 0 0 $s-40 0;
+ margin-top: $s-4;
+ border-radius: $br-8;
+ z-index: $z-index-3;
+ overflow-y: auto;
+ background-color: var(--menu-background-color);
+ .option-btn {
+ @include buttonStyle;
+ display: flex;
+ align-items: center;
+ height: $s-32;
+ padding: 0 $s-8;
+ border-radius: $br-6;
+ color: var(--menu-foreground-color);
+
+ &:hover {
+ background-color: var(--menu-background-color-hover);
+ color: var(--menu-foreground-color-hover);
+ }
+ }
+ }
+ }
+ .second-row {
+ @extend .dropdown-wrapper;
+ left: unset;
+ right: 0;
+ width: $s-108;
+ .btn-options {
+ @include buttonStyle;
+ @extend .dropdown-element-base;
+ width: 100%;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.scss
index 62687e83ab..15229959b2 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.scss
@@ -12,28 +12,13 @@
height: $s-32;
gap: $s-4;
.select {
- @extend .asset-element;
width: $s-124;
- margin: 0;
padding: 0;
- border: 1px solid var(--input-background-color);
}
.input {
@extend .input-element;
width: $s-60;
padding-left: $s-8;
- border: 1px solid var(--input-background-color);
- .icon {
- @include flexCenter;
- margin-right: $s-4;
- }
- .numeric-input {
- @include removeInputStyle;
- @include titleTipography;
- height: $s-32;
- width: 100%;
- margin: 0;
- }
}
.actions {
display: flex;
@@ -54,13 +39,13 @@
&.hidden {
.select {
background-color: transparent;
- border: 1px solid var(--input-border-color-disabled);
+ border: $s-1 solid var(--input-border-color-disabled);
color: var(--input-foreground-color-disabled);
}
.input {
background-color: transparent;
- border: 1px solid var(--input-border-color-disabled);
- color: var(--input-foreground-color-disable);
+ border: $s-1 solid var(--input-border-color-disabled);
+ color: var(--input-foreground-color-disabled);
.icon {
stroke: var(--input-foreground-color-disabled);
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.scss
index 428c85cc0b..a8408e936b 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.scss
@@ -8,7 +8,6 @@
.element-set {
.element-title {
- margin-right: $s-12;
.title-spacing-layout {
margin: 0;
}
@@ -74,74 +73,16 @@
@extend .input-element;
width: $s-108;
padding-left: $s-8;
- .numeric-input {
- @include removeInputStyle;
- @include titleTipography;
- height: $s-32;
- width: 100%;
- margin: 0;
- color: var(--input-foreground-color-active);
- }
- .icon {
- @include flexCenter;
- height: $s-32;
- margin-right: $s-4;
- svg {
- @extend .button-icon-small;
- stroke: var(--icon-foreground);
- }
- }
&.disabled {
- background-color: var(--input-background-color-disabled);
- border: 1px solid var(--input-border-color-disabled);
- color: var(--input-foreground-color-disabled);
- .numeric-input {
- pointer-events: none;
- cursor: default;
- color: var(--input-foreground-color-disabled);
- }
- .icon {
- svg {
- stroke: var(--input-foreground-color-disabled);
- }
- }
+ @extend .disabled-input;
}
}
.row-gap {
@extend .input-element;
width: $s-108;
padding-left: $s-8;
- .numeric-input {
- @include removeInputStyle;
- @include titleTipography;
- height: $s-32;
- width: 100%;
- margin: 0;
- color: var(--input-foreground-color-active);
- }
- .icon {
- @include flexCenter;
- height: $s-32;
- margin-right: $s-4;
- svg {
- @extend .button-icon-small;
- stroke: var(--icon-foreground);
- }
- }
&.disabled {
- background-color: var(--input-background-color-disabled);
- border: 1px solid var(--input-border-color-disabled);
- color: var(--input-foreground-color-disabled);
- .numeric-input {
- pointer-events: none;
- cursor: default;
- color: var(--input-foreground-color-disabled);
- }
- .icon {
- svg {
- stroke: var(--input-foreground-color-disabled);
- }
- }
+ @extend .disabled-input;
}
}
}
@@ -158,23 +99,6 @@
@extend .input-element;
width: $s-108;
padding-left: $s-8;
- .numeric-input {
- @include removeInputStyle;
- @include titleTipography;
- height: $s-32;
- width: 100%;
- margin: 0;
- color: var(--input-foreground-color-active);
- }
- .icon {
- @include flexCenter;
- height: $s-32;
- margin-right: $s-4;
- svg {
- @extend .button-icon-small;
- stroke: var(--icon-foreground);
- }
- }
}
}
.paddings-multiple {
@@ -185,23 +109,6 @@
@extend .input-element;
width: $s-108;
padding-left: $s-8;
- .numeric-input {
- @include removeInputStyle;
- @include titleTipography;
- height: $s-32;
- width: 100%;
- margin: 0;
- color: var(--input-foreground-color-active);
- }
- .icon {
- @include flexCenter;
- height: $s-32;
- margin-right: $s-4;
- svg {
- @extend .button-icon-small;
- stroke: var(--icon-foreground);
- }
- }
}
}
}
@@ -224,15 +131,4 @@
}
}
}
- .grid-layout-menu {
- background-color: antiquewhite;
- .first-row {
- .direction-edit {
- .direction {
- }
- .edit {
- }
- }
- }
- }
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
index 7a54130e98..1b2a2fc4ed 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
@@ -518,108 +518,109 @@
:id :static-position}]
[:& radio-button {:value "absolute"
:id :absolute-position}]]])]]
- [:div {:class (stl/css :flex-element-menu)}
- [:div {:class (stl/css :first-row)}
- [:& element-behaviour {:fill? is-layout-child?
- :auto? is-layout-container?
- :layout-item-v-sizing (or (:layout-item-v-sizing values) :fix)
- :layout-item-h-sizing (or (:layout-item-h-sizing values) :fix)
- :on-change-behaviour-h-refactor on-change-behaviour-h
- :on-change-behaviour-v-refactor on-change-behaviour-v
- :on-change on-change-behaviour}]
- (when is-absolute?
- [:div {:class (stl/css-case :z-index-wrapper true)
- :title "z-index"}
-
- [:span {:class (stl/css :icon-text)}
- "Z"]
- [:> numeric-input*
- {:className (stl/css :numeric-input)
- :placeholder "--"
- :on-focus #(dom/select-target %)
- :on-change #(on-change-z-index %)
- :nillable true
- :value (:layout-item-z-index values)}]])]
-
- (when (and is-layout-child? is-flex-parent?)
- [:div {:class (stl/css :second-row)}
- [:& align-self-row {:is-col? is-col?
- :align-self align-self
- :on-changer set-align-self-refactor}]])
-
- (when is-layout-child?
- [:div {:class (stl/css :third-row)}
- [:& margin-section {:values values
- :change-margin-style change-margin-style
- :on-margin-change on-margin-change}]])
-
- [:div {:class (stl/css :forth-row)}
- [:div {:class (stl/css :advanced-options)}
- (when (= (:layout-item-h-sizing values) :fill)
- [:div {:class (stl/css :horizontal-fill)}
- [:div {:class (stl/css :layout-item-min-w)
- :title (tr "workspace.options.layout-item.layout-item-min-w")}
+ (when open?
+ [:div {:class (stl/css :flex-element-menu)}
+ [:div {:class (stl/css :first-row)}
+ [:& element-behaviour {:fill? is-layout-child?
+ :auto? is-layout-container?
+ :layout-item-v-sizing (or (:layout-item-v-sizing values) :fix)
+ :layout-item-h-sizing (or (:layout-item-h-sizing values) :fix)
+ :on-change-behaviour-h-refactor on-change-behaviour-h
+ :on-change-behaviour-v-refactor on-change-behaviour-v
+ :on-change on-change-behaviour}]
+ (when is-absolute?
+ [:div {:class (stl/css :z-index-wrapper)
+ :title "z-index"}
[:span {:class (stl/css :icon-text)}
- "MIN W"]
+ "Z"]
[:> numeric-input*
{:className (stl/css :numeric-input)
- :no-validate true
- :min 0
- :data-wrap true
:placeholder "--"
:on-focus #(dom/select-target %)
- :on-change (partial on-size-change :layout-item-min-w)
- :value (get values :layout-item-min-w)
- :nillable true}]]
+ :on-change #(on-change-z-index %)
+ :nillable true
+ :value (:layout-item-z-index values)}]])]
- [:div {:class (stl/css :layout-item-max-w)
- :title (tr "workspace.options.layout-item.layout-item-max-w")}
- [:span {:class (stl/css :icon-text)}
- "MAX W"]
- [:> numeric-input*
- {:className (stl/css :numeric-input)
- :no-validate true
- :min 0
- :data-wrap true
- :placeholder "--"
- :on-focus #(dom/select-target %)
- :on-change (partial on-size-change :layout-item-max-w)
- :value (get values :layout-item-max-w)
- :nillable true}]]])
- (when (= (:layout-item-v-sizing values) :fill)
- [:div {:class (stl/css :vertical-fill)}
- [:div {:class (stl/css :layout-item-min-h)
- :title (tr "workspace.options.layout-item.layout-item-min-h")}
+ (when (and is-layout-child? is-flex-parent?)
+ [:div {:class (stl/css :second-row)}
+ [:& align-self-row {:is-col? is-col?
+ :align-self align-self
+ :on-changer set-align-self-refactor}]])
- [:span {:class (stl/css :icon-text)}
- "MIN H"]
- [:> numeric-input*
- {:className (stl/css :numeric-input)
- :no-validate true
- :min 0
- :data-wrap true
- :placeholder "--"
- :on-focus #(dom/select-target %)
- :on-change (partial on-size-change :layout-item-min-h)
- :value (get values :layout-item-min-h)
- :nillable true}]]
+ (when is-layout-child?
+ [:div {:class (stl/css :third-row)}
+ [:& margin-section {:values values
+ :change-margin-style change-margin-style
+ :on-margin-change on-margin-change}]])
- [:div {:class (stl/css :layout-item-max-h)
- :title (tr "workspace.options.layout-item.layout-item-max-h")}
+ [:div {:class (stl/css :forth-row)}
+ [:div {:class (stl/css :advanced-options)}
+ (when (= (:layout-item-h-sizing values) :fill)
+ [:div {:class (stl/css :horizontal-fill)}
+ [:div {:class (stl/css :layout-item-min-w)
+ :title (tr "workspace.options.layout-item.layout-item-min-w")}
- [:span {:class (stl/css :icon-text)}
- "MAX H"]
- [:> numeric-input*
- {:className (stl/css :numeric-input)
- :no-validate true
- :min 0
- :data-wrap true
- :placeholder "--"
- :on-focus #(dom/select-target %)
- :on-change (partial on-size-change :layout-item-max-h)
- :value (get values :layout-item-max-h)
- :nillable true}]]])]]]]
+ [:span {:class (stl/css :icon-text)}
+ "MIN W"]
+ [:> numeric-input*
+ {:className (stl/css :numeric-input)
+ :no-validate true
+ :min 0
+ :data-wrap true
+ :placeholder "--"
+ :on-focus #(dom/select-target %)
+ :on-change (partial on-size-change :layout-item-min-w)
+ :value (get values :layout-item-min-w)
+ :nillable true}]]
+
+ [:div {:class (stl/css :layout-item-max-w)
+ :title (tr "workspace.options.layout-item.layout-item-max-w")}
+ [:span {:class (stl/css :icon-text)}
+ "MAX W"]
+ [:> numeric-input*
+ {:className (stl/css :numeric-input)
+ :no-validate true
+ :min 0
+ :data-wrap true
+ :placeholder "--"
+ :on-focus #(dom/select-target %)
+ :on-change (partial on-size-change :layout-item-max-w)
+ :value (get values :layout-item-max-w)
+ :nillable true}]]])
+ (when (= (:layout-item-v-sizing values) :fill)
+ [:div {:class (stl/css :vertical-fill)}
+ [:div {:class (stl/css :layout-item-min-h)
+ :title (tr "workspace.options.layout-item.layout-item-min-h")}
+
+ [:span {:class (stl/css :icon-text)}
+ "MIN H"]
+ [:> numeric-input*
+ {:className (stl/css :numeric-input)
+ :no-validate true
+ :min 0
+ :data-wrap true
+ :placeholder "--"
+ :on-focus #(dom/select-target %)
+ :on-change (partial on-size-change :layout-item-min-h)
+ :value (get values :layout-item-min-h)
+ :nillable true}]]
+
+ [:div {:class (stl/css :layout-item-max-h)
+ :title (tr "workspace.options.layout-item.layout-item-max-h")}
+
+ [:span {:class (stl/css :icon-text)}
+ "MAX H"]
+ [:> numeric-input*
+ {:className (stl/css :numeric-input)
+ :no-validate true
+ :min 0
+ :data-wrap true
+ :placeholder "--"
+ :on-focus #(dom/select-target %)
+ :on-change (partial on-size-change :layout-item-max-h)
+ :value (get values :layout-item-max-h)
+ :nillable true}]]])]]])]
[:div.element-set
@@ -667,12 +668,12 @@
[:div.layout-row
[:div.row-title.sizing "Sizing"]
[:& element-behaviour {:fill? is-layout-child?
- :auto? is-layout-container?
- :layout-item-v-sizing (or (:layout-item-v-sizing values) :fix)
- :layout-item-h-sizing (or (:layout-item-h-sizing values) :fix)
- :on-change-behaviour-h-refactor on-change-behaviour-h
- :on-change-behaviour-v-refactor on-change-behaviour-v
- :on-change on-change-behaviour}]]
+ :auto? is-layout-container?
+ :layout-item-v-sizing (or (:layout-item-v-sizing values) :fix)
+ :layout-item-h-sizing (or (:layout-item-h-sizing values) :fix)
+ :on-change-behaviour-h-refactor on-change-behaviour-h
+ :on-change-behaviour-v-refactor on-change-behaviour-v
+ :on-change on-change-behaviour}]]
(when (and is-layout-child? is-flex-parent?)
[:div.layout-row
@@ -713,7 +714,4 @@
:on-focus #(dom/select-target %)
:on-change (partial on-size-change item)
:value (get values item)
- :nillable true}]]])]]]]]
- )
-
- ))
+ :nillable true}]]])]]]]])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.scss
index 3c61bc7dfd..1c8dbf1805 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.scss
@@ -50,27 +50,11 @@
width: $s-92;
}
}
- &.wrap {
- }
}
.z-index-wrapper {
@extend .input-element;
width: $s-124;
padding-left: $s-8;
- .icon-text {
- @include flexCenter;
- height: $s-32;
- margin-right: $s-4;
- padding-top: $s-2;
- }
- .numeric-input {
- @include removeInputStyle;
- @include titleTipography;
- height: $s-32;
- width: 100%;
- margin: 0;
- color: var(--input-foreground-color-active);
- }
}
}
.second-row {
@@ -107,23 +91,6 @@
@extend .input-element;
width: $s-108;
padding-left: $s-8;
- .icon {
- @include flexCenter;
- height: $s-32;
- margin-right: $s-4;
- svg {
- @extend .button-icon-small;
- stroke: var(--icon-foreground);
- }
- }
- .numeric-input {
- @include removeInputStyle;
- @include titleTipography;
- height: $s-32;
- width: 100%;
- margin: 0;
- color: var(--input-foreground-color-active);
- }
}
}
.margin-multiple {
@@ -137,23 +104,6 @@
@extend .input-element;
width: $s-108;
padding-left: $s-8;
- .icon {
- @include flexCenter;
- height: $s-32;
- margin-right: $s-4;
- svg {
- @extend .button-icon-small;
- stroke: var(--icon-foreground);
- }
- }
- .numeric-input {
- @include removeInputStyle;
- @include titleTipography;
- height: $s-32;
- width: 100%;
- margin: 0;
- color: var(--input-foreground-color-active);
- }
}
}
}
@@ -176,21 +126,10 @@
width: $s-108;
padding-left: $s-8;
.icon-text {
- display: flex;
- align-items: center;
- height: $s-32;
+ justify-content: flex-start;
width: $s-80;
- margin-right: $s-4;
padding-top: $s-2;
}
- .numeric-input {
- @include removeInputStyle;
- @include titleTipography;
- height: $s-32;
- width: 100%;
- margin: 0;
- color: var(--input-foreground-color-active);
- }
}
}
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
index e0735e8e9e..6ca9156ba9 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
@@ -392,7 +392,8 @@
:id :horiz}]]])
(when (options :size)
[:div {:class (stl/css :size)}
- [:div {:class (stl/css :height)
+ [:div {:class (stl/css-case :width true
+ :disabled disabled-width-sizing?)
:title (tr "workspace.options.width")}
[:span {:class (stl/css :icon-text)} "W"]
[:> numeric-input* {:min 0.01
@@ -402,7 +403,8 @@
:disabled disabled-width-sizing?
:className (stl/css :numeric-input)
:value (:width values)}]]
- [:div {:class (stl/css :height)
+ [:div {:class (stl/css-case :height true
+ :disabled disabled-height-sizing?)
:title (tr "workspace.options.height")}
[:span {:class (stl/css :icon-text)} "H"]
[:> numeric-input* {:min 0.01
@@ -422,7 +424,8 @@
i/unlock-refactor)]])
(when (options :position)
[:div {:class (stl/css :position)}
- [:div {:class (stl/css :x-position)
+ [:div {:class (stl/css-case :x-position true
+ :disabled disabled-position-x?)
:title (tr "workspace.options.x")}
[:span {:class (stl/css :icon-text)} "X"]
[:> numeric-input* {:no-validate true
@@ -432,7 +435,8 @@
:className (stl/css :numeric-input)
:value (:x values)}]]
- [:div {:class (stl/css :y-position)
+ [:div {:class (stl/css-case :y-position true
+ :disabled disabled-position-y?)
:title (tr "workspace.options.y")}
[:span {:class (stl/css :icon-text)} "Y"]
[:> numeric-input* {:no-validate true
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.scss
index 955f16705c..ffda32b629 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.scss
@@ -40,28 +40,11 @@
}
}
.custom-select-dropdown {
- @include menuShadow;
- position: absolute;
- top: $s-32;
- left: 0;
- max-height: 300px;
+ @extend .dropdown-wrapper;
width: $s-252;
- padding: $s-2;
- margin: 0;
- margin-top: $s-4;
- border-radius: $br-8;
- z-index: $z-index-3;
- overflow-y: auto;
- background-color: var(--menu-background-color);
.dropdown-element {
- @include titleTipography;
- display: flex;
- align-items: center;
- gap: $s-8;
- height: $s-32;
- padding: 0 $s-8;
- border-radius: $br-6;
- cursor: pointer;
+ @extend .dropdown-element-base;
+
&.disabled {
pointer-events: none;
cursor: default;
@@ -119,25 +102,11 @@
@extend .input-element;
width: $s-108;
padding-left: $s-8;
- .icon {
- @include flexCenter;
- width: $s-12;
- height: $s-32;
- margin-right: $s-4;
- }
- .icon-text {
- @include flexCenter;
- height: $s-32;
- margin-right: $s-4;
+ y .icon-text {
padding-top: $s-1;
}
- .numeric-input {
- @include removeInputStyle;
- @include titleTipography;
- height: $s-32;
- width: 100%;
- margin: 0;
- color: var(--input-foreground-color-active);
+ &.disabled {
+ @extend .disabled-input;
}
}
.lock-size-btn {
@@ -160,25 +129,11 @@
@extend .input-element;
width: $s-108;
padding-left: $s-8;
- .icon {
- @include flexCenter;
- height: $s-32;
- width: $s-12;
- margin-right: $s-4;
- }
.icon-text {
- @include flexCenter;
- height: $s-32;
- margin-right: $s-4;
padding-top: $s-1;
}
- .numeric-input {
- @include removeInputStyle;
- @include titleTipography;
- height: $s-32;
- width: 100%;
- margin: 0;
- color: var(--input-foreground-color-active);
+ &.disabled {
+ @extend .disabled-input;
}
}
}
@@ -192,28 +147,8 @@
width: $s-108;
padding-left: $s-8;
.icon-text {
- @include flexCenter;
- height: $s-32;
- margin-right: $s-4;
padding-top: $s-1;
}
- .icon {
- @include flexCenter;
- height: $s-32;
- margin-right: $s-4;
- svg {
- @extend .button-icon-small;
- stroke: var(--icon-foreground);
- }
- }
- .numeric-input {
- @include removeInputStyle;
- @include titleTipography;
- height: $s-32;
- width: 100%;
- margin: 0;
- color: var(--input-foreground-color-active);
- }
}
.radius {
display: flex;
@@ -226,25 +161,6 @@
@extend .input-element;
width: $s-108;
padding-left: $s-8;
- .icon {
- @include flexCenter;
- height: $s-32;
- margin-right: $s-4;
- svg {
- @extend .button-icon-small;
- stroke: var(--icon-foreground);
- }
- }
-
- .numeric-input {
- @include removeInputStyle;
- @include titleTipography;
- height: $s-32;
- width: 100%;
- margin: 0;
- padding: $s-1 $s-2;
- color: var(--input-foreground-color-active);
- }
}
.radius-4 {
display: grid;
@@ -254,14 +170,6 @@
@extend .input-element;
width: $s-52;
padding-left: $s-8;
- .numeric-input {
- @include removeInputStyle;
- @include titleTipography;
- height: $s-32;
- width: 100%;
- margin: 0;
- color: var(--input-foreground-color-active);
- }
}
}
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs
index f1f2ec21ee..93448e0ff4 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs
@@ -5,6 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.menus.shadow
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.colors :as clr]
[app.common.data :as d]
@@ -16,6 +17,9 @@
[app.main.data.workspace.undo :as dwu]
[app.main.store :as st]
[app.main.ui.components.numeric-input :refer [numeric-input*]]
+ [app.main.ui.components.select :refer [select]]
+ [app.main.ui.components.title-bar :refer [title-bar]]
+ [app.main.ui.context :as ctx]
[app.main.ui.hooks :as h]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.common :refer [advanced-options]]
@@ -47,7 +51,8 @@
(mf/defc shadow-entry
[{:keys [ids index value on-reorder disable-drag? on-blur open-state-ref]}]
- (let [basic-offset-x-ref (mf/use-ref nil)
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ basic-offset-x-ref (mf/use-ref nil)
basic-offset-y-ref (mf/use-ref nil)
basic-blur-ref (mf/use-ref nil)
@@ -56,7 +61,9 @@
adv-blur-ref (mf/use-ref nil)
adv-spread-ref (mf/use-ref nil)
- shadow-style (dm/str (:style value))
+ shadow-style (if new-css-system
+ (:style value)
+ (dm/str (:style value)))
shadow-id (:id value)
open-status-ref (mf/with-memo [open-state-ref shadow-id]
@@ -66,12 +73,9 @@
on-remove-shadow
(mf/use-fn
- (mf/deps ids)
- (fn [event]
- (let [index (-> (dom/get-current-target event)
- (dom/get-data "index")
- (parse-long))]
- (st/emit! (dch/update-shapes ids #(update % :shadow remove-shadow-by-index index))))))
+ (mf/deps ids index)
+ (fn []
+ (st/emit! (dch/update-shapes ids #(update % :shadow remove-shadow-by-index index)))))
on-drop
(mf/use-fn
@@ -105,66 +109,147 @@
(dom/set-value! update-node value))))))
update-color
- (fn [index]
- (fn [color]
- (st/emit! (dch/update-shapes
- ids
- #(assoc-in % [:shadow index :color] color)))))
+ (mf/use-fn
+ (mf/deps ids index)
+ (fn [color]
+ (st/emit! (dch/update-shapes
+ ids
+ #(assoc-in % [:shadow index :color] color)))))
detach-color
- (fn [index]
- (fn [_color _opacity]
- (when-not (string? (:color value))
- (st/emit! (dch/update-shapes
- ids
- #(assoc-in % [:shadow index :color]
- (dissoc (:color value) :id :file-id)))))))
+ (mf/use-fn
+ (mf/deps ids index)
+ (fn [_color _opacity]
+ (when-not (string? (:color value))
+ (st/emit! (dch/update-shapes
+ ids
+ #(assoc-in % [:shadow index :color]
+ (dissoc (:color value) :id :file-id)))))))
toggle-visibility
- (fn [index]
- (fn []
- (st/emit! (dch/update-shapes ids #(update-in % [:shadow index :hidden] not)))))
+ (mf/use-fn
+ (mf/deps ids index)
+ (fn []
+ (st/emit! (dch/update-shapes ids #(update-in % [:shadow index :hidden] not)))))
on-toggle-open-shadow
(fn []
- (swap! open-state-ref update shadow-id not))]
- [:*
- [:div.shadow-option {:class (dom/classnames
+ (swap! open-state-ref update shadow-id not))
+
+ on-type-change
+ (mf/use-fn
+ (mf/deps ids index)
+ (fn [event]
+ (let [value (if new-css-system
+ (keyword event)
+ (-> event dom/get-target-val d/read-string))]
+ (st/emit! (dch/update-shapes ids #(assoc-in % [:shadow index :style] value))))))
+
+ type-options [{:value "drop-shadow" :label (tr "workspace.options.shadow-options.drop-shadow")}
+ {:value "inner-shadow" :label (tr "workspace.options.shadow-options.inner-shadow")}]]
+
+ (if new-css-system
+ [:div {:class (stl/css-case :shadow-element true
:dnd-over-top (= (:over dprops) :top)
:dnd-over-bot (= (:over dprops) :bot))
- :ref dref}
- [:div.shadow-option-main {:style {:display (when open-shadow "none")}}
- [:div.element-set-actions-button
- {:on-click on-toggle-open-shadow}
- i/actions]
+ :ref dref}
+ [:div {:class (stl/css :basic-options)}
+ [:div {:class (stl/css :shadow-info)}
+ [:button {:class (stl/css :more-options)
+ :on-click on-toggle-open-shadow}
+ i/menu-refactor]
+ [:div {:class (stl/css :type-select)}
+ [:& select
+ {:class (stl/css :shadow-type-select)
+ :default-value (d/name shadow-style)
+ :options type-options
+ :on-change on-type-change}]]]
+ [:div {:class (stl/css :actions)}
+ [:button {:class (stl/css :action-btn)
+ :on-click toggle-visibility}
+ (if (:hidden value)
+ i/hide-refactor
+ i/shown-refactor)]
+ [:button {:class (stl/css :action-btn)
+ :on-click on-remove-shadow}
+ i/remove-refactor]]]
- [:select.input-select
- {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :default-value shadow-style
- :on-change (fn [event]
- (let [value (-> event dom/get-target dom/get-value d/read-string)]
- (st/emit! (dch/update-shapes ids #(assoc-in % [:shadow index :style] value)))))}
- [:option {:value ":drop-shadow"
- :selected (when (= shadow-style ":drop-shadow") "selected")}
- (tr "workspace.options.shadow-options.drop-shadow")]
- [:option {:value ":inner-shadow"
- :selected (when (= shadow-style ":inner-shadow") "selected")}
- (tr "workspace.options.shadow-options.inner-shadow")]]
+ (when open-shadow
+ [:& advanced-options {:class (stl/css :shadow-advanced-options)
+ :visible? open-shadow
+ :on-close on-toggle-open-shadow}
- [:div.shadow-option-main-actions
- [:div.element-set-actions-button {:on-click (toggle-visibility index)}
- (if (:hidden value) i/eye-closed i/eye)]
- [:div.element-set-actions-button
- {:data-index index
- :on-click on-remove-shadow}
- i/minus]]]
+ [:div {:class (stl/css :first-row)}
+ [:div {:class (stl/css :offset-x-input)
+ :title (tr "workspace.options.shadow-options.offsetx")}
+ [:span {:class (stl/css :input-label)}
+ "X"]
+ [:> numeric-input* {:className (stl/css :numeric-input)
+ :ref adv-offset-x-ref
+ :no-validate true
+ :placeholder "--"
+ :on-change (update-attr index :offset-x basic-offset-x-ref)
+ :on-blur on-blur
+ :value (:offset-x value)}]]
- [:& advanced-options {:visible? open-shadow
- :on-close on-toggle-open-shadow}
- [:div.color-data
+ [:div {:class (stl/css :blur-input)
+ :title (tr "workspace.options.shadow-options.blur")}
+ [:span {:class (stl/css :input-label)}
+ (tr "workspace.options.shadow-options.blur")]
+ [:> numeric-input* {:ref adv-blur-ref
+ :className (stl/css :numeric-input)
+ :no-validate true
+ :placeholder "--"
+ :on-change (update-attr index :blur basic-blur-ref)
+ :on-blur on-blur
+ :min 0
+ :value (:blur value)}]]
+
+ [:div {:class (stl/css :spread-input)
+ :title (tr "workspace.options.shadow-options.spread")}
+ [:span {:class (stl/css :input-label)}
+ (tr "workspace.options.shadow-options.spread")]
+ [:> numeric-input* {:ref adv-spread-ref
+ :className (stl/css :numeric-input)
+ :no-validate true
+ :placeholder "--"
+ :on-change (update-attr index :spread)
+ :on-blur on-blur
+ :value (:spread value)}]]]
+
+
+ [:div {:class (stl/css :second-row)}
+ [:div {:class (stl/css :offset-y-input)
+ :title (tr "workspace.options.shadow-options.offsety")}
+ [:span {:class (stl/css :input-label)}
+ "Y"]
+ [:> numeric-input* {:ref adv-offset-y-ref
+ :className (stl/css :numeric-input)
+ :no-validate true
+ :placeholder "--"
+ :on-change (update-attr index :offset-y basic-offset-y-ref)
+ :on-blur on-blur
+ :value (:offset-y value)}]]
+ [:& color-row {:color (if (string? (:color value))
+ ;; Support for old format colors
+ {:color (:color value) :opacity (:opacity value)}
+ (:color value))
+ :title (tr "workspace.options.shadow-options.color")
+ :disable-gradient true
+ :on-change update-color
+ :on-detach detach-color
+ :on-open #(st/emit! (dwu/start-undo-transaction :color-row))
+ :on-close #(st/emit! (dwu/commit-undo-transaction :color-row))}]]])]
+
+ [:div.shadow-option {:class (dom/classnames
+ :dnd-over-top (= (:over dprops) :top)
+ :dnd-over-bot (= (:over dprops) :bot))
+ :ref dref}
+ [:div.shadow-option-main {:style {:display (when open-shadow "none")}}
[:div.element-set-actions-button
{:on-click on-toggle-open-shadow}
i/actions]
+
[:select.input-select
{:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
:default-value shadow-style
@@ -176,70 +261,106 @@
(tr "workspace.options.shadow-options.drop-shadow")]
[:option {:value ":inner-shadow"
:selected (when (= shadow-style ":inner-shadow") "selected")}
- (tr "workspace.options.shadow-options.inner-shadow")]]]
+ (tr "workspace.options.shadow-options.inner-shadow")]]
- [:div.row-grid-2
- [:div.input-element {:title (tr "workspace.options.shadow-options.offsetx")}
- [:> numeric-input* {:ref adv-offset-x-ref
- :no-validate true
- :placeholder "--"
- :on-change (update-attr index :offset-x basic-offset-x-ref)
- :on-blur on-blur
- :value (:offset-x value)}]
- [:span.after (tr "workspace.options.shadow-options.offsetx")]]
+ [:div.shadow-option-main-actions
+ [:div.element-set-actions-button {:on-click (toggle-visibility index)}
+ (if (:hidden value) i/eye-closed i/eye)]
+ [:div.element-set-actions-button
+ {:data-index index
+ :on-click on-remove-shadow}
+ i/minus]]]
- [:div.input-element {:title (tr "workspace.options.shadow-options.offsety")}
- [:> numeric-input* {:ref adv-offset-y-ref
- :no-validate true
- :placeholder "--"
- :on-change (update-attr index :offset-y basic-offset-y-ref)
- :on-blur on-blur
- :value (:offset-y value)}]
- [:span.after (tr "workspace.options.shadow-options.offsety")]]]
+ [:& advanced-options {:visible? open-shadow
+ :on-close on-toggle-open-shadow}
+ [:div.color-data
+ [:div.element-set-actions-button
+ {:on-click on-toggle-open-shadow}
+ i/actions]
+ [:select.input-select
+ {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
+ :default-value shadow-style
+ :on-change (fn [event]
+ (let [value (-> event dom/get-target dom/get-value d/read-string)]
+ (st/emit! (dch/update-shapes ids #(assoc-in % [:shadow index :style] value)))))}
+ [:option {:value ":drop-shadow"
+ :selected (when (= shadow-style ":drop-shadow") "selected")}
+ (tr "workspace.options.shadow-options.drop-shadow")]
+ [:option {:value ":inner-shadow"
+ :selected (when (= shadow-style ":inner-shadow") "selected")}
+ (tr "workspace.options.shadow-options.inner-shadow")]]]
- [:div.row-grid-2
- [:div.input-element {:title (tr "workspace.options.shadow-options.blur")}
- [:> numeric-input* {:ref adv-blur-ref
- :no-validate true
- :placeholder "--"
- :on-change (update-attr index :blur basic-blur-ref)
- :on-blur on-blur
- :min 0
- :value (:blur value)}]
- [:span.after (tr "workspace.options.shadow-options.blur")]]
+ [:div.row-grid-2
+ [:div.input-element {:title (tr "workspace.options.shadow-options.offsetx")}
+ [:> numeric-input* {:ref adv-offset-x-ref
+ :no-validate true
+ :placeholder "--"
+ :on-change (update-attr index :offset-x basic-offset-x-ref)
+ :on-blur on-blur
+ :value (:offset-x value)}]
+ [:span.after (tr "workspace.options.shadow-options.offsetx")]]
- [:div.input-element {:title (tr "workspace.options.shadow-options.spread")}
- [:> numeric-input* {:ref adv-spread-ref
- :no-validate true
- :placeholder "--"
- :on-change (update-attr index :spread)
- :on-blur on-blur
- :value (:spread value)}]
- [:span.after (tr "workspace.options.shadow-options.spread")]]]
+ [:div.input-element {:title (tr "workspace.options.shadow-options.offsety")}
+ [:> numeric-input* {:ref adv-offset-y-ref
+ :no-validate true
+ :placeholder "--"
+ :on-change (update-attr index :offset-y basic-offset-y-ref)
+ :on-blur on-blur
+ :value (:offset-y value)}]
+ [:span.after (tr "workspace.options.shadow-options.offsety")]]]
- [:div.color-row-wrap
- [:& color-row {:color (if (string? (:color value))
- ;; Support for old format colors
- {:color (:color value) :opacity (:opacity value)}
- (:color value))
- :title (tr "workspace.options.shadow-options.color")
- :disable-gradient true
- :on-change (update-color index)
- :on-detach (detach-color index)
- :on-open #(st/emit! (dwu/start-undo-transaction :color-row))
- :on-close #(st/emit! (dwu/commit-undo-transaction :color-row))}]]]]]))
+ [:div.row-grid-2
+ [:div.input-element {:title (tr "workspace.options.shadow-options.blur")}
+ [:> numeric-input* {:ref adv-blur-ref
+ :no-validate true
+ :placeholder "--"
+ :on-change (update-attr index :blur basic-blur-ref)
+ :on-blur on-blur
+ :min 0
+ :value (:blur value)}]
+ [:span.after (tr "workspace.options.shadow-options.blur")]]
+
+ [:div.input-element {:title (tr "workspace.options.shadow-options.spread")}
+ [:> numeric-input* {:ref adv-spread-ref
+ :no-validate true
+ :placeholder "--"
+ :on-change (update-attr index :spread)
+ :on-blur on-blur
+ :value (:spread value)}]
+ [:span.after (tr "workspace.options.shadow-options.spread")]]]
+
+ [:div.color-row-wrap
+ [:& color-row {:color (if (string? (:color value))
+ ;; Support for old format colors
+ {:color (:color value) :opacity (:opacity value)}
+ (:color value))
+ :title (tr "workspace.options.shadow-options.color")
+ :disable-gradient true
+ :on-change update-color
+ :on-detach detach-color
+ :on-open #(st/emit! (dwu/start-undo-transaction :color-row))
+ :on-close #(st/emit! (dwu/commit-undo-transaction :color-row))}]]]])))
(mf/defc shadow-menu
{::mf/wrap-props false}
[props]
- (let [ids (unchecked-get props "ids")
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ ids (unchecked-get props "ids")
type (unchecked-get props "type")
values (unchecked-get props "values")
shadows (:shadow values [])
open-state-ref (mf/with-memo [] (l/atom {}))
- disable-drag* (mf/use-state false)
- disable-drag? (deref disable-drag*)
+
+ state* (mf/use-state {:show-content true
+ :disable-drag false})
+
+ state (deref state*)
+ open? (:show-content state)
+ disable-drag? (:disable-drag state)
+
+ toggle-content
+ (mf/use-fn #(swap! state* update :show-content not))
on-remove-all
(mf/use-fn
@@ -255,43 +376,84 @@
on-blur
(mf/use-fn
- #(reset! disable-drag* false))
+ #(swap! state* assoc :disable-drag false))
on-add-shadow
(mf/use-fn
(mf/deps ids)
#(st/emit! (dc/add-shadow ids (create-shadow))))]
- [:div.element-set.shadow-options
- [:div.element-set-title
- [:span
- (case type
- :multiple (tr "workspace.options.shadow-options.title.multiple")
- :group (tr "workspace.options.shadow-options.title.group")
- (tr "workspace.options.shadow-options.title"))]
+ (if new-css-system
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? true
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title (case type
+ :multiple (tr "workspace.options.shadow-options.title.multiple")
+ :group (tr "workspace.options.shadow-options.title.group")
+ (tr "workspace.options.shadow-options.title"))
+ :class (stl/css :title-spacing-shadow)}
- (when-not (= :multiple shadows)
- [:div.add-page {:on-click on-add-shadow} i/close])]
+ (when-not (= :multiple shadows)
+ [:button {:class (stl/css :add-shadow)
+ :on-click on-add-shadow} i/add-refactor])]]
- (cond
- (= :multiple shadows)
- [:div.element-set-content
- [:div.element-set-options-group
- [:div.element-set-label (tr "settings.multiple")]
- [:div.element-set-actions
- [:div.element-set-actions-button {:on-click on-remove-all}
- i/minus]]]]
+ (when open?
+ (cond
+ (= :multiple shadows)
+ [:div {:class (stl/css :element-set-content)}
+ [:div {:class (stl/css :multiple-shadows)}
+ [:div {:class (stl/css :label)} (tr "settings.multiple")]
+ [:div {:class (stl/css :actions)}
+ [:button {:class (stl/css :action-btn)
+ :on-click on-remove-all}
+ i/remove-refactor]]]]
- (seq shadows)
- [:& h/sortable-container {}
- [:div.element-set-content
- (for [[index value] (d/enumerate shadows)]
- [:& shadow-entry
- {:key (dm/str "shadow-" index)
- :ids ids
- :value value
- :on-reorder handle-reorder
- :disable-drag? disable-drag?
- :on-blur on-blur
- :index index
- :open-state-ref open-state-ref}])]])]))
+ (seq shadows)
+ [:& h/sortable-container {}
+ [:div {:class (stl/css :element-set-content)}
+ (for [[index value] (d/enumerate shadows)]
+ [:& shadow-entry
+ {:key (dm/str "shadow-" index)
+ :ids ids
+ :value value
+ :on-reorder handle-reorder
+ :disable-drag? disable-drag?
+ :on-blur on-blur
+ :index index
+ :open-state-ref open-state-ref}])]]))]
+
+ [:div.element-set.shadow-options
+ [:div.element-set-title
+ [:span
+ (case type
+ :multiple (tr "workspace.options.shadow-options.title.multiple")
+ :group (tr "workspace.options.shadow-options.title.group")
+ (tr "workspace.options.shadow-options.title"))]
+
+ (when-not (= :multiple shadows)
+ [:div.add-page {:on-click on-add-shadow} i/close])]
+
+ (cond
+ (= :multiple shadows)
+ [:div.element-set-content
+ [:div.element-set-options-group
+ [:div.element-set-label (tr "settings.multiple")]
+ [:div.element-set-actions
+ [:div.element-set-actions-button {:on-click on-remove-all}
+ i/minus]]]]
+
+ (seq shadows)
+ [:& h/sortable-container {}
+ [:div.element-set-content
+ (for [[index value] (d/enumerate shadows)]
+ [:& shadow-entry
+ {:key (dm/str "shadow-" index)
+ :ids ids
+ :value value
+ :on-reorder handle-reorder
+ :disable-drag? disable-drag?
+ :on-blur on-blur
+ :index index
+ :open-state-ref open-state-ref}])]])])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/shadow.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/shadow.scss
new file mode 100644
index 0000000000..2c7e02144c
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/shadow.scss
@@ -0,0 +1,130 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.element-set {
+ .element-title {
+ .add-shadow {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ .element-set-content {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ .multiple-shadows {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .label {
+ @extend .mixed-bar;
+ }
+ .actions {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .action-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ }
+ .shadow-element {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ .basic-options {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .shadow-info {
+ display: flex;
+ align-items: center;
+ gap: $s-1;
+ width: $s-188;
+ .more-options {
+ @extend .button-secondary;
+ height: $s-32;
+ width: $s-28;
+ border-radius: $br-8 0 0 $br-8;
+ svg {
+ @extend .button-icon;
+ }
+ &.selected {
+ background-color: var(--button-secondary-background-color-active);
+ color: var(--button-secondary-foreground-color-active);
+ svg {
+ stroke: var(--button-secondary-foreground-color-active);
+ }
+ }
+ }
+ .type-select {
+ padding: 0;
+ border-radius: 0 $br-8 $br-8 0;
+ flex-grow: 1;
+ .shadow-type-select {
+ flex-grow: 1;
+ border-radius: 0 $br-8 $br-8 0;
+ }
+ }
+ }
+ .actions {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .action-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ }
+ .shadow-advanced-options {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ .first-row,
+ .second-row {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .offset-x-input,
+ .blur-input,
+ .spread-input,
+ .offset-y-input {
+ @extend .input-element;
+ width: $s-60;
+ min-width: $s-60;
+ padding: 0 0 0 $s-8;
+ input {
+ width: $s-32;
+ }
+ }
+ .blur-input,
+ .spread-input {
+ width: $s-92;
+ .input-label {
+ width: $s-44;
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
index a00e21a3ed..4deded69dd 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
@@ -5,12 +5,15 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.menus.stroke
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.colors :as clr]
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.main.data.workspace.colors :as dc]
[app.main.store :as st]
+ [app.main.ui.components.title-bar :refer [title-bar]]
+ [app.main.ui.context :as ctx]
[app.main.ui.hooks :as h]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.rows.stroke-row :refer [stroke-row]]
@@ -35,11 +38,17 @@
(mf/defc stroke-menu
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "type" "show-caps"]))]}
[{:keys [ids type values show-caps disable-stroke-style] :as props}]
- (let [label (case type
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ label (case type
:multiple (tr "workspace.options.selection-stroke")
:group (tr "workspace.options.group-stroke")
(tr "workspace.options.stroke"))
+ state* (mf/use-state true)
+ open? (deref state*)
+
+ toggle-content (mf/use-fn #(swap! state* not))
+
handle-change-stroke-color
(mf/use-callback
(mf/deps ids)
@@ -47,14 +56,25 @@
(fn [color]
(st/emit! (dc/change-stroke ids color index)))))
+ on-color-change-refactor
+ (mf/use-callback
+ (mf/deps ids)
+ (fn [index color]
+ (st/emit! (dc/change-stroke ids color index))))
+
handle-remove
(mf/use-callback
(mf/deps ids)
(fn [index]
(fn []
(st/emit! (dc/remove-stroke ids index)))))
+ on-remove-refactor
+ (mf/use-callback
+ (mf/deps ids)
+ (fn [index]
+ (st/emit! (dc/remove-stroke ids index))))
- handle-remove-remove-all
+ handle-remove-all
(fn [_]
(st/emit! (dc/remove-all-strokes ids)))
@@ -67,6 +87,14 @@
(assoc :id nil :file-id nil))]
(st/emit! (dc/change-stroke ids color index))))))
+ on-color-detach-refactor
+ (mf/use-callback
+ (mf/deps ids)
+ (fn [index color]
+ (let [color (-> color
+ (assoc :id nil :file-id nil))]
+ (st/emit! (dc/change-stroke ids color index)))))
+
handle-reorder
(mf/use-callback
(mf/deps ids)
@@ -82,6 +110,13 @@
(d/read-string))]
(st/emit! (dc/change-stroke ids {:stroke-style value} index)))))
+ on-stroke-style-change-refactor
+ (mf/use-callback
+ (mf/deps ids)
+ (fn [index value]
+ (st/emit! (dc/change-stroke ids {:stroke-style value} index))))
+
+
on-stroke-alignment-change
(fn [index]
(fn [event]
@@ -91,12 +126,24 @@
(when-not (str/empty? value)
(st/emit! (dc/change-stroke ids {:stroke-alignment value} index))))))
+ on-stroke-alignment-change-refactor
+ (fn [index value]
+ (when-not (str/empty? value)
+ (st/emit! (dc/change-stroke ids {:stroke-alignment value} index))))
+
+
on-stroke-width-change
(fn [index]
(fn [value]
(when-not (str/empty? value)
(st/emit! (dc/change-stroke ids {:stroke-width value} index)))))
+ on-stroke-width-change-refactor
+ (fn [index value]
+ (when-not (str/empty? value)
+ (st/emit! (dc/change-stroke ids {:stroke-width value} index))))
+
+
open-caps-select
(fn [caps-state]
(fn [event]
@@ -147,48 +194,96 @@
disable-drag (mf/use-state false)
on-focus (fn [_]
- (reset! disable-drag true))
+ (reset! disable-drag true))
on-blur (fn [_]
(reset! disable-drag false))]
- [:div.element-set
- [:div.element-set-title
- [:span label]
- [:div.add-page {:on-click on-add-stroke} i/close]]
+ (if new-css-system
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? true
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title label
+ :class (stl/css :title-spacing-fill)}
- [:div.element-set-content
- (cond
- (= :multiple (:strokes values))
- [:div.element-set-options-group
- [:div.element-set-label (tr "settings.multiple")]
- [:div.element-set-actions
- [:div.element-set-actions-button {:on-click handle-remove-remove-all}
- i/minus]]]
+ [:button {:class (stl/css :add-stroke)
+ :on-click on-add-stroke} i/add-refactor]]]
+ (when open?
+ [:div {:class (stl/css :element-content)}
+ (cond
+ (= :multiple (:strokes values))
+ [:div {:class (stl/css :element-set-options-group)}
+ [:div {:class (stl/css :group-label)}
+ (tr "settings.multiple")]
+ [:button {:on-click handle-remove-all
+ :class (stl/css :remove-btn)}
+ i/remove-refactor]]
+ (seq (:strokes values))
+ [:& h/sortable-container {}
+ (for [[index value] (d/enumerate (:strokes values []))]
+ [:& stroke-row {:key (dm/str "stroke-" index)
+ :stroke value
+ :title (tr "workspace.options.stroke-color")
+ :index index
+ :show-caps show-caps
+ :on-color-change on-color-change-refactor
+ :on-color-detach on-color-detach-refactor
+ :on-stroke-width-change on-stroke-width-change-refactor
+ :on-stroke-style-change on-stroke-style-change-refactor
+ :on-stroke-alignment-change on-stroke-alignment-change-refactor
+ :open-caps-select open-caps-select
+ :close-caps-select close-caps-select
+ :on-stroke-cap-start-change on-stroke-cap-start-change
+ :on-stroke-cap-end-change on-stroke-cap-end-change
+ :on-stroke-cap-switch on-stroke-cap-switch
+ :on-remove on-remove-refactor
+ :on-reorder (handle-reorder index)
+ :disable-drag disable-drag
+ :on-focus on-focus
+ :select-on-focus (not @disable-drag)
+ :on-blur on-blur
+ :disable-stroke-style disable-stroke-style}])])])]
- (seq (:strokes values))
- [:& h/sortable-container {}
- (for [[index value] (d/enumerate (:strokes values []))]
- [:& stroke-row {:key (dm/str "stroke-" index)
- :stroke value
- :title (tr "workspace.options.stroke-color")
- :index index
- :show-caps show-caps
- :on-color-change handle-change-stroke-color
- :on-color-detach handle-detach
- :on-stroke-width-change on-stroke-width-change
- :on-stroke-style-change on-stroke-style-change
- :on-stroke-alignment-change on-stroke-alignment-change
- :open-caps-select open-caps-select
- :close-caps-select close-caps-select
- :on-stroke-cap-start-change on-stroke-cap-start-change
- :on-stroke-cap-end-change on-stroke-cap-end-change
- :on-stroke-cap-switch on-stroke-cap-switch
- :on-remove handle-remove
- :on-reorder (handle-reorder index)
- :disable-drag disable-drag
- :on-focus on-focus
- :select-on-focus (not @disable-drag)
- :on-blur on-blur
- :disable-stroke-style disable-stroke-style}])])]]))
+ [:div.element-set
+ [:div.element-set-title
+ [:span label]
+ [:div.add-page {:on-click on-add-stroke} i/close]]
+
+ [:div.element-set-content
+ (cond
+ (= :multiple (:strokes values))
+ [:div.element-set-options-group
+ [:div.element-set-label (tr "settings.multiple")]
+ [:div.element-set-actions
+ [:div.element-set-actions-button {:on-click handle-remove-all}
+ i/minus]]]
+
+
+ (seq (:strokes values))
+ [:& h/sortable-container {}
+ (for [[index value] (d/enumerate (:strokes values []))]
+ [:& stroke-row {:key (dm/str "stroke-" index)
+ :stroke value
+ :title (tr "workspace.options.stroke-color")
+ :index index
+ :show-caps show-caps
+ :on-color-change handle-change-stroke-color
+ :on-color-detach handle-detach
+ :on-stroke-width-change on-stroke-width-change
+ :on-stroke-style-change on-stroke-style-change
+ :on-stroke-alignment-change on-stroke-alignment-change
+ :open-caps-select open-caps-select
+ :close-caps-select close-caps-select
+ :on-stroke-cap-start-change on-stroke-cap-start-change
+ :on-stroke-cap-end-change on-stroke-cap-end-change
+ :on-stroke-cap-switch on-stroke-cap-switch
+ :on-remove handle-remove
+ :on-reorder (handle-reorder index)
+ :disable-drag disable-drag
+ :on-focus on-focus
+ :select-on-focus (not @disable-drag)
+ :on-blur on-blur
+ :disable-stroke-style disable-stroke-style}])])]])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/stroke.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/stroke.scss
new file mode 100644
index 0000000000..ce1d49eae4
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/stroke.scss
@@ -0,0 +1,42 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.element-set {
+ .element-title {
+ .add-stroke {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+
+ .element-content {
+ display: flex;
+ flex-direction: column;
+ gap: $s-12;
+ .element-set-options-group {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .group-label {
+ @extend .mixed-bar;
+ }
+ .remove-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.cljs
index 4db6b521bf..8423f5b013 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.cljs
@@ -5,10 +5,13 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.menus.svg-attrs
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.main.data.workspace.changes :as dch]
[app.main.store :as st]
+ [app.main.ui.components.title-bar :refer [title-bar]]
+ [app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.rows.input-row :refer [input-row]]
[app.util.dom :as dom]
@@ -16,7 +19,8 @@
[rumext.v2 :as mf]))
(mf/defc attribute-value [{:keys [attr value on-change on-delete] :as props}]
- (let [handle-change
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ handle-change
(mf/use-callback
(mf/deps attr on-change)
(fn [event]
@@ -29,32 +33,62 @@
(on-delete attr)))
label (->> attr last d/name)]
- [:div.element-set-content
- (if (string? value)
- [:div.row-flex.row-flex-removable
- [:& input-row {:label label
- :type :text
- :class "large"
- :value (str value)
- :on-change handle-change}]
- [:div.element-set-actions
- [:div.element-set-actions-button {:on-click handle-delete}
- i/minus]]]
+ (if new-css-system
+ [:*
+ (if (string? value)
+ [:div {:class (stl/css :attr-content)}
+ [:span {:class (stl/css :attr-name)} label]
+ [:div {:class (stl/css :attr-input)}
+ [:input {:value value
+ :class "input-text"
+ :on-change handle-change}]]
+ [:div {:class (stl/css :attr-actions)}
+ [:button {:class (stl/css :attr-action-btn)
+ :on-click handle-delete}
+ i/remove-refactor]]]
+ [:div {:class (stl/css :attr-row)}
+ [:span {:class (stl/css :attr-title)}
+ (str (d/name (last attr)))]
- [:*
- [:div.element-set-title
- {:style {:border-bottom "1px solid #444" :margin-bottom "0.5rem"}}
- [:span (str (d/name (last attr)))]]
+ (for [[key value] value]
+ [:& attribute-value {:key key
+ :attr (conj attr key)
+ :value value
+ :on-change on-change
+ :on-delete on-delete}])])]
- (for [[key value] value]
- [:& attribute-value {:key key
- :attr (conj attr key)
- :value value
- :on-change on-change
- :on-delete on-delete}])])]))
+
+ [:div.element-set-content
+ (if (string? value)
+ [:div.row-flex.row-flex-removable
+ [:& input-row {:label label
+ :type :text
+ :class "large"
+ :value (str value)
+ :on-change handle-change}]
+ [:div.element-set-actions
+ [:div.element-set-actions-button {:on-click handle-delete}
+ i/minus]]]
+
+ [:*
+ [:div.element-set-title
+ {:style {:border-bottom "1px solid #444" :margin-bottom "0.5rem"}}
+ [:span (str (d/name (last attr)))]]
+
+ (for [[key value] value]
+ [:& attribute-value {:key key
+ :attr (conj attr key)
+ :value value
+ :on-change on-change
+ :on-delete on-delete}])])])))
(mf/defc svg-attrs-menu [{:keys [ids values]}]
- (let [handle-change
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ state* (mf/use-state true)
+ open? (deref state*)
+
+ toggle-content (mf/use-fn #(swap! state* not))
+ handle-change
(mf/use-callback
(mf/deps ids)
(fn [attr value]
@@ -75,18 +109,32 @@
(empty? (get-in shape [:svg-attrs :style]))
(update :svg-attrs dissoc :style))]
shape))]
- (st/emit! (dch/update-shapes ids update-fn)))))
-
- ]
+ (st/emit! (dch/update-shapes ids update-fn)))))]
(when-not (empty? (:svg-attrs values))
- [:div.element-set
- [:div.element-set-title
- [:span (tr "workspace.sidebar.options.svg-attrs.title")]]
+ (if new-css-system
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-set-title)}
+ [:& title-bar {:collapsable? true
+ :collapsed? (not open?)
+ :on-collapsed toggle-content
+ :title (tr "workspace.sidebar.options.svg-attrs.title")
+ :class (stl/css :title-spacing-svg-attrs)}]]
+ [:div {:class (stl/css :element-set-content)}
+ (for [[attr-key attr-value] (:svg-attrs values)]
+ [:& attribute-value {:key attr-key
+ :attr [attr-key]
+ :value attr-value
+ :on-change handle-change
+ :on-delete handle-delete}])]]
- (for [[attr-key attr-value] (:svg-attrs values)]
- [:& attribute-value {:key attr-key
- :attr [attr-key]
- :value attr-value
- :on-change handle-change
- :on-delete handle-delete}])])))
+ [:div.element-set
+ [:div.element-set-title
+ [:span (tr "workspace.sidebar.options.svg-attrs.title")]]
+
+ (for [[attr-key attr-value] (:svg-attrs values)]
+ [:& attribute-value {:key attr-key
+ :attr [attr-key]
+ :value attr-value
+ :on-change handle-change
+ :on-delete handle-delete}])]))))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.scss
new file mode 100644
index 0000000000..5495e17be9
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.scss
@@ -0,0 +1,52 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.element-set {
+ .element-set-content {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ .attr-row {
+ display: flex;
+ gap: $s-4;
+ .attr-title {
+ @include tabTitleTipography;
+ border-bottom: $s-1 solid var(--color-foreground-secondary);
+ }
+ }
+
+ .attr-content {
+ display: flex;
+ gap: $s-4;
+ .attr-name {
+ @include titleTipography;
+ @include twoLineTextEllipsis;
+ width: $s-92;
+ margin: auto $s-4;
+ margin-right: 0;
+ }
+ .attr-input {
+ @extend .input-element;
+ width: $s-124;
+ padding-left: $s-8;
+ }
+ .attr-actions {
+ display: flex;
+ gap: $s-4;
+ .attr-action-btn {
+ @extend .button-tertiary;
+ width: $s-28;
+ height: $s-32;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs
index a7f85fe0ff..436eb28dc8 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs
@@ -5,6 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.menus.text
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.text :as txt]
@@ -16,6 +17,8 @@
[app.main.data.workspace.undo :as dwu]
[app.main.refs :as refs]
[app.main.store :as st]
+ [app.main.ui.components.radio-buttons :refer [radio-button radio-buttons nilable-option]]
+ [app.main.ui.components.title-bar :refer [title-bar]]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.menus.typography :refer [typography-entry typography-options]]
@@ -27,147 +30,309 @@
(mf/defc text-align-options
[{:keys [values on-change on-blur] :as props}]
(let [{:keys [text-align]} values
+ new-css-system (mf/use-ctx ctx/new-css-system)
+
handle-change
- (fn [_ new-align]
- (on-change {:text-align new-align})
- (when (some? on-blur) (on-blur)))]
+ (mf/use-fn
+ (fn [value]
+ (let [new-align (if new-css-system
+ value
+ (-> (dom/get-current-target value)
+ (dom/get-data "value")))]
+ (on-change {:text-align new-align})
+ (when (some? on-blur) (on-blur)))))]
;; --- Align
- [:div.align-icons
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.text-align-left" (sc/get-tooltip :text-align-left))
- :class (dom/classnames :current (= "left" text-align))
- :on-click #(handle-change % "left")}
- i/text-align-left]
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.text-align-center" (sc/get-tooltip :text-align-center))
- :class (dom/classnames :current (= "center" text-align))
- :on-click #(handle-change % "center")}
- i/text-align-center]
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.text-align-right" (sc/get-tooltip :text-align-right))
- :class (dom/classnames :current (= "right" text-align))
- :on-click #(handle-change % "right")}
- i/text-align-right]
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.text-align-justify" (sc/get-tooltip :text-align-justify))
- :class (dom/classnames :current (= "justify" text-align))
- :on-click #(handle-change % "justify")}
- i/text-align-justify]]))
+ (if new-css-system
+ [:div {:class (stl/css :align-options)}
+ [:& radio-buttons {:selected text-align
+ :on-change handle-change
+ :name "align-text-options"}
+ [:& radio-button {:value "left"
+ :id "text-align-left"
+ :title (tr "workspace.options.text-options.text-align-left" (sc/get-tooltip :text-align-left))
+ :icon i/text-align-left-refactor}]
+ [:& radio-button {:value "center"
+ :id "text-align-center"
+ :title (tr "workspace.options.text-options.text-align-center" (sc/get-tooltip :text-align-center))
+ :icon i/text-align-center-refactor}]
+ [:& radio-button {:value "right"
+ :id "text-align-right"
+ :title (tr "workspace.options.text-options.text-align-right" (sc/get-tooltip :text-align-right))
+ :icon i/text-align-right-refactor}]
+ [:& radio-button {:value "justify"
+ :id "text-align-justify"
+ :title (tr "workspace.options.text-options.text-align-justify" (sc/get-tooltip :text-align-justify))
+ :icon i/text-justify-refactor}]]]
+ [:div.align-icons
+ [:span.tooltip.tooltip-bottom
+ {:alt (tr "workspace.options.text-options.text-align-left" (sc/get-tooltip :text-align-left))
+ :class (dom/classnames :current (= "left" text-align))
+ :data-value "left"
+ :on-click handle-change}
+ i/text-align-left]
+ [:span.tooltip.tooltip-bottom
+ {:alt (tr "workspace.options.text-options.text-align-center" (sc/get-tooltip :text-align-center))
+ :class (dom/classnames :current (= "center" text-align))
+ :data-value "center"
+ :on-click handle-change}
+ i/text-align-center]
+ [:span.tooltip.tooltip-bottom
+ {:alt (tr "workspace.options.text-options.text-align-right" (sc/get-tooltip :text-align-right))
+ :class (dom/classnames :current (= "right" text-align))
+ :data-value "right"
+ :on-click handle-change}
+ i/text-align-right]
+ [:span.tooltip.tooltip-bottom
+ {:alt (tr "workspace.options.text-options.text-align-justify" (sc/get-tooltip :text-align-justify))
+ :class (dom/classnames :current (= "justify" text-align))
+ :data-value "justify"
+ :on-click handle-change}
+ i/text-align-justify]])))
(mf/defc text-direction-options
[{:keys [values on-change on-blur] :as props}]
- (let [direction (:text-direction values)
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ direction (:text-direction values)
handle-change
- (fn [_ val]
- (on-change {:text-direction val})
- (when (some? on-blur) (on-blur)))]
+ (mf/use-fn
+ (mf/deps direction)
+ (fn [value]
+ (let [val (if new-css-system
+ value
+ (-> (dom/get-current-target value)
+ (dom/get-data "value")))
+ dir (if (= val direction)
+ "none"
+ val)]
+ (on-change {:text-direction dir})
+ (when (some? on-blur) (on-blur)))))]
+
+ (if new-css-system
+ [:div {:class (stl/css :text-direction-options)}
+ [:& radio-buttons {:selected direction
+ :on-change handle-change
+ :name "text-direction-options"}
+ [:& nilable-option {:value "ltr"
+ :id "ltr-text-direction"
+ :title (tr "workspace.options.text-options.direction-ltr")
+ :icon i/text-ltr-refactor}]
+ [:& nilable-option {:value "rtl"
+ :id "rtl-text-direction"
+ :title (tr "workspace.options.text-options.direction-rtl")
+ :icon i/text-rtl-refactor}]]]
;; --- Align
[:div.align-icons
[:span.tooltip.tooltip-bottom-left
{:alt (tr "workspace.options.text-options.direction-ltr")
:class (dom/classnames :current (= "ltr" direction))
- :on-click #(handle-change % "ltr")}
+ :data-value "ltr"
+ :on-click handle-change}
i/text-direction-ltr]
[:span.tooltip.tooltip-bottom-left
{:alt (tr "workspace.options.text-options.direction-rtl")
:class (dom/classnames :current (= "rtl" direction))
- :on-click #(handle-change % "rtl")}
- i/text-direction-rtl]]))
+ :data-value "rtl"
+ :on-click handle-change}
+ i/text-direction-rtl]])))
(mf/defc vertical-align
[{:keys [values on-change on-blur] :as props}]
(let [{:keys [vertical-align]} values
+ new-css-system (mf/use-ctx ctx/new-css-system)
vertical-align (or vertical-align "top")
handle-change
- (fn [_ new-align]
- (on-change {:vertical-align new-align})
- (when (some? on-blur) (on-blur)))]
+ (mf/use-fn
+ (fn [value]
+ (let [new-align (if new-css-system
+ value
+ (-> (dom/get-current-target value)
+ (dom/get-data "value")))]
+ (on-change {:vertical-align new-align})
+ (when (some? on-blur) (on-blur)))))]
- [:div.align-icons
- [:span.tooltip.tooltip-bottom-left
- {:alt (tr "workspace.options.text-options.align-top")
- :class (dom/classnames :current (= "top" vertical-align))
- :on-click #(handle-change % "top")}
- i/align-top]
- [:span.tooltip.tooltip-bottom-left
- {:alt (tr "workspace.options.text-options.align-middle")
- :class (dom/classnames :current (= "center" vertical-align))
- :on-click #(handle-change % "center")}
- i/align-middle]
- [:span.tooltip.tooltip-bottom-left
- {:alt (tr "workspace.options.text-options.align-bottom")
- :class (dom/classnames :current (= "bottom" vertical-align))
- :on-click #(handle-change % "bottom")}
- i/align-bottom]]))
+ (if new-css-system
+ [:div {:class (stl/css :vertical-align-options)}
+ [:& radio-buttons {:selected vertical-align
+ :on-change handle-change
+ :name "vertical-align-text-options"}
+ [:& radio-button {:value "top"
+ :id "vertical-text-align-top"
+ :title (tr "workspace.options.text-options.align-top")
+ :icon i/text-top-refactor}]
+ [:& radio-button {:value "center"
+ :id "vertical-text-align-center"
+ :title (tr "workspace.options.text-options.align-middle")
+ :icon i/text-middle-refactor}]
+ [:& radio-button {:value "bottom"
+ :id "vertical-text-align-bottom"
+ :title (tr "workspace.options.text-options.align-bottom")
+ :icon i/text-bottom-refactor}]]]
+ [:div.align-icons
+ [:span.tooltip.tooltip-bottom-left
+ {:alt (tr "workspace.options.text-options.align-top")
+ :class (dom/classnames :current (= "top" vertical-align))
+ :data-value "top"
+ :on-click handle-change}
+ i/align-top]
+ [:span.tooltip.tooltip-bottom-left
+ {:alt (tr "workspace.options.text-options.align-middle")
+ :class (dom/classnames :current (= "center" vertical-align))
+ :data-value "center"
+ :on-click handle-change}
+ i/align-middle]
+ [:span.tooltip.tooltip-bottom-left
+ {:alt (tr "workspace.options.text-options.align-bottom")
+ :class (dom/classnames :current (= "bottom" vertical-align))
+ :data-value "bottom"
+ :on-click handle-change}
+ i/align-bottom]])))
(mf/defc grow-options
[{:keys [ids values on-blur] :as props}]
- (let [grow-type (:grow-type values)
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ grow-type (:grow-type values)
+
handle-change-grow
- (fn [_ grow-type]
- (let [uid (js/Symbol)]
+ (mf/use-fn
+ (mf/deps ids)
+ (fn [value]
+ (let [uid (js/Symbol)
+
+ grow-type (if new-css-system
+ (keyword value)
+ (-> (dom/get-current-target value)
+ (dom/get-data "value")
+ (keyword)))]
(st/emit!
(dwu/start-undo-transaction uid)
(dch/update-shapes ids #(assoc % :grow-type grow-type)))
;; We asynchronously commit so every sychronous event is resolved first and inside the transaction
(ts/schedule #(st/emit! (dwu/commit-undo-transaction uid))))
- (when (some? on-blur) (on-blur)))]
+ (when (some? on-blur) (on-blur))))]
- [:div.align-icons
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.grow-fixed")
- :class (dom/classnames :current (= :fixed grow-type))
- :on-click #(handle-change-grow % :fixed)}
- i/auto-fix]
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.grow-auto-width")
- :class (dom/classnames :current (= :auto-width grow-type))
- :on-click #(handle-change-grow % :auto-width)}
- i/auto-width]
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.grow-auto-height")
- :class (dom/classnames :current (= :auto-height grow-type))
- :on-click #(handle-change-grow % :auto-height)}
- i/auto-height]]))
+ (if new-css-system
+ [:div {:class (stl/css :grow-options)}
+ [:& radio-buttons {:selected (d/name grow-type)
+ :on-change handle-change-grow
+ :name "grow-text-options"}
+ [:& radio-button {:value "fixed"
+ :id "text-fixed-grow"
+ :title (tr "workspace.options.text-options.grow-fixed")
+ :icon i/text-fixed-refactor}]
+ [:& radio-button {:value "auto-width"
+ :id "text-auto-width-grow"
+ :title (tr "workspace.options.text-options.grow-auto-width")
+ :icon i/text-auto-width-refactor}]
+ [:& radio-button {:value "auto-height"
+ :id "text-auto-height-grow"
+ :title (tr "workspace.options.text-options.grow-auto-height")
+ :icon i/text-auto-height-refactor}]]]
+
+ [:div.align-icons
+ [:span.tooltip.tooltip-bottom
+ {:alt (tr "workspace.options.text-options.grow-fixed")
+ :class (dom/classnames :current (= :fixed grow-type))
+ :data-value "fixed"
+ :on-click handle-change-grow}
+ i/auto-fix]
+ [:span.tooltip.tooltip-bottom
+ {:alt (tr "workspace.options.text-options.grow-auto-width")
+ :data-value "auto-width"
+ :class (dom/classnames :current (= :auto-width grow-type))
+ :on-click handle-change-grow}
+ i/auto-width]
+ [:span.tooltip.tooltip-bottom
+ {:alt (tr "workspace.options.text-options.grow-auto-height")
+ :class (dom/classnames :current (= :auto-height grow-type))
+ :data-value "auto-height"
+ :on-click handle-change-grow}
+ i/auto-height]])))
(mf/defc text-decoration-options
[{:keys [values on-change on-blur] :as props}]
- (let [text-decoration (or (:text-decoration values) "none")
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ text-decoration (or (:text-decoration values) "none")
handle-change
- (fn [_ type]
- (on-change {:text-decoration type})
- (when (some? on-blur) (on-blur)))]
- [:div.align-icons
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.none")
- :class (dom/classnames :current (= "none" text-decoration))
- :on-click #(handle-change % "none")}
- i/minus]
+ (mf/use-fn
+ (mf/deps text-decoration)
+ (fn [value]
+ (let [val (if new-css-system
+ value
+ (-> (dom/get-current-target value)
+ (dom/get-data "value")))
+ decoration (if (= val text-decoration)
+ "none"
+ val)]
+ (on-change {:text-decoration decoration})
+ (when (some? on-blur) (on-blur)))))]
+ (if new-css-system
+ [:div {:class (stl/css :text-decoration-options)}
+ [:& radio-buttons {:selected text-decoration
+ :on-change handle-change
+ :name "text-decoration-options"}
+ [:& nilable-option {:value "underline"
+ :id "underline-text-decoration"
+ :title (tr "workspace.options.text-options.underline" (sc/get-tooltip :underline))
+ :icon i/text-underlined-refactor}]
+ [:& nilable-option {:value "line-through"
+ :id "line-through-text-decoration"
+ :title (tr "workspace.options.text-options.strikethrough" (sc/get-tooltip :line-through))
+ :icon i/text-stroked-refactor}]]]
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.underline" (sc/get-tooltip :underline))
- :class (dom/classnames :current (= "underline" text-decoration))
- :on-click #(handle-change % "underline")}
- i/underline]
+ [:div.align-icons
+ [:span.tooltip.tooltip-bottom
+ {:alt (tr "workspace.options.text-options.none")
+ :class (dom/classnames :current (= "none" text-decoration))
+ :data-value "none"
+ :on-click handle-change}
+ i/minus]
- [:span.tooltip.tooltip-bottom
- {:alt (tr "workspace.options.text-options.strikethrough" (sc/get-tooltip :line-through))
- :class (dom/classnames :current (= "line-through" text-decoration))
- :on-click #(handle-change % "line-through")}
- i/strikethrough]]))
+ [:span.tooltip.tooltip-bottom
+ {:alt (tr "workspace.options.text-options.underline" (sc/get-tooltip :underline))
+ :class (dom/classnames :current (= "underline" text-decoration))
+ :data-value "underline"
+ :on-click handle-change}
+ i/underline]
+
+ [:span.tooltip.tooltip-bottom
+ {:alt (tr "workspace.options.text-options.strikethrough" (sc/get-tooltip :line-through))
+ :class (dom/classnames :current (= "line-through" text-decoration))
+ :data-value "line-through"
+ :on-click handle-change}
+ i/strikethrough]])))
(mf/defc text-menu
{::mf/wrap [mf/memo]}
[{:keys [ids type values] :as props}]
- (let [file-id (mf/use-ctx ctx/current-file-id)
- typographies (mf/deref refs/workspace-file-typography)
- shared-libs (mf/deref refs/workspace-libraries)
- label (case type
- :multiple (tr "workspace.options.text-options.title-selection")
- :group (tr "workspace.options.text-options.title-group")
- (tr "workspace.options.text-options.title"))
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ file-id (mf/use-ctx ctx/current-file-id)
+ typographies (mf/deref refs/workspace-file-typography)
+ shared-libs (mf/deref refs/workspace-libraries)
+ label (case type
+ :multiple (tr "workspace.options.text-options.title-selection")
+ :group (tr "workspace.options.text-options.title-group")
+ (tr "workspace.options.text-options.title"))
+
+ state* (mf/use-state {:main-menu true
+ :more-options false})
+ state (deref state*)
+ main-menu-open? (:main-menu state)
+ more-options-open? (:more-options state)
+
+ toggle-main-menu
+ (mf/use-fn
+ (mf/deps main-menu-open?)
+ #(swap! state* assoc-in [:main-menu] (not main-menu-open?)))
+
+ toggle-more-options
+ (mf/use-fn
+ (mf/deps more-options-open?)
+ #(swap! state* assoc-in [:more-options] (not more-options-open?)))
+
+ typography-id (:typography-ref-id values)
+ typography-file (:typography-ref-file values)
emit-update!
(mf/use-callback
@@ -188,17 +353,17 @@
(mf/deps values file-id shared-libs)
(fn []
(cond
- (and (:typography-ref-id values)
- (not= (:typography-ref-id values) :multiple)
- (not= (:typography-ref-file values) file-id))
+ (and typography-id
+ (not= typography-id :multiple)
+ (not= typography-file file-id))
(-> shared-libs
- (get-in [(:typography-ref-file values) :data :typographies (:typography-ref-id values)])
- (assoc :file-id (:typography-ref-file values)))
+ (get-in [typography-file :data :typographies typography-id])
+ (assoc :file-id typography-file))
- (and (:typography-ref-id values)
- (not= (:typography-ref-id values) :multiple)
- (= (:typography-ref-file values) file-id))
- (get typographies (:typography-ref-id values)))))
+ (and typography-id
+ (not= typography-id :multiple)
+ (= typography-file file-id))
+ (get typographies typography-id))))
on-convert-to-typography
(fn [_]
@@ -243,39 +408,87 @@
(let [node (dom/get-element-by-class "public-DraftEditor-content")]
(dom/focus! node))))))}]
- [:div.element-set
- [:div.element-set-title
- [:span label]
- (when (and (not typography) (not multiple?))
- [:div.add-page {:on-click on-convert-to-typography} i/close])]
+ (if new-css-system
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? true
+ :collapsed? (not main-menu-open?)
+ :on-collapsed toggle-main-menu
+ :title label
+ :class (stl/css :title-spacing-text)}
+ (when (and (not typography) (not multiple?))
+ [:button {:class (stl/css :add-typography)
+ :on-click on-convert-to-typography}
+ i/add-refactor])]]
- (cond
- typography
- [:& typography-entry {:typography typography
- :local? (= (:typography-ref-file values) file-id)
- :file (get shared-libs (:typography-ref-file values))
- :on-detach handle-detach-typography
- :on-change handle-change-typography}]
+ (when main-menu-open?
+ [:div {:class (stl/css :element-content)}
+ (cond
+ typography
+ [:& typography-entry {:typography typography
+ :local? (= typography-file file-id)
+ :file (get shared-libs typography-file)
+ :on-detach handle-detach-typography
+ :on-change handle-change-typography}]
- (= (:typography-ref-id values) :multiple)
- [:div.multiple-typography
- [:div.multiple-typography-text (tr "workspace.libraries.text.multiple-typography")]
- [:div.multiple-typography-button {:on-click handle-detach-typography
- :title (tr "workspace.libraries.text.multiple-typography-tooltip")} i/unchain]]
+ (= typography-id :multiple)
+ [:div {:class (stl/css :multiple-typography)}
+ [:span {:class (stl/css :multiple-text)} (tr "workspace.libraries.text.multiple-typography")]
+ [:div {:class (stl/css :multiple-typography-button)
+ :on-click handle-detach-typography
+ :title (tr "workspace.libraries.text.multiple-typography-tooltip")}
+ i/detach-refactor]]
- :else
- [:> typography-options opts])
+ :else
+ [:> typography-options opts])
- [:div.element-set-content
+ [:div {:class (stl/css :text-align-options)}
+ [:> text-align-options opts]
+ [:> grow-options opts]
+ [:button {:class (stl/css :more-options)
+ :on-click toggle-more-options}
+ i/menu-refactor]]
- [:div.row-flex
- [:> text-align-options opts]
- [:> vertical-align opts]]
+ (when more-options-open?
+ [:div {:class (stl/css :text-decoration-options)}
+ [:> vertical-align opts]
+ [:> text-decoration-options opts]
+ [:> text-direction-options opts]])])]
- [:div.row-flex
- [:> text-decoration-options opts]
- [:> text-direction-options opts]]
- [:div.row-flex
- [:> grow-options opts]
- [:div.align-icons]]]]))
+ [:div.element-set
+ [:div.element-set-title
+ [:span label]
+ (when (and (not typography) (not multiple?))
+ [:div.add-page {:on-click on-convert-to-typography} i/close])]
+
+ (cond
+ typography
+ [:& typography-entry {:typography typography
+ :local? (= typography-file file-id)
+ :file (get shared-libs typography-file)
+ :on-detach handle-detach-typography
+ :on-change handle-change-typography}]
+
+ (= typography-id :multiple)
+ [:div.multiple-typography
+ [:div.multiple-typography-text (tr "workspace.libraries.text.multiple-typography")]
+ [:div.multiple-typography-button {:on-click handle-detach-typography
+ :title (tr "workspace.libraries.text.multiple-typography-tooltip")} i/unchain]]
+
+ :else
+ [:> typography-options opts])
+
+ [:div.element-set-content
+
+ [:div.row-flex
+ [:> text-align-options opts]
+ [:> vertical-align opts]]
+
+ [:div.row-flex
+ [:> text-decoration-options opts]
+ [:> text-direction-options opts]]
+
+ [:div.row-flex
+ [:> grow-options opts]
+ [:div.align-icons]]]])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.scss
new file mode 100644
index 0000000000..e142d4d5ac
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.scss
@@ -0,0 +1,71 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.element-set {
+ .element-title {
+ .add-typography {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ .element-content {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ .multiple-typography {
+ display: flex;
+ align-items: center;
+ padding: 0 $s-8;
+ gap: $s-4;
+ border-radius: $s-8;
+ background-color: var(--input-background-color);
+ height: $s-32;
+ flex-grow: 1;
+ .multiple-text {
+ @include titleTipography;
+ flex-grow: 1;
+ color: var(--input-foreground-color-active);
+ }
+ .multiple-typography-button {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ .text-align-options {
+ display: flex;
+ gap: $s-4;
+ .align-options,
+ .text-direction-options,
+ .vertical-align-options,
+ .grow-options,
+ .text-decoration-options {
+ height: $s-32;
+ }
+ .more-options {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ .text-decoration-options {
+ display: flex;
+ gap: $s-4;
+ }
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs
index 5a90e4ab01..55d64f06c1 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs
@@ -5,7 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.menus.typography
- (:require-macros [app.main.style :refer [css]])
+ (:require-macros [app.main.style :as stl])
(:require
["react-virtualized" :as rvt]
[app.common.data :as d]
@@ -73,15 +73,14 @@
(dom/scroll-into-view! element))))))
(if new-css-system
- [:div {:class (css :font-wrapper)
+ [:div {:class (stl/css :font-wrapper)
:style style
:ref item-ref
:on-click on-click}
- [:div {:class (dom/classnames
- (css :font-item) true
- (css :selected) current?)}
- [:span {:class (css :label)} (:name font)]
- [:span {:class (css :icon)} (when current? i/tick-refactor)]]]
+ [:div {:class (stl/css-case :font-item true
+ :selected current?)}
+ [:span {:class (stl/css :label)} (:name font)]
+ [:span {:class (stl/css :icon)} (when current? i/tick-refactor)]]]
[:div.font-item {:ref item-ref
:style style
@@ -186,9 +185,9 @@
(.scrollToPosition ^js inst offset)))))
(if new-css-system
- [:div {:class (css :font-selector)}
- [:div {:class (css :font-selector-dropdown)}
- [:div {:class (css :header)}
+ [:div {:class (stl/css :font-selector)}
+ [:div {:class (stl/css :font-selector-dropdown)}
+ [:div {:class (stl/css :header)}
[:& search-bar {:on-change on-filter-change
:value (:term @state)
:placeholder (tr "workspace.options.search-font")}]
@@ -202,7 +201,7 @@
:on-click on-select-and-close
:current? (= (:id font) (:id @selected))}])])]
- [:div {:class (css :fonts-list)}
+ [:div {:class (stl/css :fonts-list)}
[:> rvt/AutoSizer {}
(fn [props]
(let [width (unchecked-get props "width")
@@ -341,7 +340,7 @@
:show-recent show-recent}])
[:div
- {:class (css :font-option)
+ {:class (stl/css :font-option)
:on-click #(reset! open-selector? true)}
(cond
(= :multiple font-id)
@@ -349,31 +348,30 @@
(some? font)
[:*
- [:span {:class (css :name)}
+ [:span {:class (stl/css :name)}
(:name font)]
- [:span {:class (css :icon)}
+ [:span {:class (stl/css :icon)}
i/arrow-refactor]]
:else
(tr "dashboard.fonts.deleted-placeholder"))]
-
- [:div {:class (css :font-modifiers)}
- [:div {:class (css :font-size-options)}
- (let [sizes [8 9 10 11 12 14 16 18 24 36 48 72]
- basic-size-options (map (fn [number]
- {:value (dm/str number) :key (dm/str "size-" number) :label (dm/str number)}) sizes)
- size-options (if (= font-size :multiple)
- (conj {:value :key :mulitple-sizes :multiple :label "--"} basic-size-options)
- basic-size-options)]
-
- [:& select
- {:class (css :font-size-select)
- :default-value (attr->string font-size)
+ [:div {:class (stl/css :font-modifiers)}
+ [:div {:class (stl/css :font-size-options)}
+ (let [size-options [8 9 10 11 12 14 16 18 24 36 48 72]
+ size-options (if (= font-size :multiple) (into [""] size-options) size-options)]
+ [:& editable-select
+ {:value (attr->string font-size)
+ :class (stl/css :font-size-select)
+ :input-class (stl/css :numeric-input)
:options size-options
+ :type "number"
+ :placeholder "--"
+ :min 3
+ :max 1000
:on-change on-font-size-change
:on-blur on-blur}])]
- [:div {:class (css :font-variant-options)}
+ [:div {:class (stl/css :font-variant-options)}
(let [basic-variant-options (map (fn [variant]
{:value (:id variant) :key (pr-str variant) :label (:name variant)}) (:variants font))
variant-options (if (= font-size :multiple)
@@ -381,7 +379,7 @@
basic-variant-options)]
;; TODO Add disabled mode
[:& select
- {:class (css :font-variant-select)
+ {:class (stl/css :font-variant-select)
:default-value (attr->string font-variant-id)
:options variant-options
:on-change on-font-variant-change
@@ -451,34 +449,33 @@
(fn [value attr]
(on-change {attr (str value)}))]
(if new-css-system
- [:div {:class (css :spacing-options)}
- [:div {:class (css :line-height)}
- [:span {:class (css :icon)
+ [:div {:class (stl/css :spacing-options)}
+ [:div {:class (stl/css :line-height)}
+ [:span {:class (stl/css :icon)
:alt (tr "workspace.options.text-options.line-height")}
i/text-lineheight-refactor]
-
[:> numeric-input*
{:min -200
:max 200
:step 0.1
:default "1.2"
- :class (css :line-height-input)
+ :class (stl/css :line-height-input)
:value (attr->string line-height)
:placeholder (tr "settings.multiple")
:nillable line-height-nillable
:on-change #(handle-change % :line-height)
:on-blur on-blur}]]
- [:div {:class (css :letter-spacing)}
+ [:div {:class (stl/css :letter-spacing)}
[:span
- {:class (css :icon)
+ {:class (stl/css :icon)
:alt (tr "workspace.options.text-options.letter-spacing")}
i/text-letterspacing-refactor]
[:> numeric-input*
{:min -200
:max 200
:step 0.1
- :class (css :letter-spacing-input)
+ :class (stl/css :letter-spacing-input)
:value (attr->string letter-spacing)
:placeholder (tr "settings.multiple")
:on-change #(handle-change % :letter-spacing)
@@ -525,7 +522,7 @@
(on-change {:text-transform type}))
(when (some? on-blur) (on-blur)))]
(if new-css-system
- [:div {:class (css :text-transform)}
+ [:div {:class (stl/css :text-transform)}
[:& radio-buttons {:selected text-transform
:on-change handle-change
:name "text-transform"}
@@ -574,9 +571,9 @@
:show-recent show-recent}]
(if new-css-system
- [:div {:class (css :typography-options)}
+ [:div {:class (stl/css :typography-options)}
[:> font-options opts]
- [:div {:class (css :typography-variations)}
+ [:div {:class (stl/css :typography-variations)}
[:> spacing-options opts]
[:> text-transform-options opts]]]
@@ -601,26 +598,26 @@
(when visible?
[:div {:ref ref
- :class (css :advanced-options-wrapper)}
+ :class (stl/css :advanced-options-wrapper)}
(if ^boolean editable?
[:*
- [:div {:class (css :font-name-wrapper)}
+ [:div {:class (stl/css :font-name-wrapper)}
[:div
- {:class (dom/classnames (css :typography-sample-input) true)
+ {:class (stl/css :typography-sample-input)
:style {:font-family (:font-family typography)
:font-weight (:font-weight typography)
:font-style (:font-style typography)}}
(tr "workspace.assets.typography.sample")]
[:input
- {:class (css :adv-typography-name)
+ {:class (stl/css :adv-typography-name)
:type "text"
:ref name-input-ref
:default-value (:name typography)
:on-key-down on-key-down
:on-blur on-name-blur}]
- [:div {:class (css :action-btn)
+ [:div {:class (stl/css :action-btn)
:on-click on-close}
i/tick-refactor]]
@@ -738,49 +735,49 @@
(dom/select-text! node)))))
(if new-css-system
[:*
- [:div {:class (dom/classnames (css :typography-entry) true
- (css :selected) ^boolean selected?)
+ [:div {:class (stl/css-case :typography-entry true
+ :selected ^boolean selected?)
:style {:display (when ^boolean open? "none")}}
(if renaming?
- [:div {:class (css :font-name-wrapper)}
+ [:div {:class (stl/css :font-name-wrapper)}
[:div
- {:class (dom/classnames (css :typography-sample-input) true)
+ {:class (stl/css :typography-sample-input)
:style {:font-family (:font-family typography)
:font-weight (:font-weight typography)
:font-style (:font-style typography)}}
(tr "workspace.assets.typography.sample")]
[:input
- {:class (css :adv-typography-name)
+ {:class (stl/css :adv-typography-name)
:type "text"
:ref name-input-ref
:default-value (:name typography)
:on-key-down on-key-down
:on-blur on-name-blur}]]
[:div
- {:class (dom/classnames (css :typography-selection-wrapper) true
- (css :is-selectable) ^boolean on-click)
+ {:class (stl/css-case :typography-selection-wrapper true
+ :is-selectable ^boolean on-click)
:on-click on-click
:on-context-menu on-context-menu}
[:div
- {:class (dom/classnames (css :typography-sample) true)
+ {:class (stl/css :typography-sample)
:style {:font-family (:font-family typography)
:font-weight (:font-weight typography)
:font-style (:font-style typography)}}
(tr "workspace.assets.typography.sample")]
- [:div {:class (dom/classnames (css :typography-name) true)
+ [:div {:class (stl/css :typography-name)
:title (:name typography)} (:name typography)]
(when-not name-only?
- [:div {:class (dom/classnames (css :typography-font) true)
+ [:div {:class (stl/css :typography-font)
:title (:name font-data)}
(:name font-data)])])
(when ^boolean on-detach
- [:div {:class (dom/classnames (css :element-set-actions) true)}
+ [:div {:class (stl/css :element-set-actions)}
[:div
- {:class (dom/classnames (css :element-set-actions-button) true)
+ {:class (stl/css :element-set-actions-button)
:on-pointer-enter on-pointer-enter
:on-pointer-leave on-pointer-leave
:on-click on-detach}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.scss
index 8ffe111de0..41bdb7e7ea 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.scss
@@ -109,137 +109,109 @@
height: 100%;
width: 100%;
background-color: var(--assets-title-background-color);
+}
- .typography-options {
- position: relative;
- .font-option {
- @include titleTipography;
+.typography-options {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ .font-option {
+ @include titleTipography;
+ @extend .asset-element;
+ padding-right: 0;
+ cursor: pointer;
+ .name {
+ flex-grow: 1;
+ }
+ .icon {
+ @include flexCenter;
+ height: $s-28;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
+ transform: rotate(90deg);
+ }
+ }
+ }
+ .font-modifiers {
+ display: flex;
+ gap: $s-4;
+ .font-size-options {
@extend .asset-element;
- padding-right: 0;
- margin-bottom: $s-4;
- cursor: pointer;
- .name {
- flex-grow: 1;
+ @include titleTipography;
+ flex-grow: 1;
+ width: $s-60;
+ margin: 0;
+ padding: 0;
+ border: $s-1 solid var(--input-background-color);
+ position: relative;
+ .font-size-select {
+ height: $s-32;
+ .numeric-input {
+ @extend .input-base;
+ margin: 0;
+ padding: 0;
+ }
+ span {
+ @include flexCenter;
+ svg {
+ @extend .button-icon;
+ }
+ }
}
.icon {
@include flexCenter;
height: $s-28;
- width: $s-28;
+ min-width: $s-28;
svg {
@extend .button-icon;
stroke: var(--icon-foreground);
transform: rotate(90deg);
}
}
- }
- .font-modifiers {
- display: flex;
- gap: $s-4;
- .font-size-options {
- @extend .asset-element;
+ .font-size-select {
+ @include removeInputStyle;
@include titleTipography;
+ height: 100%;
+ width: 100%;
+ margin: 0;
padding: 0;
- margin-bottom: $s-4;
- flex-grow: 1;
- .icon {
- @include flexCenter;
- height: $s-28;
- min-width: $s-28;
- svg {
- @extend .button-icon;
- stroke: var(--icon-foreground);
- transform: rotate(90deg);
- }
- }
- .font-size-select {
- @include removeInputStyle;
- @include titleTipography;
- height: 100%;
- width: 100%;
- margin: 0;
- padding: 0;
- }
- }
- .font-variant-options {
- @extend .asset-element;
- @include titleTipography;
- padding: 0;
- margin-bottom: $s-4;
- flex-grow: 2;
- .icon {
- @include flexCenter;
- height: $s-28;
- min-width: $s-28;
- svg {
- @extend .button-icon;
- stroke: var(--icon-foreground);
- transform: rotate(90deg);
- }
- }
- .font-variant-select {
- @include removeInputStyle;
- @include titleTipography;
- height: 100%;
- width: 100%;
- margin: 0;
- color: var(--assets-item-name-foreground-color);
- option {
- color: var(--assets-item-name-foreground-color);
- }
- &:hover {
- color: var(--assets-item-name-foreground-color-hover);
- option {
- color: var(--assets-item-name-foreground-color-hover);
- }
- }
- }
}
}
- .typography-variations {
+ .font-variant-options {
+ padding: 0;
+ flex-grow: 2;
+ }
+ }
+ .typography-variations {
+ display: flex;
+ gap: $s-4;
+ align-items: center;
+ .spacing-options {
display: flex;
- gap: $s-4;
align-items: center;
- .spacing-options {
- display: flex;
- align-items: center;
- gap: $s-4;
- .line-height,
- .letter-spacing {
- @extend .asset-element;
- margin-bottom: $s-4;
- .icon {
- @include flexCenter;
- width: $s-28;
- svg {
- @extend .button-icon-small;
- stroke: var(--icon-foreground);
- }
- }
- .line-height-input,
- .letter-spacing-input {
- @include removeInputStyle;
- @include titleTipography;
- height: 100%;
- width: 100%;
- margin: 0;
- color: var(--assets-item-name-foreground-color);
- &:hover,
- &:active,
- &:focus {
- color: var(--assets-item-name-foreground-color-hover);
- }
+ gap: $s-4;
+ .line-height,
+ .letter-spacing {
+ @extend .input-element;
+ .icon {
+ @include flexCenter;
+ width: $s-28;
+ svg {
+ @extend .button-icon-small;
}
}
}
- .text-transform {
- @extend .asset-element;
- width: fit-content;
- padding: 0;
- margin-bottom: $s-4;
+ }
+ .text-transform {
+ @extend .asset-element;
+ width: fit-content;
+ padding: 0;
+ background-color: var(--radio-btns-background-color);
+ &:hover {
background-color: var(--radio-btns-background-color);
- &:hover {
- background-color: var(--radio-btns-background-color);
- }
}
}
}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/page.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/page.cljs
index e5a9a92ad6..fa0f3d23df 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/page.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/page.cljs
@@ -6,12 +6,15 @@
(ns app.main.ui.workspace.sidebar.options.page
"Page options menu entries."
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.colors :as clr]
[app.main.data.workspace :as dw]
[app.main.data.workspace.undo :as dwu]
[app.main.refs :as refs]
[app.main.store :as st]
+ [app.main.ui.components.title-bar :refer [title-bar]]
+ [app.main.ui.context :as ctx]
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
[app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf]))
@@ -20,20 +23,38 @@
{::mf/wrap [mf/memo]
::mf/wrap-props false}
[]
- (let [options (mf/deref refs/workspace-page-options)
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ options (mf/deref refs/workspace-page-options)
on-change (mf/use-fn #(st/emit! (dw/change-canvas-color %)))
on-open (mf/use-fn #(st/emit! (dwu/start-undo-transaction :options)))
on-close (mf/use-fn #(st/emit! (dwu/commit-undo-transaction :options)))]
- [:div.element-set
- [:div.element-set-title (tr "workspace.options.canvas-background")]
- [:div.element-set-content
- [:& color-row
- {:disable-gradient true
- :disable-opacity true
- :title (tr "workspace.options.canvas-background")
- :color {:color (get options :background clr/canvas)
- :opacity 1}
- :on-change on-change
- :on-open on-open
- :on-close on-close}]]]))
+ (if new-css-system
+ [:div {:class (stl/css :element-set)}
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? false
+ :title (tr "workspace.options.canvas-background")
+ :class (stl/css :title-spacing-page)}]]
+ [:div {:class (stl/css :element-content)}
+ [:& color-row
+ {:disable-gradient true
+ :disable-opacity true
+ :title (tr "workspace.options.canvas-background")
+ :color {:color (get options :background clr/canvas)
+ :opacity 1}
+ :on-change on-change
+ :on-open on-open
+ :on-close on-close}]]]
+
+ [:div.element-set
+ [:div.element-set-title (tr "workspace.options.canvas-background")]
+ [:div.element-set-content
+ [:& color-row
+ {:disable-gradient true
+ :disable-opacity true
+ :title (tr "workspace.options.canvas-background")
+ :color {:color (get options :background clr/canvas)
+ :opacity 1}
+ :on-change on-change
+ :on-open on-open
+ :on-close on-close}]]])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/page.scss b/frontend/src/app/main/ui/workspace/sidebar/options/page.scss
new file mode 100644
index 0000000000..da131647f1
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/page.scss
@@ -0,0 +1,7 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs
index 4c47ab4850..c2ad44f5e0 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs
@@ -5,6 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.rows.color-row
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
@@ -13,7 +14,7 @@
[app.main.data.workspace.libraries :as dwl]
[app.main.refs :as refs]
[app.main.store :as st]
- [app.main.ui.components.color-bullet :as cb]
+ [app.main.ui.components.color-bullet-new :as cb]
[app.main.ui.components.color-input :refer [color-input*]]
[app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.context :as ctx]
@@ -42,7 +43,8 @@
[{:keys [index color disable-gradient disable-opacity on-change
on-reorder on-detach on-open on-close title on-remove
disable-drag on-focus on-blur select-only select-on-focus]}]
- (let [current-file-id (mf/use-ctx ctx/current-file-id)
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ current-file-id (mf/use-ctx ctx/current-file-id)
file-colors (mf/deref refs/workspace-file-colors)
shared-libs (mf/deref refs/workspace-libraries)
hover-detach (mf/use-state false)
@@ -53,6 +55,11 @@
color-name (dm/get-in src-colors [(:id color) :name])
+ multiple-colors? (uc/multiple? color)
+ library-color? (and (:id color) color-name (not multiple-colors?))
+ gradient-color? (and (not multiple-colors?)
+ (:gradient color)
+ (get-in color [:gradient :type]))
parse-color
(mf/use-fn
(fn [color]
@@ -79,7 +86,7 @@
(assoc :color new-value)
(dissoc :gradient))]
(st/emit! (dwl/add-recent-color color)
- (on-change color)))))
+ (on-change color)))))
handle-opacity-change
(mf/use-fn
@@ -90,14 +97,14 @@
:id nil
:file-id nil)]
(st/emit! (dwl/add-recent-color color)
- (on-change color)))))
+ (on-change color)))))
handle-click-color
(mf/use-fn
(mf/deps disable-gradient disable-opacity on-change on-close on-open)
(fn [color event]
(let [color (cond
- (uc/multiple? color)
+ multiple-colors?
{:color default-color
:opacity 1}
@@ -149,73 +156,153 @@
(when (not= prev-color color)
(modal/update-props! :colorpicker {:data (parse-color color)})))
- [:div.row-flex.color-data {:title title
- :class (dom/classnames
- :dnd-over-top (= (:over dprops) :top)
- :dnd-over-bot (= (:over dprops) :bot))
- :ref dref}
- [:& cb/color-bullet {:color (cond-> color
- (nil? color-name) (assoc
- :id nil
- :file-id nil))
- :on-click handle-click-color}]
- (cond
- ;; Rendering a color with ID
- (and (:id color) color-name (not (uc/multiple? color)))
- [:*
- [:div.color-info
- [:div.color-name (str color-name)]]
- (when on-detach
- [:div.element-set-actions-button
- {:on-pointer-enter #(reset! hover-detach true)
- :on-pointer-leave #(reset! hover-detach false)
- :on-click detach-value}
- (if @hover-detach i/unchain i/chain)])
+ (if new-css-system
+ [:div {:class (stl/css-case
+ :color-data true
+ :dnd-over-top (= (:over dprops) :top)
+ :dnd-over-bot (= (:over dprops) :bot))
+ :ref dref}
+ [:span {:class (stl/css :color-info)}
+ [:span {:class (stl/css-case :color-name-wrapper true
+ :gradient-name-wrapper gradient-color?)}
+ [:span {:class (stl/css :color-bullet-wrapper)}
+ [:& cb/color-bullet {:color (cond-> color
+ (nil? color-name) (assoc
+ :id nil
+ :file-id nil))
+ :on-click handle-click-color}]]
+ (cond
+ ;; Rendering a color with ID
+ library-color?
+ [:*
+ [:div {:class (stl/css :color-name)
+ :title (str color-name)}
- (when select-only
- [:div.element-set-actions-button {:on-click handle-select}
- i/pointer-inner])]
+ (str color-name)]
+ (when on-detach
+ [:button
+ {:class (stl/css :detach-btn)
+ :title (tr "settings.detach")
+ :on-pointer-enter #(reset! hover-detach true)
+ :on-pointer-leave #(reset! hover-detach false)
+ :on-click detach-value}
+ i/detach-refactor])]
- ;; Rendering a gradient
- (and (not (uc/multiple? color))
- (:gradient color)
- (get-in color [:gradient :type]))
- [:*
- [:div.color-info
- [:div.color-name (uc/gradient-type->string (get-in color [:gradient :type]))]]
- (when select-only
- [:div.element-set-actions-button {:on-click handle-select}
- i/pointer-inner])]
+ ;; Rendering a gradient
+ gradient-color?
+ [:*
+ [:div {:class (stl/css :color-name)}
+ (uc/gradient-type->string (get-in color [:gradient :type]))]]
+
+ ;; Rendering a plain color
+ :else
+ [:span {:class (stl/css :color-input-wrapper)}
+ [:> color-input* {:value (if multiple-colors?
+ ""
+ (-> color :color uc/remove-hash))
+ :placeholder (tr "settings.multiple")
+ :className (stl/css :color-input)
+ :on-focus on-focus
+ :on-blur on-blur
+ :on-change handle-value-change}]])]
+
+ (when (and (not gradient-color?)
+ (not multiple-colors?)
+ (not library-color?))
- ;; Rendering a plain color/opacity
- :else
- [:*
- [:div.color-info
- [:> color-input* {:value (if (uc/multiple? color)
- ""
- (-> color :color uc/remove-hash))
- :placeholder (tr "settings.multiple")
- :on-focus on-focus
- :on-blur on-blur
- :on-change handle-value-change}]]
-
- (when (and (not disable-opacity)
- (not (:gradient color)))
- [:div.input-element
- {:class (dom/classnames :percentail (not= (:opacity color) :multiple))}
+ [:div {:class (stl/css :opacity-element-wrapper)}
+ [:span {:class (stl/css :icon-text)}
+ "%"]
[:> numeric-input* {:value (-> color :opacity opacity->string)
+ :className (stl/css :opacity-input)
:placeholder (tr "settings.multiple")
:select-on-focus select-on-focus
:on-focus on-focus
:on-blur on-blur
:on-change handle-opacity-change
:min 0
- :max 100}]])
- (when select-only
- [:div.element-set-actions-button {:on-click handle-select}
- i/pointer-inner])])
- (when (some? on-remove)
- [:div.element-set-actions-button.remove {:on-click on-remove} i/minus])]))
+ :max 100}]])]
+
+ (when (some? on-remove)
+ [:button {:class (stl/css :remove-btn)
+ :on-click on-remove} i/remove-refactor])
+ (when select-only
+ [:button {:class (stl/css :select-btn)
+ :on-click handle-select}
+ i/move-refactor])]
+
+
+
+
+
+
+
+
+
+ [:div.row-flex.color-data {:title title
+ :class (dom/classnames
+ :dnd-over-top (= (:over dprops) :top)
+ :dnd-over-bot (= (:over dprops) :bot))
+ :ref dref}
+ [:& cb/color-bullet {:color (cond-> color
+ (nil? color-name) (assoc
+ :id nil
+ :file-id nil))
+ :on-click handle-click-color}]
+
+ (cond
+ ;; Rendering a color with ID
+ library-color?
+ [:*
+ [:div.color-info
+ [:div.color-name (str color-name)]]
+ (when on-detach
+ [:div.element-set-actions-button
+ {:on-pointer-enter #(reset! hover-detach true)
+ :on-pointer-leave #(reset! hover-detach false)
+ :on-click detach-value}
+ (if @hover-detach i/unchain i/chain)])]
+
+ ;; Rendering a gradient
+ gradient-color?
+ [:*
+ [:div.color-info
+ [:div.color-name (uc/gradient-type->string (get-in color [:gradient :type]))]]
+ (when select-only
+ [:div.element-set-actions-button {:on-click handle-select}
+ i/pointer-inner])]
+
+ ;; Rendering a plain color/opacity
+ :else
+ [:*
+ [:div.color-info
+ [:> color-input* {:value (if multiple-colors?
+ ""
+ (-> color :color uc/remove-hash))
+ :placeholder (tr "settings.multiple")
+ :on-focus on-focus
+ :on-blur on-blur
+ :on-change handle-value-change}]]
+
+ (when (and (not disable-opacity)
+ (not (:gradient color)))
+ [:div.input-element
+ {:class (dom/classnames :percentail (not= (:opacity color) :multiple))}
+ [:> numeric-input* {:value (-> color :opacity opacity->string)
+ :placeholder (tr "settings.multiple")
+ :select-on-focus select-on-focus
+ :on-focus on-focus
+ :on-blur on-blur
+ :on-change handle-opacity-change
+ :min 0
+ :max 100}]])
+ (when select-only
+ [:div.element-set-actions-button {:on-click handle-select}
+ i/pointer-inner])])
+ (when (some? on-remove)
+ [:div.element-set-actions-button.remove {:on-click on-remove} i/minus])])
+
+ ))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.scss b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.scss
new file mode 100644
index 0000000000..fed6300cd8
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.scss
@@ -0,0 +1,121 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.color-data {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .color-info {
+ display: flex;
+ align-items: center;
+ gap: $s-1;
+ border-radius: $s-8;
+ background-color: var(--input-details-color);
+ height: $s-32;
+ width: 100%;
+ flex-grow: 1;
+ .color-name-wrapper {
+ display: flex;
+ align-items: center;
+ border-radius: $br-8;
+ background-color: var(--input-background-color);
+ flex-grow: 1;
+
+ .color-bullet-wrapper {
+ @extend .input-element;
+ background-color: transparent;
+ border-radius: $br-8 0 0 $br-8;
+ padding: 0 $s-4 0 $s-8;
+ &:hover {
+ background-color: transparent;
+ }
+ }
+ .color-name {
+ @include titleTipography;
+ display: flex;
+ align-items: center;
+ height: $s-32;
+ flex-grow: 1;
+ color: var(--input-foreground-color-active);
+ }
+ .detach-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ border-radius: 0 $br-8 $br-8 0;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ .color-input-wrapper {
+ @extend .input-element;
+ border-radius: $br-0;
+ }
+ &:hover,
+ &:focus,
+ &:focus-within {
+ .color-bullet-wrapper,
+ .color-name,
+ .detach-btn,
+ .color-input-wrapper {
+ background-color: var(--input-background-color-hover);
+ }
+ .detach-btn svg {
+ stroke: var(--input-foreground-color-active);
+ }
+ }
+ }
+ .gradient-name-wrapper {
+ .color-name {
+ border-radius: 0 $br-8 $br-8 0;
+ }
+ }
+ .opacity-element-wrapper {
+ @extend .input-element;
+ width: $s-60;
+ border-radius: 0 $br-8 $br-8 0;
+ padding-left: $s-8;
+ .opacity-input {
+ border-radius: 0 $br-8 $br-8 0;
+ min-width: $s-28;
+ }
+ .icon-text {
+ @include flexCenter;
+ height: $s-32;
+ margin-right: $s-4;
+ padding-top: $s-2;
+ }
+ }
+
+ &:hover {
+ .detach-btn,
+ .select-btn {
+ background-color: transparent;
+ svg {
+ stroke: var(--input-foreground-color-active);
+ }
+ }
+ }
+ }
+ .remove-btn,
+ .select-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+
+ &.dnd-over-top {
+ border-top: $s-1 solid var(--layer-row-foreground-color-drag);
+ }
+ &.dnd-over-bot {
+ border-bottom: $s-1 solid var(--layer-row-foreground-color-drag);
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs
index 60bf0afb6c..d938043c39 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs
@@ -5,11 +5,14 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.rows.stroke-row
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.components.numeric-input :refer [numeric-input*]]
+ [app.main.ui.components.select :refer [select]]
+ [app.main.ui.context :as ctx]
[app.main.ui.hooks :as h]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
@@ -49,10 +52,34 @@
(mf/defc stroke-row
{::mf/wrap-props false}
- [{:keys [index stroke title show-caps on-color-change on-reorder on-color-detach on-remove on-stroke-width-change on-stroke-style-change on-stroke-alignment-change open-caps-select close-caps-select on-stroke-cap-start-change on-stroke-cap-end-change on-stroke-cap-switch disable-drag on-focus on-blur disable-stroke-style select-on-focus]}]
- (let [start-caps-state (mf/use-state {:open? false
- :top 0
- :left 0})
+ [{:keys [index
+ stroke
+ title
+ show-caps
+ on-color-change
+ on-reorder
+ on-color-detach
+ on-remove
+ on-stroke-width-change
+ on-stroke-style-change
+ on-stroke-alignment-change
+ open-caps-select
+ close-caps-select
+ on-stroke-cap-start-change
+ on-stroke-cap-end-change
+ on-stroke-cap-switch
+ disable-drag
+ on-focus
+ on-blur
+ disable-stroke-style
+ select-on-focus]}]
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ start-caps-state* (mf/use-state {:open? false
+ :top 0
+ :left 0})
+
+ start-caps-state (deref start-caps-state*)
+
end-caps-state (mf/use-state {:open? false
:top 0
:left 0})
@@ -69,99 +96,255 @@
:data {:id (str "stroke-row-" index)
:index index
:name (str "Border row" index)})
- [nil nil])]
+ [nil nil])
- [:div.border-data {:class (dom/classnames
- :dnd-over-top (= (:over dprops) :top)
- :dnd-over-bot (= (:over dprops) :bot))
- :ref dref}
- ;; Stroke Color
- [:& color-row {:color {:color (:stroke-color stroke)
- :opacity (:stroke-opacity stroke)
- :id (:stroke-color-ref-id stroke)
- :file-id (:stroke-color-ref-file stroke)
- :gradient (:stroke-color-gradient stroke)}
- :index index
- :title title
- :on-change (on-color-change index)
- :on-detach (on-color-detach index)
- :on-remove (on-remove index)
- :disable-drag disable-drag
- :on-focus on-focus
- :select-on-focus select-on-focus
- :on-blur on-blur}]
+ on-color-change-refactor
+ (mf/use-callback
+ (mf/deps index on-color-change)
+ (fn [color]
+ (on-color-change index color)))
- ;; Stroke Width, Alignment & Style
- [:div.row-flex
- [:div.input-element
- {:class (dom/classnames :pixels (not= (:stroke-width stroke) :multiple))
- :title (tr "workspace.options.stroke-width")}
+ on-color-detach-refactor
+ (mf/use-callback
+ (mf/deps index on-color-detach)
+ (fn [color]
+ (on-color-detach index color)))
- [:> numeric-input*
- {:min 0
- :value (-> (:stroke-width stroke) width->string)
- :placeholder (tr "settings.multiple")
- :on-change (on-stroke-width-change index)
- :on-focus on-focus
- :select-on-focus select-on-focus
- :on-blur on-blur}]]
+ on-remove-refactor
+ (mf/use-callback
+ (mf/deps index on-remove)
+ #(on-remove index))
- [:select#style.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (enum->string (:stroke-alignment stroke))
- :on-change (on-stroke-alignment-change index)}
- (when (= (:stroke-alignment stroke) :multiple)
- [:option {:value ""} "--"])
- [:option {:value ":center"} (tr "workspace.options.stroke.center")]
- [:option {:value ":inner"} (tr "workspace.options.stroke.inner")]
- [:option {:value ":outer"} (tr "workspace.options.stroke.outer")]]
+ stroke-width (:stroke-width stroke)
- (when-not disable-stroke-style
- [:select#style.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (enum->string (:stroke-style stroke))
- :on-change (on-stroke-style-change index)}
- (when (= (:stroke-style stroke) :multiple)
- [:option {:value ""} "--"])
- [:option {:value ":solid"} (tr "workspace.options.stroke.solid")]
- [:option {:value ":dotted"} (tr "workspace.options.stroke.dotted")]
- [:option {:value ":dashed"} (tr "workspace.options.stroke.dashed")]
- [:option {:value ":mixed"} (tr "workspace.options.stroke.mixed")]])]
+ on-width-change
+ (mf/use-callback
+ (mf/deps index on-stroke-width-change)
+ #(on-stroke-width-change index %))
- ;; Stroke Caps
- (when show-caps
+ stroke-alignment (or (:stroke-alignment stroke) :center)
+
+ stroke-alignment-options
+ (mf/with-memo [stroke-alignment]
+ (d/concat-vec
+ (when (= :multiple stroke-alignment)
+ [{:value :multiple :label "--"}])
+ [{:value :center :label (tr "workspace.options.stroke.center")}
+ {:value :inner :label (tr "workspace.options.stroke.inner")}
+ {:value :outer :label (tr "workspace.options.stroke.outer")}]))
+
+ on-alignment-change
+ (mf/use-callback
+ (mf/deps index on-stroke-alignment-change)
+ #(on-stroke-alignment-change index (keyword %)))
+
+ stroke-style (or (:stroke-style stroke) :solid)
+
+ stroke-style-options
+ (mf/with-memo [stroke-style]
+ (d/concat-vec
+ (when (= :multiple stroke-style)
+ [{:value :multiple :label "--"}])
+ [{:value :solid :label (tr "workspace.options.stroke.solid")}
+ {:value :dotted :label (tr "workspace.options.stroke.dotted")}
+ {:value :dashed :label (tr "workspace.options.stroke.dashed")}
+ {:value :mixed :label (tr "workspace.options.stroke.mixed")}]))
+
+ on-style-change
+ (mf/use-callback
+ (mf/deps index on-stroke-style-change)
+ #(on-stroke-style-change index (keyword %)))
+
+ on-caps-start-change
+ (mf/use-callback
+ (mf/deps index on-stroke-cap-start-change)
+ #(on-stroke-cap-start-change index (keyword %)))
+
+ on-caps-end-change
+ (mf/use-callback
+ (mf/deps index on-stroke-cap-end-change)
+ #(on-stroke-cap-end-change index (keyword %)))
+
+ stroke-caps-options
+ [{:value nil :label (tr "workspace.options.stroke-cap.none")}
+ :separator
+ {:value :line-arrow :label (tr "workspace.options.stroke-cap.line-arrow-short")}
+ {:value :triangle-arrow :label (tr "workspace.options.stroke-cap.triangle-arrow-short")}
+ {:value :square-marker :label (tr "workspace.options.stroke-cap.square-marker-short")}
+ {:value :circle-marker :label (tr "workspace.options.stroke-cap.circle-marker-short")}
+ {:value :diamond-marker :label (tr "workspace.options.stroke-cap.diamond-marker-short")}
+ :separator
+ {:value :round :label (tr "workspace.options.stroke-cap.round")}
+ {:value :square :label (tr "workspace.options.stroke-cap.square")}]
+
+ on-cap-switch
+ (mf/use-callback
+ (mf/deps index on-stroke-cap-switch)
+ #(on-stroke-cap-switch index))]
+
+ (if new-css-system
+ [:div {:class (stl/css-case
+ :stroke-data true
+ :dnd-over-top (= (:over dprops) :top)
+ :dnd-over-bot (= (:over dprops) :bot))
+ :ref dref}
+ ;; Stroke Color
+ [:& color-row {:color {:color (:stroke-color stroke)
+ :opacity (:stroke-opacity stroke)
+ :id (:stroke-color-ref-id stroke)
+ :file-id (:stroke-color-ref-file stroke)
+ :gradient (:stroke-color-gradient stroke)}
+ :index index
+ :title title
+ :on-change on-color-change-refactor
+ :on-detach on-color-detach-refactor
+ :on-remove on-remove-refactor
+ :disable-drag disable-drag
+ :on-focus on-focus
+ :select-on-focus select-on-focus
+ :on-blur on-blur}]
+
+ ;; Stroke Width, Alignment & Style
+ [:div {:class (stl/css :stroke-options)}
+ [:div {:class (stl/css :stroke-width-input-element)
+ :title (tr "workspace.options.stroke-width")}
+ [:span {:class (stl/css :icon)}
+ i/stroke-size-refactor]
+ [:> numeric-input*
+ {:min 0
+ :className (stl/css :stroke-width-input)
+ :value stroke-width
+ :placeholder (tr "settings.multiple")
+ :on-change on-width-change
+ :on-focus on-focus
+ :select-on-focus select-on-focus
+ :on-blur on-blur}]]
+
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select
+ {:default-value stroke-alignment
+ :options stroke-alignment-options
+ :on-change on-alignment-change}]]
+
+ (when-not disable-stroke-style
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select
+ {:default-value stroke-style
+ :options stroke-style-options
+ :on-change on-style-change}]])]
+
+ ;; Stroke Caps
+ (when show-caps
+ [:div {:class (stl/css :stroke-caps-options)}
+ [:div {:class (stl/css :cap-select)}
+ [:& select
+ {:default-value (:stroke-cap-start stroke)
+ :options stroke-caps-options
+ :on-change on-caps-start-change}]]
+
+ [:button {:class (stl/css :swap-caps-btn)
+ :on-click on-cap-switch}
+ i/switch-refactor]
+
+ [:div {:class (stl/css :cap-select)}
+ [:& select
+ {:default-value (:stroke-cap-end stroke)
+ :options stroke-caps-options
+ :on-change on-caps-end-change}]]])]
+
+
+
+ [:div.border-data {:class (dom/classnames
+ :dnd-over-top (= (:over dprops) :top)
+ :dnd-over-bot (= (:over dprops) :bot))
+ :ref dref}
+ ;; Stroke Color
+ [:& color-row {:color {:color (:stroke-color stroke)
+ :opacity (:stroke-opacity stroke)
+ :id (:stroke-color-ref-id stroke)
+ :file-id (:stroke-color-ref-file stroke)
+ :gradient (:stroke-color-gradient stroke)}
+ :index index
+ :title title
+ :on-change (on-color-change index)
+ :on-detach (on-color-detach index)
+ :on-remove (on-remove index)
+ :disable-drag disable-drag
+ :on-focus on-focus
+ :select-on-focus select-on-focus
+ :on-blur on-blur}]
+
+ ;; Stroke Width, Alignment & Style
[:div.row-flex
- [:div.cap-select {:tab-index 0 ;; tab-index to make the element focusable
- :on-click (open-caps-select start-caps-state)}
- (value->name (:stroke-cap-start stroke))
- [:span.cap-select-button
- i/arrow-down]]
- [:& dropdown {:show (:open? @start-caps-state)
- :on-close (close-caps-select start-caps-state)}
- [:ul.dropdown.cap-select-dropdown {:style {:top (:top @start-caps-state)
- :left (:left @start-caps-state)}}
- (for [[idx [value label separator]] (d/enumerate (stroke-cap-names))]
- (let [img (value->img value)]
- [:li {:key (dm/str "start-cap-" idx)
- :class (dom/classnames :separator separator)
- :on-click #(on-stroke-cap-start-change index value)}
- (when img [:img {:src (value->img value)}])
- label]))]]
+ [:div.input-element
+ {:class (dom/classnames :pixels (not= (:stroke-width stroke) :multiple))
+ :title (tr "workspace.options.stroke-width")}
- [:div.element-set-actions-button {:on-click #(on-stroke-cap-switch index)}
- i/switch]
+ [:> numeric-input*
+ {:min 0
+ :value (-> (:stroke-width stroke) width->string)
+ :placeholder (tr "settings.multiple")
+ :on-change (on-stroke-width-change index)
+ :on-focus on-focus
+ :select-on-focus select-on-focus
+ :on-blur on-blur}]]
- [:div.cap-select {:tab-index 0
- :on-click (open-caps-select end-caps-state)}
- (value->name (:stroke-cap-end stroke))
- [:span.cap-select-button
- i/arrow-down]]
- [:& dropdown {:show (:open? @end-caps-state)
- :on-close (close-caps-select end-caps-state)}
- [:ul.dropdown.cap-select-dropdown {:style {:top (:top @end-caps-state)
- :left (:left @end-caps-state)}}
- (for [[idx [value label separator]] (d/enumerate (stroke-cap-names))]
- (let [img (value->img value)]
- [:li {:key (dm/str "end-cap-" idx)
- :class (dom/classnames :separator separator)
- :on-click #(on-stroke-cap-end-change index value)}
- (when img [:img {:src (value->img value)}])
- label]))]]])]))
+ [:select#style.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
+ :value (enum->string (:stroke-alignment stroke))
+ :on-change (on-stroke-alignment-change index)}
+ (when (= (:stroke-alignment stroke) :multiple)
+ [:option {:value ""} "--"])
+ [:option {:value ":center"} (tr "workspace.options.stroke.center")]
+ [:option {:value ":inner"} (tr "workspace.options.stroke.inner")]
+ [:option {:value ":outer"} (tr "workspace.options.stroke.outer")]]
+
+ (when-not disable-stroke-style
+ [:select#style.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
+ :value (enum->string (:stroke-style stroke))
+ :on-change (on-stroke-style-change index)}
+ (when (= (:stroke-style stroke) :multiple)
+ [:option {:value ""} "--"])
+ [:option {:value ":solid"} (tr "workspace.options.stroke.solid")]
+ [:option {:value ":dotted"} (tr "workspace.options.stroke.dotted")]
+ [:option {:value ":dashed"} (tr "workspace.options.stroke.dashed")]
+ [:option {:value ":mixed"} (tr "workspace.options.stroke.mixed")]])]
+
+ ;; Stroke Caps
+ (when show-caps
+ [:div.row-flex
+ [:div.cap-select {:tab-index 0 ;; tab-index to make the element focusable
+ :on-click (open-caps-select start-caps-state*)}
+ (value->name (:stroke-cap-start stroke))
+ [:span.cap-select-button
+ i/arrow-down]]
+ [:& dropdown {:show (:open? start-caps-state)
+ :on-close (close-caps-select start-caps-state*)}
+ [:ul.dropdown.cap-select-dropdown {:style {:top (:top start-caps-state)
+ :left (:left start-caps-state)}}
+ (for [[idx [value label separator]] (d/enumerate (stroke-cap-names))]
+ (let [img (value->img value)]
+ [:li {:key (dm/str "start-cap-" idx)
+ :class (dom/classnames :separator separator)
+ :on-click #(on-stroke-cap-start-change index value)}
+ (when img [:img {:src (value->img value)}])
+ label]))]]
+
+ [:div.element-set-actions-button {:on-click #(on-stroke-cap-switch index)}
+ i/switch]
+
+ [:div.cap-select {:tab-index 0
+ :on-click (open-caps-select end-caps-state)}
+ (value->name (:stroke-cap-end stroke))
+ [:span.cap-select-button
+ i/arrow-down]]
+ [:& dropdown {:show (:open? @end-caps-state)
+ :on-close (close-caps-select end-caps-state)}
+ [:ul.dropdown.cap-select-dropdown {:style {:top (:top @end-caps-state)
+ :left (:left @end-caps-state)}}
+ (for [[idx [value label separator]] (d/enumerate (stroke-cap-names))]
+ (let [img (value->img value)]
+ [:li {:key (dm/str "end-cap-" idx)
+ :class (dom/classnames :separator separator)
+ :on-click #(on-stroke-cap-end-change index value)}
+ (when img [:img {:src (value->img value)}])
+ label]))]]])])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.scss b/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.scss
new file mode 100644
index 0000000000..0ed841ada6
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.scss
@@ -0,0 +1,55 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// Copyright (c) KALEIDOS INC
+
+@import "refactor/common-refactor.scss";
+
+.stroke-data {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ .stroke-options {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .stroke-width-input-element {
+ @extend .input-element;
+ width: $s-60;
+ border-radius: $br-8;
+ padding: $s-8;
+ .icon {
+ @include flexCenter;
+ height: $s-32;
+ width: $s-12;
+ margin-right: $s-4;
+ }
+ }
+ .select-wrapper {
+ width: $s-124;
+ }
+ }
+ .stroke-caps-options {
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .cap-select {
+ width: $s-124;
+ }
+ .swap-caps-btn {
+ @extend .button-secondary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ &.dnd-over-top {
+ border-top: $s-1 solid var(--layer-row-foreground-color-drag);
+ }
+ &.dnd-over-bot {
+ border-bottom: $s-1 solid var(--layer-row-foreground-color-drag);
+ }
+}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/sitemap.scss b/frontend/src/app/main/ui/workspace/sidebar/sitemap.scss
index 8ba8c7d6d8..0cac04b5ba 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/sitemap.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/sitemap.scss
@@ -44,7 +44,7 @@
}
.resize-area {
position: absolute;
- bottom: -8px;
+ bottom: calc(-1 * $s-8);
left: 0;
width: 100%;
height: $s-12;
diff --git a/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.scss b/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.scss
index 3b77f7f3d2..6c153cff1e 100644
--- a/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.scss
+++ b/frontend/src/app/main/ui/workspace/text_palette_ctx_menu.scss
@@ -10,7 +10,7 @@
position: absolute;
left: auto;
bottom: $s-0;
- max-width: $s-248;
+ max-width: $s-480;
padding: $s-4;
margin: 0 0 $s-4 0;
z-index: $z-index-3;
@@ -22,6 +22,7 @@
position: relative;
display: flex;
justify-content: space-between;
+ width: 100%;
gap: $s-8;
padding: $s-8;
margin-bottom: $s-4;
@@ -41,7 +42,6 @@
max-width: $s-380;
}
.lib-num {
- background-color: green;
margin-left: $s-4;
}
}
diff --git a/frontend/src/app/main/ui/workspace/viewport/pixel_overlay.cljs b/frontend/src/app/main/ui/workspace/viewport/pixel_overlay.cljs
index e911ae42e1..2eab802c6c 100644
--- a/frontend/src/app/main/ui/workspace/viewport/pixel_overlay.cljs
+++ b/frontend/src/app/main/ui/workspace/viewport/pixel_overlay.cljs
@@ -11,6 +11,7 @@
[app.main.data.workspace.undo :as dwu]
[app.main.rasterizer :as thr]
[app.main.store :as st]
+ [app.main.ui.context :as ctx]
[app.main.ui.css-cursors :as cur]
[app.util.dom :as dom]
[app.util.keyboard :as kbd]
@@ -23,7 +24,8 @@
(mf/defc pixel-overlay
{::mf/wrap-props false}
[props]
- (let [vport (unchecked-get props "vport")
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ vport (unchecked-get props "vport")
viewport-ref (unchecked-get props "viewport-ref")
viewport-node (mf/ref-val viewport-ref)
@@ -52,7 +54,9 @@
(when-let [zoom-view-node (dom/get-element "picker-detail")]
(when-not (mf/ref-val zoom-view-context)
(mf/set-ref-val! zoom-view-context (.getContext zoom-view-node "2d")))
- (let [{brx :left bry :top} (dom/get-bounding-rect viewport-node)
+ (let [canvas-width (if new-css-system 260 200)
+ canvas-height (if new-css-system 140 160)
+ {brx :left bry :top} (dom/get-bounding-rect viewport-node)
x (- (.-clientX event) brx)
y (- (.-clientY event) bry)
@@ -75,8 +79,8 @@
sh 40
dx 0
dy 0
- dw 200
- dh 160]
+ dw canvas-width
+ dh canvas-height]
(when (obj/get zoom-context "imageSmoothingEnabled")
(obj/set! zoom-context "imageSmoothingEnabled" false))
(.drawImage zoom-context canvas sx sy sw sh dx dy dw dh)
diff --git a/frontend/translations/en.po b/frontend/translations/en.po
index 0e5a7bbf36..96473cca0f 100644
--- a/frontend/translations/en.po
+++ b/frontend/translations/en.po
@@ -2284,6 +2284,10 @@ msgstr "Go to login"
msgid "settings.multiple"
msgstr "Mixed"
+#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs,
+msgid "settings.detach"
+msgstr "Detach"
+
# SECTIONS
msgid "shortcut-section.basics"
msgstr "Basics"
@@ -4140,14 +4144,26 @@ msgstr "Stroke"
msgid "workspace.options.stroke-cap.circle-marker"
msgstr "Circle marker"
+#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
+msgid "workspace.options.stroke-cap.circle-marker-short"
+msgstr "Circle"
+
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
msgid "workspace.options.stroke-cap.diamond-marker"
msgstr "Diamond marker"
+#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
+msgid "workspace.options.stroke-cap.diamond-marker-short"
+msgstr "Diamond"
+
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
msgid "workspace.options.stroke-cap.line-arrow"
msgstr "Line arrow"
+#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
+msgid "workspace.options.stroke-cap.line-arrow-short"
+msgstr "Arrow"
+
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
msgid "workspace.options.stroke-cap.none"
msgstr "None"
@@ -4164,10 +4180,18 @@ msgstr "Square"
msgid "workspace.options.stroke-cap.square-marker"
msgstr "Square marker"
+#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
+msgid "workspace.options.stroke-cap.square-marker-short"
+msgstr "Rectangle"
+
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
msgid "workspace.options.stroke-cap.triangle-arrow"
msgstr "Triangle arrow"
+#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
+msgid "workspace.options.stroke-cap.triangle-arrow-short"
+msgstr "Triangle"
+
msgid "workspace.options.stroke-color"
msgstr "Stroke color"
diff --git a/frontend/translations/es.po b/frontend/translations/es.po
index ee428ed1b8..0b38b32774 100644
--- a/frontend/translations/es.po
+++ b/frontend/translations/es.po
@@ -2357,6 +2357,10 @@ msgstr "Ir al login"
msgid "settings.multiple"
msgstr "Varios"
+#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs,
+msgid "settings.detach"
+msgstr "Desacoplar"
+
# SECTIONS
msgid "shortcut-section.basics"
msgstr "Básicos"
@@ -4235,14 +4239,26 @@ msgstr "Borde"
msgid "workspace.options.stroke-cap.circle-marker"
msgstr "Marcador círculo"
+#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
+msgid "workspace.options.stroke-cap.circle-marker-short"
+msgstr "Círculo"
+
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
msgid "workspace.options.stroke-cap.diamond-marker"
msgstr "Marcador diamante"
+#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
+msgid "workspace.options.stroke-cap.diamond-marker-short"
+msgstr "Diamante"
+
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
msgid "workspace.options.stroke-cap.line-arrow"
msgstr "Flecha de línea"
+#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
+msgid "workspace.options.stroke-cap.line-arrow-short"
+msgstr "Flecha"
+
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
msgid "workspace.options.stroke-cap.none"
msgstr "Ninguno"
@@ -4259,10 +4275,18 @@ msgstr "Cuadrado"
msgid "workspace.options.stroke-cap.square-marker"
msgstr "Marcador cuadrado"
+#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
+msgid "workspace.options.stroke-cap.square-marker-short"
+msgstr "Rectángulo"
+
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
msgid "workspace.options.stroke-cap.triangle-arrow"
msgstr "Flecha triángulo"
+#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
+msgid "workspace.options.stroke-cap.triangle-arrow-short"
+msgstr "Triángulo"
+
msgid "workspace.options.stroke-color"
msgstr "Color del trazo"