diff --git a/frontend/resources/images/icons/easing-ease-in-out-refactor.svg b/frontend/resources/images/icons/easing-ease-in-out-refactor.svg
new file mode 100644
index 0000000000..def35ce0e5
--- /dev/null
+++ b/frontend/resources/images/icons/easing-ease-in-out-refactor.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/frontend/resources/images/icons/easing-ease-in-refactor.svg b/frontend/resources/images/icons/easing-ease-in-refactor.svg
new file mode 100644
index 0000000000..8d2d215ce6
--- /dev/null
+++ b/frontend/resources/images/icons/easing-ease-in-refactor.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/frontend/resources/images/icons/easing-ease-out-refactor.svg b/frontend/resources/images/icons/easing-ease-out-refactor.svg
new file mode 100644
index 0000000000..03209db2d3
--- /dev/null
+++ b/frontend/resources/images/icons/easing-ease-out-refactor.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/frontend/resources/images/icons/easing-ease-refactor.svg b/frontend/resources/images/icons/easing-ease-refactor.svg
new file mode 100644
index 0000000000..68cac1fa61
--- /dev/null
+++ b/frontend/resources/images/icons/easing-ease-refactor.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/frontend/resources/images/icons/easing-linear-refactor.svg b/frontend/resources/images/icons/easing-linear-refactor.svg
new file mode 100644
index 0000000000..2890f2212e
--- /dev/null
+++ b/frontend/resources/images/icons/easing-linear-refactor.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/frontend/resources/images/icons/interaction-refactor.svg b/frontend/resources/images/icons/interaction-refactor.svg
new file mode 100644
index 0000000000..7c3fb8462a
--- /dev/null
+++ b/frontend/resources/images/icons/interaction-refactor.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/frontend/resources/styles/common/refactor/basic-rules.scss b/frontend/resources/styles/common/refactor/basic-rules.scss
index 0206395eaf..8b912412c7 100644
--- a/frontend/resources/styles/common/refactor/basic-rules.scss
+++ b/frontend/resources/styles/common/refactor/basic-rules.scss
@@ -375,6 +375,37 @@
}
}
+.input-checkbox {
+ display: flex;
+ align-items: center;
+ label {
+ @include titleTipography;
+ display: flex;
+ align-items: center;
+ gap: $s-6;
+ cursor: pointer;
+ span {
+ @include flexCenter;
+ width: $s-16;
+ height: $s-16;
+ min-width: $s-16;
+ min-height: $s-16;
+ border-radius: $br-6;
+ background-color: var(--input-background-color);
+ &:global(.checked) {
+ background-color: var(--input-border-color-active);
+ svg {
+ @extend .button-icon-small;
+ stroke: var(--input-details-color);
+ }
+ }
+ }
+ input {
+ margin: 0;
+ }
+ }
+}
+
//MODALS
.modal-background {
@include menuShadow;
@@ -467,8 +498,14 @@
border-color: var(--colorpicker-details-color-selected);
}
}
-// SELECTS AND DROPDOWNS
+.attr-row {
+ display: grid;
+ grid-template-areas: "name content";
+ grid-template-columns: $s-92 1fr;
+}
+
+// SELECTS AND DROPDOWNS
.menu-dropdown {
@include menuShadow;
position: absolute;
diff --git a/frontend/resources/styles/common/refactor/design-tokens.scss b/frontend/resources/styles/common/refactor/design-tokens.scss
index aec6339a37..29d7670159 100644
--- a/frontend/resources/styles/common/refactor/design-tokens.scss
+++ b/frontend/resources/styles/common/refactor/design-tokens.scss
@@ -14,6 +14,8 @@
--panel-background-color: var(--color-background-primary);
--panel-title-background-color: var(--color-background-secondary);
+ // BUTTONS
+
--button-foreground-hover: var(--color-accent-primary);
--button-background-focus: var(--color-background-secondary);
--button-foreground-focus: var(--color-foreground-primary);
@@ -84,6 +86,7 @@
--constraint-widget-background-color: var(--color-background-tertiary);
--constraint-center-area-background-color: var(--color-background-primary);
+ // ICONS
--icon-foreground: var(--color-foreground-secondary);
--icon-foreground-hover: var(--color-foreground-primary);
diff --git a/frontend/src/app/main/ui/components/select.cljs b/frontend/src/app/main/ui/components/select.cljs
index 04a963d3b1..2fabc9d226 100644
--- a/frontend/src/app/main/ui/components/select.cljs
+++ b/frontend/src/app/main/ui/components/select.cljs
@@ -19,8 +19,8 @@
(defn- as-key-value
[item]
(if (map? item)
- [(:value item) (:label item)]
- [item item]))
+ [(:value item) (:label item) (:icon item)]
+ [item item item]))
(mf/defc select
[{:keys [default-value options class is-open? on-change on-pointer-enter-option on-pointer-leave-option disabled]}]
@@ -42,7 +42,7 @@
open-dropdown
(mf/use-fn
(mf/deps disabled)
- (fn[]
+ (fn []
(when-not disabled
(swap! state* assoc :is-open? true))))
@@ -82,10 +82,16 @@
(mf/with-effect [default-value]
(swap! state* assoc :current-value default-value))
+
(if new-css-system
[:div {:on-click open-dropdown
:class (dm/str class " " (stl/css-case :custom-select true
:disabled disabled))}
+ (let [selected-option (first (filter #(= (:value %) default-value) options))
+ current-icon (:icon selected-option)
+ current-icon-ref (i/key->icon current-icon)]
+ (when (and current-icon current-icon-ref)
+ [:span {:class (stl/css :current-icon)} @current-icon-ref]))
[: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}
@@ -94,7 +100,8 @@
(if (= :separator item)
[:li {:class (dom/classnames (stl/css :separator) true)
:key (dm/str current-id "-" index)}]
- (let [[value label] (as-key-value item)]
+ (let [[value label icon] (as-key-value item)
+ icon-ref (i/key->icon icon)]
[:li
{:key (dm/str current-id "-" index)
:class (dom/classnames
@@ -104,10 +111,10 @@
:on-pointer-enter highlight-item
:on-pointer-leave unhighlight-item
:on-click select-item}
+ (when (and icon icon-ref) [:span {:class (stl/css :icon)} @icon-ref])
[: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]
[:span.dropdown-button i/arrow-down]
diff --git a/frontend/src/app/main/ui/components/select.scss b/frontend/src/app/main/ui/components/select.scss
index 7fb9fcd37b..8b4625d79e 100644
--- a/frontend/src/app/main/ui/components/select.scss
+++ b/frontend/src/app/main/ui/components/select.scss
@@ -24,6 +24,16 @@
width: 100%;
flex-grow: 1;
}
+ .current-icon {
+ @include flexCenter;
+ height: $s-24;
+ width: $s-24;
+ padding-right: $s-4;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
+ }
+ }
.dropdown-button {
@include flexCenter;
svg {
@@ -42,6 +52,17 @@
.checked-element {
@extend .dropdown-element-base;
+ .icon {
+ @include flexCenter;
+ height: $s-24;
+ width: $s-24;
+ padding-right: $s-4;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
+ }
+ }
+
.label {
flex-grow: 1;
width: 100%;
diff --git a/frontend/src/app/main/ui/icons.cljs b/frontend/src/app/main/ui/icons.cljs
index 48d5bccf69..4147e44e31 100644
--- a/frontend/src/app/main/ui/icons.cljs
+++ b/frontend/src/app/main/ui/icons.cljs
@@ -7,7 +7,11 @@
(ns app.main.ui.icons
(:refer-clojure :exclude [import mask])
(:require-macros [app.main.ui.icons :refer [icon-xref]])
- (:require [rumext.v2 :as mf]))
+ (:require
+ [app.common.data :as d]
+ [rumext.v2 :as mf]))
+
+
;; Keep the list of icons sorted
@@ -320,6 +324,11 @@
(def detach-refactor (icon-xref :detach-refactor))
(def document-refactor (icon-xref :document-refactor))
(def drop-refactor (icon-xref :drop-refactor))
+(def easing-linear-refactor (icon-xref :easing-linear-refactor))
+(def easing-ease-refactor (icon-xref :easing-ease-refactor))
+(def easing-ease-in-refactor (icon-xref :easing-ease-in-refactor))
+(def easing-ease-out-refactor (icon-xref :easing-ease-out-refactor))
+(def easing-ease-in-out-refactor (icon-xref :easing-ease-in-out-refactor))
(def effects-refactor (icon-xref :effects-refactor))
(def elipse-refactor (icon-xref :elipse-refactor))
(def fill-content-refactor (icon-xref :fill-content-refactor))
@@ -348,6 +357,7 @@
(def hug-content-refactor (icon-xref :hug-content-refactor))
(def img-refactor (icon-xref :img-refactor))
(def icon-refactor (icon-xref :icon-refactor))
+(def interaction-refactor (icon-xref :interaction-refactor))
(def join-nodes-refactor (icon-xref :join-nodes-refactor))
(def justify-content-column-around-refactor (icon-xref :justify-content-column-around-refactor))
(def justify-content-column-between-refactor (icon-xref :justify-content-column-between-refactor))
@@ -466,3 +476,8 @@
[:div.icon-item {:key key}
(deref val)
[:span (pr-str key)]]))])
+
+(defn key->icon
+ [icon-key]
+ (when icon-key
+ (get (ns-publics 'app.main.ui.icons) (symbol (d/name icon-key)))))
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 a7cc63c469..68781e1572 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
@@ -175,7 +175,7 @@
(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?))}
+ :class (stl/css-case :global/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?)
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
index 477343ed7c..76786dc02b 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.scss
@@ -38,35 +38,10 @@
}
}
.checkbox {
- display: flex;
- align-items: center;
+ @extend .input-checkbox;
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/interactions.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
index 53ec895026..029a74f377 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
@@ -5,6 +5,7 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.menus.interactions
+ (:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
@@ -18,6 +19,10 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.numeric-input :refer [numeric-input*]]
+ [app.main.ui.components.radio-buttons :refer [radio-buttons radio-button]]
+ [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]]
@@ -92,12 +97,26 @@
:ease-out (tr "workspace.options.interaction-easing-ease-out")
:ease-in-out (tr "workspace.options.interaction-easing-ease-in-out")})
+(defn- get-frames-options
+ [frames shape]
+ (->> frames
+ (filter #(and (not= (:id %) (:id shape)) ; A frame cannot navigate to itself
+ (not= (:id %) (:frame-id shape)))) ; nor a shape to its container frame
+ (map (fn [frame]
+ {:value (str (:id frame)) :label (:name frame)}))))
+
+(defn- get-shared-frames-options
+ [shared-frames]
+ (map (fn [frame]
+ {:value (str (:id frame)) :label (:name frame)}) shared-frames))
+
(def flow-for-rename-ref
(l/derived (l/in [:workspace-local :flow-for-rename]) st/state))
(mf/defc flow-item
[{:keys [flow]}]
- (let [editing? (mf/use-state false)
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ editing? (mf/use-state false)
flow-for-rename (mf/deref flow-for-rename-ref)
name-ref (mf/use-ref)
@@ -118,7 +137,22 @@
on-key-down (fn [event]
(when (kbd/enter? event) (accept-edit))
- (when (kbd/esc? event) (cancel-edit)))]
+ (when (kbd/esc? event) (cancel-edit)))
+
+ start-flow
+ (mf/use-fn
+ (mf/deps flow)
+ #(st/emit! (dw/select-shape (:starting-frame flow))))
+
+ rename-flow
+ (mf/use-fn
+ (mf/deps flow)
+ #(st/emit! (dwi/start-rename-flow (:id flow))))
+
+ remove-flow
+ (mf/use-fn
+ (mf/deps flow)
+ #(st/emit! (dwi/remove-flow (:id flow))))]
(mf/use-effect
(fn []
@@ -137,50 +171,97 @@
(let [name-input (mf/ref-val name-ref)]
(dom/select-text! name-input))
nil))
+ (if new-css-system
+ [:div {:class (stl/css :flow-element)}
+ [:button {:class (stl/css :start-flow-btn)
+ :on-click start-flow}
+ i/play-refactor]
- [:div.flow-element
- [:div.flow-button {:on-click #(st/emit! (dw/select-shape (:starting-frame flow)))}
- i/play]
- (if @editing?
- [:input.element-name
- {:type "text"
- :ref name-ref
- :on-blur accept-edit
- :on-key-down on-key-down
- :auto-focus true
- :default-value (:name flow "")}]
- [:span.element-label.flow-name
- {:on-double-click #(st/emit! (dwi/start-rename-flow (:id flow)))}
- (:name flow)])
- [:div.add-page {:on-click #(st/emit! (dwi/remove-flow (:id flow)))}
- i/minus]]))
+ (if @editing?
+ [:input
+ {:class (stl/css :input-text)
+ :type "text"
+ :ref name-ref
+ :on-blur accept-edit
+ :on-key-down on-key-down
+ :auto-focus true
+ :default-value (:name flow "")}]
+ [:span
+ {:class (stl/css :flow-name-label)
+ :on-double-click rename-flow}
+ (:name flow)])
+ [:div {:class (stl/css :remove-flow-btn)
+ :on-click remove-flow}
+ i/remove-refactor]]
+
+ [:div.flow-element
+ [:div.flow-button {:on-click start-flow} i/play]
+ (if @editing?
+ [:input.element-name
+ {:type "text"
+ :ref name-ref
+ :on-blur accept-edit
+ :on-key-down on-key-down
+ :auto-focus true
+ :default-value (:name flow "")}]
+ [:span.element-label.flow-name
+ {:on-double-click rename-flow}
+ (:name flow)])
+ [:div.add-page {:on-click remove-flow} i/minus]])))
(mf/defc page-flows
[{:keys [flows]}]
- (when (seq flows)
- [:div.element-set.interactions-options
- [:div.element-set-title
- [:span (tr "workspace.options.flows.flow-starts")]]
- (for [flow flows]
- [:& flow-item {:flow flow :key (str (:id flow))}])]))
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)]
+ (if new-css-system
+ (when (seq flows)
+ [:div {:class (stl/css :interaction-options)}
+ [:& title-bar {:collapsable? false
+ :title (tr "workspace.options.flows.flow-starts")
+ :class (stl/css :title-spacing-layout-flow)}]
+ (for [flow flows]
+ [:& flow-item {:flow flow :key (str (:id flow))}])])
+
+ (when (seq flows)
+ [:div.element-set.interactions-options
+ [:div.element-set-title
+ [:span (tr "workspace.options.flows.flow-starts")]]
+ (for [flow flows]
+ [:& flow-item {:flow flow :key (str (:id flow))}])]))))
(mf/defc shape-flows
[{:keys [flows shape]}]
(when (= (:type shape) :frame)
- (let [flow (ctp/get-frame-flow flows (:id shape))]
- [:div.element-set.interactions-options
- [:div.element-set-title
- [:span (tr "workspace.options.flows.flow-start")]]
- (if (nil? flow)
- [:div.flow-element
- [:span.element-label (tr "workspace.options.flows.add-flow-start")]
- [:div.add-page {:on-click #(st/emit! (dwi/add-flow-selected-frame))}
- i/plus]]
- [:& flow-item {:flow flow :key (str (:id flow))}])])))
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ flow (ctp/get-frame-flow flows (:id shape))
+ add-flow (mf/use-fn #(st/emit! (dwi/add-flow-selected-frame)))]
+ (if new-css-system
+ [:div {:class (stl/css :element-set)}
+ [:& title-bar {:collapsable? false
+ :title (tr "workspace.options.flows.flow")
+ :class (stl/css :title-spacing-layout-flow)}
+ (when (nil? flow)
+ [:button {:class (stl/css :add-flow-btn)
+ :title (tr "workspace.options.flows.add-flow-start")
+ :on-click add-flow}
+ i/add-refactor])]
+
+ (when flow
+ [:& flow-item {:flow flow :key (str (:id flow))}])]
+
+ [:div.element-set.interactions-options
+ [:div.element-set-title
+ [:span (tr "workspace.options.flows.flow-start")]]
+ (if (nil? flow)
+ [:div.flow-element
+ [:span.element-label (tr "workspace.options.flows.add-flow-start")]
+ [:div.add-page {:on-click add-flow}
+ i/plus]]
+ [:& flow-item {:flow flow :key (str (:id flow))}])]))))
(mf/defc interaction-entry
[{:keys [index shape interaction update-interaction remove-interaction]}]
- (let [objects (deref refs/workspace-page-objects)
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ objects (deref refs/workspace-page-objects)
destination (get objects (:destination interaction))
frames (mf/with-memo [objects] (ctt/get-viewer-frames objects {:all-frames? true}))
@@ -191,49 +272,75 @@
close-click-outside? (:close-click-outside interaction false)
background-overlay? (:background-overlay interaction false)
preserve-scroll? (:preserve-scroll interaction false)
+
way (-> interaction :animation :way)
direction (-> interaction :animation :direction)
- extended-open? (mf/use-state false)
+ state* (mf/use-state false)
+ extended-open? (deref state*)
+
+ toggle-extended (mf/use-fn #(swap! state* not))
ext-delay-ref (mf/use-ref nil)
ext-duration-ref (mf/use-ref nil)
change-event-type
- (fn [event]
- (let [value (-> event dom/get-target dom/get-value d/read-string)]
- (update-interaction index #(ctsi/set-event-type % value shape))))
+ (mf/use-fn
+ (mf/deps index)
+ (fn [event]
+ (let [value (if new-css-system
+ (keyword event)
+ (-> event dom/get-target dom/get-value d/read-string))]
+ (update-interaction index #(ctsi/set-event-type % value shape)))))
change-action-type
- (fn [event]
- (let [value (-> event dom/get-target dom/get-value d/read-string)]
- (update-interaction index #(ctsi/set-action-type % value))))
+ (mf/use-fn
+ (mf/deps index)
+ (fn [event]
+ (let [value (if new-css-system
+ (keyword event)
+ (-> event dom/get-target dom/get-value d/read-string))]
+ (update-interaction index #(ctsi/set-action-type % value)))))
change-delay
- (fn [value]
- (update-interaction index #(ctsi/set-delay % value)))
+ (mf/use-fn
+ (mf/deps index)
+ (fn [value]
+ (update-interaction index #(ctsi/set-delay % value))))
change-destination
- (fn [event]
- (let [value (-> event dom/get-target dom/get-value)
- value (when (not= value "") (uuid/uuid value))]
- (update-interaction index #(ctsi/set-destination % value))))
+ (mf/use-fn
+ (mf/deps index)
+ (fn [event]
+ (let [value (if new-css-system
+ event
+ (-> event dom/get-target dom/get-value))
+ value (when (not= value "") (uuid/uuid value))]
+ (update-interaction index #(ctsi/set-destination % value)))))
change-position-relative-to
- (fn [event]
- (let [value (-> event
- dom/get-target
- dom/get-value
- uuid/uuid)]
- (update-interaction index #(ctsi/set-position-relative-to % value))))
+ (mf/use-fn
+ (mf/deps index)
+ (fn [event]
+ (let [value (if new-css-system
+ (uuid/uuid event)
+ (-> event
+ dom/get-target
+ dom/get-value
+ uuid/uuid))]
+ (update-interaction index #(ctsi/set-position-relative-to % value)))))
change-preserve-scroll
- (fn [event]
+ (mf/use-fn
+ (mf/deps index)
+ (fn [event]
(let [value (-> event dom/get-target dom/checked?)]
- (update-interaction index #(ctsi/set-preserve-scroll % value))))
+ (update-interaction index #(ctsi/set-preserve-scroll % value)))))
change-url
- (fn [event]
+ (mf/use-fn
+ (mf/deps index)
+ (fn [event]
(let [target (dom/get-target event)
value (dom/get-value target)
has-prefix? (or (str/starts-with? value "http://")
@@ -247,321 +354,712 @@
(do
(dom/remove-class! target "error")
(update-interaction index #(ctsi/set-url % value)))
- (dom/add-class! target "error"))))
+ (dom/add-class! target "error")))))
change-overlay-pos-type
- (fn [shape-id event]
- (let [value (-> event dom/get-target dom/get-value d/read-string)]
- (update-interaction index #(ctsi/set-overlay-pos-type % value shape objects))
- (when (= value :manual)
- (update-interaction index #(ctsi/set-position-relative-to % shape-id)))))
-
+ (mf/use-fn
+ (mf/deps shape)
+ (fn [event]
+ (let [shape-id (:id shape)
+ value (if new-css-system
+ event
+ (-> event dom/get-target dom/get-value d/read-string))]
+ (update-interaction index #(ctsi/set-overlay-pos-type % value shape objects))
+ (when (= value :manual)
+ (update-interaction index #(ctsi/set-position-relative-to % shape-id))))))
toggle-overlay-pos-type
- (fn [pos-type]
- (update-interaction index #(ctsi/toggle-overlay-pos-type % pos-type shape objects)))
+ (mf/use-fn
+ (mf/deps index)
+ (fn [event]
+ (let [pos-type (-> (dom/get-current-target event)
+ (dom/get-data "value")
+ (keyword))]
+ (update-interaction index #(ctsi/toggle-overlay-pos-type % pos-type shape objects)))))
change-close-click-outside
- (fn [event]
+ (mf/use-fn
+ (mf/deps index)
+ (fn [event]
(let [value (-> event dom/get-target dom/checked?)]
- (update-interaction index #(ctsi/set-close-click-outside % value))))
+ (update-interaction index #(ctsi/set-close-click-outside % value)))))
change-background-overlay
- (fn [event]
+ (mf/use-fn
+ (mf/deps index)
+ (fn [event]
(let [value (-> event dom/get-target dom/checked?)]
- (update-interaction index #(ctsi/set-background-overlay % value))))
+ (update-interaction index #(ctsi/set-background-overlay % value)))))
change-animation-type
- (fn [event]
- (let [value (-> event dom/get-target dom/get-value d/read-string)]
- (update-interaction index #(ctsi/set-animation-type % value))))
+ (mf/use-fn
+ (mf/deps index)
+ (fn [event]
+ (let [value (if new-css-system
+ (if (= "" event)
+ nil
+ (keyword event))
+ (-> event dom/get-target dom/get-value d/read-string))]
+ (update-interaction index #(ctsi/set-animation-type % value)))))
change-duration
- (fn [value]
- (update-interaction index #(ctsi/set-duration % value)))
+ (mf/use-fn(fn [value]
+ (update-interaction index #(ctsi/set-duration % value))))
change-easing
- (fn [event]
- (let [value (-> event dom/get-target dom/get-value d/read-string)]
- (update-interaction index #(ctsi/set-easing % value))))
+ (mf/use-fn
+ (mf/deps index)
+ (fn [event]
+ (let [value (if new-css-system
+ (keyword event)
+ (-> event dom/get-target dom/get-value d/read-string))]
+ (update-interaction index #(ctsi/set-easing % value)))))
change-way
- (fn [event]
- (let [value (-> event dom/get-target dom/get-value d/read-string)]
- (update-interaction index #(ctsi/set-way % value))))
+ (mf/use-fn
+ (mf/deps index)
+ (fn [event]
+ (let [value (if new-css-system
+ (keyword event)
+ (-> event dom/get-target dom/get-value d/read-string))]
+ (update-interaction index #(ctsi/set-way % value)))))
change-direction
- (fn [value]
- (update-interaction index #(ctsi/set-direction % value)))
+ (mf/use-fn
+ (mf/deps index)
+ (fn [event]
+ (let [value (if new-css-system
+ (keyword event)
+ (-> event
+ dom/get-target
+ (dom/get-data "value")
+ keyword))]
+ (update-interaction index #(ctsi/set-direction % value)))))
change-offset-effect
- (fn [event]
+ (mf/use-fn
+ (mf/deps index)
+ (fn [event]
(let [value (-> event dom/get-target dom/checked?)]
- (update-interaction index #(ctsi/set-offset-effect % value))))]
+ (update-interaction index #(ctsi/set-offset-effect % value)))))
- [:*
- [:div.element-set-options-group {:class (dom/classnames
- :open @extended-open?)}
- ; Summary
- [:div.element-set-actions-button {:on-click #(swap! extended-open? not)}
- i/actions]
- [:div.interactions-summary {:on-click #(swap! extended-open? not)}
- [:div.trigger-name (event-type-name interaction)]
- [:div.action-summary (action-summary interaction destination)]]
- [:div.element-set-actions {:on-click #(remove-interaction index)}
- [:div.element-set-actions-button i/minus]]
+ event-type-options [{:value :click :label (tr "workspace.options.interaction-on-click")}
+ ;; TODO: need more UX research
+ ;; :mouse-over (tr "workspace.options.interaction-while-hovering")
+ ;; :mouse-press (tr "workspace.options.interaction-while-pressing")
+ {:value :mouse-enter :label (tr "workspace.options.interaction-mouse-enter")}
+ {:value :mouse-leave :label (tr "workspace.options.interaction-mouse-leave")}
+ {:value :after-delay :label (tr "workspace.options.interaction-after-delay")}]
- (when @extended-open?
- [:div.element-set-content
+ action-type-options [{:value :navigate :label (tr "workspace.options.interaction-navigate-to")}
+ {:value :open-overlay :label (tr "workspace.options.interaction-open-overlay")}
+ {:value :toggle-overlay :label (tr "workspace.options.interaction-toggle-overlay")}
+ {:value :close-overlay :label (tr "workspace.options.interaction-close-overlay")}
+ {:value :prev-screen :label (tr "workspace.options.interaction-prev-screen")}
+ {:value :open-url :label (tr "workspace.options.interaction-open-url")}]
- ;; Trigger select
- [:div.interactions-element.separator
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-trigger")]
- [:select.input-select
- {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (str (:event-type interaction))
- :on-change change-event-type}
- (for [[value name] (event-type-names)]
- (when-not (and (= value :after-delay)
- (not= (:type shape) :frame))
- [:option {:key (dm/str value)
- :value (dm/str value)} name]))]]
+ frames-opts (get-frames-options frames shape)
+
+ default-opts [(if (= (:action-type interaction) :close-overlay)
+ {:value "" :label (tr "workspace.options.interaction-self")}
+ {:value "" :label (tr "workspace.options.interaction-none")})]
+ destination-options
+ (mf/with-memo [frames-opts default-opts]
+ (d/concat-vec default-opts frames-opts))
+
+ shape-parents-opts (get-shared-frames-options shape-parents)
+
+ relative-to-opts
+ (mf/with-memo [shape-parents-opts]
+ (if (not= (:overlay-pos-type interaction) :manual)
+ (d/concat-vec [{:value "" :label (tr "workspace.options.interaction-auto")}]
+ shape-parents-opts
+ [{:value (str (:id shape)) :label (str (:name shape) " (" (tr "workspace.options.interaction-self") ")")}])
+ [{:value (str (:id shape)) :label (str (:name shape) " (" (tr "workspace.options.interaction-self") ")")}]))
+
+ overlay-position-opts [{:value :manual :label (tr "workspace.options.interaction-pos-manual")}
+ {:value :center :label (tr "workspace.options.interaction-pos-center")}
+ {:value :top-left :label (tr "workspace.options.interaction-pos-top-left")}
+ {:value :top-right :label (tr "workspace.options.interaction-pos-top-right")}
+ {:value :top-center :label (tr "workspace.options.interaction-pos-top-center")}
+ {:value :bottom-left :label (tr "workspace.options.interaction-pos-bottom-left")}
+ {:value :bottom-right :label (tr "workspace.options.interaction-pos-bottom-right")}
+ {:value :bottom-center :label (tr "workspace.options.interaction-pos-bottom-center")}]
+
+ basic-animation-opts [{:value "" :label (tr "workspace.options.interaction-animation-none")}
+ {:value :dissolve :label (tr "workspace.options.interaction-animation-dissolve")}
+ {:value :slide :label (tr "workspace.options.interaction-animation-slide")}]
+
+ animation-opts
+ (mf/with-memo [basic-animation-opts]
+ (if (ctsi/allow-push? (:action-type interaction))
+ (d/concat-vec basic-animation-opts [{:value :push :label (tr "workspace.options.interaction-animation-push")}])
+ basic-animation-opts))
+
+ easing-options [{:icon :easing-linear-refactor :value :linear :label (tr "workspace.options.interaction-easing-linear")}
+ {:icon :easing-ease-refactor :value :ease :label (tr "workspace.options.interaction-easing-ease")}
+ {:icon :easing-ease-in-refactor :value :ease-in :label (tr "workspace.options.interaction-easing-ease-in")}
+ {:icon :easing-ease-out-refactor :value :ease-out :label (tr "workspace.options.interaction-easing-ease-out")}
+ {:icon :easing-ease-in-out-refactor :value :ease-in-out :label (tr "workspace.options.interaction-easing-ease-in-out")}]]
+
+
+ (if new-css-system
+ [:div {:class (stl/css-case :element-set-options-group true
+ :open extended-open?)}
+ ; Summary
+ [:div {:class (stl/css :interactions-summary)}
+ [:div {:class (stl/css :extend-btn)
+ :on-click toggle-extended}
+ i/menu-refactor]
+
+ [:div {:class (stl/css :interactions-info)
+ :on-click toggle-extended}
+ [:div {:class (stl/css :trigger-name)} (event-type-name interaction)]
+ [:div {:class (stl/css :action-summary)} (action-summary interaction destination)]]
+ [:button {:class (stl/css :remove-btn)
+ :data-value index
+ :on-click #(remove-interaction index)}
+ i/remove-refactor]]
+
+ (when extended-open?
+ [:div {:class (stl/css :extended-options)}
+ ;; Trigger select
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)}
+ (tr "workspace.options.interaction-trigger")]
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select {:class (stl/css :interaction-type-select)
+ :default-value (:event-type interaction)
+ :options event-type-options
+ :on-change change-event-type}]]]
;; Delay
- (when (ctsi/has-delay interaction)
- [:div.interactions-element
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-delay")]
- [:div.input-element {:title (tr "workspace.options.interaction-ms")}
- [:> numeric-input* {:ref ext-delay-ref
- :on-change change-delay
- :value (:delay interaction)
- :title (tr "workspace.options.interaction-ms")}]
- [:span.after (tr "workspace.options.interaction-ms")]]])
+ (when (ctsi/has-delay interaction)
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)}
+ (tr "workspace.options.interaction-delay")]
+ [:div {:class (stl/css :input-element-wrapper)
+ :title (tr "workspace.options.interaction-ms")}
+ [:span.after (tr "workspace.options.interaction-ms")]
+ [:> numeric-input* {:ref ext-delay-ref
+ :className (stl/css :numeric-input)
+ :on-change change-delay
+ :value (:delay interaction)
+ :title (tr "workspace.options.interaction-ms")}]]])
- ;; Action select
- [:div.interactions-element.separator
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-action")]
- [:select.input-select
- {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (str (:action-type interaction))
- :on-change change-action-type}
- (for [[value name] (action-type-names)]
- [:option {:key (dm/str "action-" value)
- :value (str value)} name])]]
+ ;; Action select
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-action")]
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select {:class (stl/css :interaction-type-select)
+ :default-value (:action-type interaction)
+ :options action-type-options
+ :on-change change-action-type}]]]
- ;; Destination
- (when (ctsi/has-destination interaction)
- [:div.interactions-element
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-destination")]
- [:select.input-select
- {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (str (:destination interaction))
- :on-change change-destination}
- (if (= (:action-type interaction) :close-overlay)
- [:option {:value ""} (tr "workspace.options.interaction-self")]
- [:option {:value ""} (tr "workspace.options.interaction-none")])
- (for [frame frames]
- (when (and (not= (:id frame) (:id shape)) ; A frame cannot navigate to itself
- (not= (:id frame) (:frame-id shape))) ; nor a shape to its container frame
- [:option {:key (dm/str "destination-" (:id frame))
- :value (str (:id frame))} (:name frame)]))]])
+ ;; Destination
+ (when (ctsi/has-destination interaction)
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-destination")]
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select {:class (stl/css :interaction-type-select)
+ :default-value (str (:destination interaction))
+ :options destination-options
+ :on-change change-destination}]]])
- ;; Preserve scroll
- (when (ctsi/has-preserve-scroll interaction)
- [:div.interactions-element
- [:div.input-checkbox
- [:input {:type "checkbox"
- :id (str "preserve-" index)
- :checked preserve-scroll?
- :on-change change-preserve-scroll}]
- [:label {:for (str "preserve-" index)}
- (tr "workspace.options.interaction-preserve-scroll")]]])
+ ;; Preserve scroll
+ (when (ctsi/has-preserve-scroll interaction)
+ [:div {:class (stl/css :property-row)}
+ [:div {:class (stl/css :checkbox-option)}
+ [:label {:for (str "preserve-" index)
+ :class (stl/css-case :global/checked preserve-scroll?)}
+ [:span {:class (stl/css-case :global/checked preserve-scroll?)}
+ (when preserve-scroll?
+ i/status-tick-refactor)]
+ (tr "workspace.options.interaction-preserve-scroll")
+ [:input {:type "checkbox"
+ :id (str "preserve-" index)
+ :checked preserve-scroll?
+ :on-change change-preserve-scroll}]]]])
- ;; URL
- (when (ctsi/has-url interaction)
- [:div.interactions-element
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-url")]
- [:input.input-text {:type "url"
- :placeholder "http://example.com"
- :default-value (str (:url interaction))
- :on-blur change-url}]])
+ ;; URL
+ (when (ctsi/has-url interaction)
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-url")]
+ [:div {:class (stl/css :input-element-wrapper)}
+ [:input {:class (stl/css :input-text)
+ :type "url"
+ :placeholder "http://example.com"
+ :default-value (str (:url interaction))
+ :on-blur change-url}]]])
- (when (ctsi/has-overlay-opts interaction)
- [:*
- ;; Overlay position relative-to (select)
- [:div.interactions-element
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-relative-to")]
- [:select.input-select
- {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (str (:position-relative-to interaction))
- :on-change change-position-relative-to}
- (when (not= (:overlay-pos-type interaction) :manual)
- [:*
- [:option {:value ""} (tr "workspace.options.interaction-auto")]
- (for [frame shape-parents]
- [:option {:key (dm/str "position-relative-to-" (:id frame))
- :value (str (:id frame))} (:name frame)])])
- [:option {:key (dm/str "position-relative-to-" (:id shape))
- :value (str (:id shape))} (:name shape) " (" (tr "workspace.options.interaction-self") ")"]]]
+ (when (ctsi/has-overlay-opts interaction)
+ [:*
+ ;; Overlay position relative-to (select)
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-relative-to")]
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select {:class (stl/css :interaction-type-select)
+ :default-value (str (:position-relative-to interaction))
+ :options relative-to-opts
+ :on-change change-position-relative-to}]]]
- ;; Overlay position (select)
- [:div.interactions-element
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-position")]
- [:select.input-select
- {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (str (:overlay-pos-type interaction))
- :on-change (partial change-overlay-pos-type (:id shape))}
- (for [[value name] (overlay-pos-type-names)]
- [:option {:value (str value)} name])]]
+ ;; Overlay position (select)
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-position")]
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select {:class (stl/css :interaction-type-select)
+ :default-value (:overlay-pos-type interaction)
+ :options overlay-position-opts
+ :on-change change-overlay-pos-type}]]]
- ;; Overlay position (buttons)
- [:div.interactions-element.interactions-pos-buttons
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= overlay-pos-type :center))
- :on-click #(toggle-overlay-pos-type :center)}
- i/position-center]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= overlay-pos-type :top-left))
- :on-click #(toggle-overlay-pos-type :top-left)}
- i/position-top-left]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= overlay-pos-type :top-right))
- :on-click #(toggle-overlay-pos-type :top-right)}
- i/position-top-right]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= overlay-pos-type :top-center))
- :on-click #(toggle-overlay-pos-type :top-center)}
- i/position-top-center]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= overlay-pos-type :bottom-left))
- :on-click #(toggle-overlay-pos-type :bottom-left)}
- i/position-bottom-left]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= overlay-pos-type :bottom-right))
- :on-click #(toggle-overlay-pos-type :bottom-right)}
- i/position-bottom-right]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= overlay-pos-type :bottom-center))
- :on-click #(toggle-overlay-pos-type :bottom-center)}
- i/position-bottom-center]]
+ ;; Overlay position (buttons)
+ [:div {:class (stl/css :property-row)}
+ [:div {:class (stl/css :position-btns-wrapper)}
+ [:button {:class (stl/css-case :direction-btn true
+ :center-btn true
+ :active (= overlay-pos-type :center))
+ :data-value :center
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]
+ [:button {:class (stl/css-case :direction-btn true
+ :top-left-btn true
+ :active (= overlay-pos-type :top-left))
+ :data-value :top-left
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]
+ [:button {:class (stl/css-case :direction-btn true
+ :top-right-btn true
+ :active (= overlay-pos-type :top-right))
+ :data-value :top-right
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]
- ;; Overlay click outside
- [:div.interactions-element
- [:div.input-checkbox
- [:input {:type "checkbox"
- :id (str "close-" index)
- :checked close-click-outside?
- :on-change change-close-click-outside}]
- [:label {:for (str "close-" index)}
- (tr "workspace.options.interaction-close-outside")]]]
+ [:button {:class (stl/css-case :direction-btn true
+ :top-center-btn true
+ :active (= overlay-pos-type :top-center))
+ :data-value :top-center
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]
+ [:button {:class (stl/css-case :direction-btn true
+ :bottom-left-btn true
+ :active (= overlay-pos-type :bottom-left))
+ :data-value :bottom-left
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]
+ [:button {:class (stl/css-case :direction-btn true
+ :bottom-left-btn true
+ :active (= overlay-pos-type :bottom-left))
+ :data-value :bottom-left
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]
+
+ [:button {:class (stl/css-case :direction-btn true
+ :bottom-left-btn true
+ :active (= overlay-pos-type :bottom-left))
+ :data-value :bottom-left
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]
+ [:button {:class (stl/css-case :direction-btn true
+ :bottom-right-btn true
+ :active (= overlay-pos-type :bottom-right))
+ :data-value :bottom-right
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]
+ [:button {:class (stl/css-case :direction-btn true
+ :bottom-center-btn true
+ :active (= overlay-pos-type :bottom-center))
+ :data-value :bottom-center
+ :on-click toggle-overlay-pos-type}
+ [:span {:class (stl/css :rectangle)}]]]]
+
+ ;; Overlay click outside
+ [:div {:class (stl/css :property-row)}
+ [:div {:class (stl/css :checkbox-option)}
+ [:label {:for (str "close-" index)
+ :class (stl/css-case :global/checked close-click-outside?)}
+ [:span {:class (stl/css-case :global/checked close-click-outside?)}
+ (when close-click-outside?
+ i/status-tick-refactor)]
+ (tr "workspace.options.interaction-close-outside")
+ [:input {:type "checkbox"
+ :id (str "close-" index)
+ :checked close-click-outside?
+ :on-change change-close-click-outside}]]]]
;; Overlay background
+ [:div {:class (stl/css :property-row)}
+ [:div {:class (stl/css :checkbox-option)}
+ [:label {:for (str "background-" index)
+ :class (stl/css-case :global/checked background-overlay?)}
+ [:span {:class (stl/css-case :global/checked background-overlay?)}
+ (when background-overlay?
+ i/status-tick-refactor)]
+ (tr "workspace.options.interaction-background")
+ [:input {:type "checkbox"
+ :id (str "background-" index)
+ :checked background-overlay?
+ :on-change change-background-overlay}]]]]])
+
+ (when (ctsi/has-animation? interaction)
+ [:*
+ ;; Animation select
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-animation")]
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select {:class (stl/css :animation-select)
+ :default-value (or (-> interaction :animation :animation-type) "")
+ :options animation-opts
+ :on-change change-animation-type}]]]
+
+ ;; Direction
+ (when (ctsi/has-way? interaction)
+ [:div {:class (stl/css :property-row)}
+ [:div {:class (stl/css :inputs-wrapper)}
+
+ [:& radio-buttons {:selected (d/name way)
+ :on-change change-way
+ :name "animation-way"}
+ [:& radio-button {:value "in"
+ :id "animation-way-in"}]
+ [:& radio-button {:id "animation-way-out"
+ :value "out"}]]]])
+
+ ;; Direction
+ (when (ctsi/has-direction? interaction)
+ [:div {:class (stl/css :property-row)}
+ [:div {:class (stl/css :buttons-wrapper)}
+ [:& radio-buttons {:selected (d/name direction)
+ :on-change change-direction
+ :name "animation-direction"}
+ [:& radio-button {:icon i/column-refactor
+ :icon-class (stl/css :right)
+ :value "right"
+ :id "animation-right"}]
+ [:& radio-button {:icon i/column-refactor
+ :icon-class (stl/css :left)
+ :id "animation-left"
+ :value "left"}]
+ [:& radio-button {:icon i/column-refactor
+ :icon-class (stl/css :down)
+ :id "animation-down"
+ :value "down"}]
+ [:& radio-button {:icon i/column-refactor
+ :icon-class (stl/css :up)
+ :id "animation-up"
+ :value "up"}]]]])
+
+ ;; Duration
+ (when (ctsi/has-duration? interaction)
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-duration")]
+ [:div {:class (stl/css :input-element-wrapper)
+ :title (tr "workspace.options.interaction-ms")}
+ [:span.after (tr "workspace.options.interaction-ms")]
+ [:> numeric-input* {:ref ext-duration-ref
+ :on-change change-duration
+ :value (-> interaction :animation :duration)
+ :title (tr "workspace.options.interaction-ms")}]]])
+
+ ;; Easing
+ (when (ctsi/has-easing? interaction)
+ [:div {:class (stl/css :property-row)}
+ [:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-easing")]
+ [:div {:class (stl/css :select-wrapper)}
+ [:& select {:class (stl/css :easing-select)
+ :default-value (-> interaction :animation :easing)
+ :options easing-options
+ :on-change change-easing}]]])
+
+ ;; Offset effect
+ (when (ctsi/has-offset-effect? interaction)
+ [:div {:class (stl/css :property-row)}
+ [:div {:class (stl/css :checkbox-option)}
+ [:label {:for (str "offset-effect-" index)
+ :class (stl/css-case :global/checked (-> interaction :animation :offset-effect))}
+ [:span {:class (stl/css-case :global/checked (-> interaction :animation :offset-effect))}
+ (when (-> interaction :animation :offset-effect)
+ i/status-tick-refactor)]
+ (tr "workspace.options.interaction-offset-effect")
+ [:input {:type "checkbox"
+ :id (str "offset-effect-" index)
+ :checked (-> interaction :animation :offset-effect)
+ :on-change change-offset-effect}]]]])])])]
+
+
+ [:div.element-set-options-group {:class (dom/classnames
+ :open extended-open?)}
+ ; Summary
+ [:div.element-set-actions-button {:on-click toggle-extended}
+ i/actions]
+ [:div.interactions-summary {:on-click toggle-extended}
+ [:div.trigger-name (event-type-name interaction)]
+ [:div.action-summary (action-summary interaction destination)]]
+ [:div.element-set-actions {:on-click #(remove-interaction index)}
+ [:div.element-set-actions-button i/minus]]
+
+ (when extended-open?
+ [:div.element-set-content
+
+ ;; Trigger select
+ [:div.interactions-element.separator
+ [:span.element-set-subtitle.wide (tr "workspace.options.interaction-trigger")]
+ [:select.input-select
+ {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
+ :value (str (:event-type interaction))
+ :on-change change-event-type}
+ (for [[value name] (event-type-names)]
+ (when-not (and (= value :after-delay)
+ (not= (:type shape) :frame))
+ [:option {:key (dm/str value)
+ :value (dm/str value)} name]))]]
+
+ ;; Delay
+ (when (ctsi/has-delay interaction)
+ [:div.interactions-element
+ [:span.element-set-subtitle.wide (tr "workspace.options.interaction-delay")]
+ [:div.input-element {:title (tr "workspace.options.interaction-ms")}
+ [:> numeric-input* {:ref ext-delay-ref
+ :on-change change-delay
+ :value (:delay interaction)
+ :title (tr "workspace.options.interaction-ms")}]
+ [:span.after (tr "workspace.options.interaction-ms")]]])
+
+ ;; Action select
+ [:div.interactions-element.separator
+ [:span.element-set-subtitle.wide (tr "workspace.options.interaction-action")]
+ [:select.input-select
+ {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
+ :value (str (:action-type interaction))
+ :on-change change-action-type}
+ (for [[value name] (action-type-names)]
+ [:option {:key (dm/str "action-" value)
+ :value (str value)} name])]]
+
+ ;; Destination
+ (when (ctsi/has-destination interaction)
+ [:div.interactions-element
+ [:span.element-set-subtitle.wide (tr "workspace.options.interaction-destination")]
+ [:select.input-select
+ {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
+ :value (str (:destination interaction))
+ :on-change change-destination}
+ (if (= (:action-type interaction) :close-overlay)
+ [:option {:value ""} (tr "workspace.options.interaction-self")]
+ [:option {:value ""} (tr "workspace.options.interaction-none")])
+ (for [frame frames]
+ (when (and (not= (:id frame) (:id shape)) ; A frame cannot navigate to itself
+ (not= (:id frame) (:frame-id shape))) ; nor a shape to its container frame
+ [:option {:key (dm/str "destination-" (:id frame))
+ :value (str (:id frame))} (:name frame)]))]])
+
+ ;; Preserve scroll
+ (when (ctsi/has-preserve-scroll interaction)
[:div.interactions-element
[:div.input-checkbox
[:input {:type "checkbox"
- :id (str "background-" index)
- :checked background-overlay?
- :on-change change-background-overlay}]
- [:label {:for (str "background-" index)}
- (tr "workspace.options.interaction-background")]]]])
+ :id (str "preserve-" index)
+ :checked preserve-scroll?
+ :on-change change-preserve-scroll}]
+ [:label {:for (str "preserve-" index)}
+ (tr "workspace.options.interaction-preserve-scroll")]]])
- (when (ctsi/has-animation? interaction)
- [:*
- ;; Animation select
- [:div.interactions-element.separator
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-animation")]
- [:select.input-select
- {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (str (-> interaction :animation :animation-type))
- :on-change change-animation-type}
- [:option {:value ""} (tr "workspace.options.interaction-animation-none")]
- (for [[value name] (animation-type-names interaction)]
- [:option {:value (str value)} name])]]
+ ;; URL
+ (when (ctsi/has-url interaction)
+ [:div.interactions-element
+ [:span.element-set-subtitle.wide (tr "workspace.options.interaction-url")]
+ [:input.input-text {:type "url"
+ :placeholder "http://example.com"
+ :default-value (str (:url interaction))
+ :on-blur change-url}]])
- ;; Direction
- (when (ctsi/has-way? interaction)
- [:div.interactions-element.interactions-way-buttons
- [:div.input-radio
- [:input {:type "radio"
- :id "way-in"
- :checked (= :in way)
- :name "animation-way"
- :value ":in"
- :on-change change-way}]
- [:label {:for "way-in"} (tr "workspace.options.interaction-in")]]
- [:div.input-radio
- [:input {:type "radio"
- :id "way-out"
- :checked (= :out way)
- :name "animation-way"
- :value ":out"
- :on-change change-way}]
- [:label {:for "way-out"} (tr "workspace.options.interaction-out")]]])
+ (when (ctsi/has-overlay-opts interaction)
+ [:*
+ ;; Overlay position relative-to (select)
+ [:div.interactions-element
+ [:span.element-set-subtitle.wide (tr "workspace.options.interaction-relative-to")]
+ [:select.input-select
+ {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
+ :value (str (:position-relative-to interaction))
+ :on-change change-position-relative-to}
+ (when (not= (:overlay-pos-type interaction) :manual)
+ [:*
+ [:option {:value ""} (tr "workspace.options.interaction-auto")]
+ (for [frame shape-parents]
+ [:option {:key (dm/str "position-relative-to-" (:id frame))
+ :value (str (:id frame))} (:name frame)])])
+ [:option {:key (dm/str "position-relative-to-" (:id shape))
+ :value (str (:id shape))} (:name shape) " (" (tr "workspace.options.interaction-self") ")"]]]
- ;; Direction
- (when (ctsi/has-direction? interaction)
- [:div.interactions-element.interactions-direction-buttons
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= direction :right))
- :on-click #(change-direction :right)}
- i/animate-right]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= direction :down))
- :on-click #(change-direction :down)}
- i/animate-down]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= direction :left))
- :on-click #(change-direction :left)}
- i/animate-left]
- [:div.element-set-actions-button
- {:class (dom/classnames :active (= direction :up))
- :on-click #(change-direction :up)}
- i/animate-up]])
+ ;; Overlay position (select)
+ [:div.interactions-element
+ [:span.element-set-subtitle.wide (tr "workspace.options.interaction-position")]
+ [:select.input-select
+ {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
+ :value (str (:overlay-pos-type interaction))
+ :on-change change-overlay-pos-type}
+ (for [[value name] (overlay-pos-type-names)]
+ [:option {:value (str value)} name])]]
- ;; Duration
- (when (ctsi/has-duration? interaction)
- [:div.interactions-element
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-duration")]
- [:div.input-element {:title (tr "workspace.options.interaction-ms")}
- [:> numeric-input* {:ref ext-duration-ref
- :on-change change-duration
- :value (-> interaction :animation :duration)
- :title (tr "workspace.options.interaction-ms")}]
- [:span.after (tr "workspace.options.interaction-ms")]]])
+ ;; Overlay position (buttons)
+ [:div.interactions-element.interactions-pos-buttons
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= overlay-pos-type :center))
+ :data-value :center
+ :on-click toggle-overlay-pos-type}
+ i/position-center]
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= overlay-pos-type :top-left))
+ :data-value :top-left
+ :on-click toggle-overlay-pos-type}
+ i/position-top-left]
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= overlay-pos-type :top-right))
+ :data-value :top-right
+ :on-click toggle-overlay-pos-type}
+ i/position-top-right]
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= overlay-pos-type :top-center))
+ :data-value :top-center
+ :on-click toggle-overlay-pos-type}
+ i/position-top-center]
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= overlay-pos-type :bottom-left))
+ :data-value :bottom-center
+ :on-click toggle-overlay-pos-type}
+ i/position-bottom-left]
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= overlay-pos-type :bottom-right))
+ :data-value :bottom-right
+ :on-click toggle-overlay-pos-type}
+ i/position-bottom-right]
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= overlay-pos-type :bottom-center))
+ :data-value :bottom-center
+ :on-click toggle-overlay-pos-type}
+ i/position-bottom-center]]
- ;; Easing
- (when (ctsi/has-easing? interaction)
- [:div.interactions-element
- [:span.element-set-subtitle.wide (tr "workspace.options.interaction-easing")]
- [:select.input-select
- {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
- :value (str (-> interaction :animation :easing))
- :on-change change-easing}
- (for [[value name] (easing-names)]
- [:option {:value (str value)} name])]
- [:div.interactions-easing-icon
- (case (-> interaction :animation :easing)
- :linear i/easing-linear
- :ease i/easing-ease
- :ease-in i/easing-ease-in
- :ease-out i/easing-ease-out
- :ease-in-out i/easing-ease-in-out)]])
+ ;; Overlay click outside
+ [:div.interactions-element
+ [:div.input-checkbox
+ [:input {:type "checkbox"
+ :id (str "close-" index)
+ :checked close-click-outside?
+ :on-change change-close-click-outside}]
+ [:label {:for (str "close-" index)}
+ (tr "workspace.options.interaction-close-outside")]]]
- ;; Offset effect
- (when (ctsi/has-offset-effect? interaction)
- [:div.interactions-element
- [:div.input-checkbox
- [:input {:type "checkbox"
- :id (str "offset-effect-" index)
- :checked (-> interaction :animation :offset-effect)
- :on-change change-offset-effect}]
- [:label {:for (str "offset-effect-" index)}
- (tr "workspace.options.interaction-offset-effect")]]])])])]]))
+ ;; Overlay background
+ [:div.interactions-element
+ [:div.input-checkbox
+ [:input {:type "checkbox"
+ :id (str "background-" index)
+ :checked background-overlay?
+ :on-change change-background-overlay}]
+ [:label {:for (str "background-" index)}
+ (tr "workspace.options.interaction-background")]]]])
+
+ (when (ctsi/has-animation? interaction)
+ [:*
+ ;; Animation select
+ [:div.interactions-element.separator
+ [:span.element-set-subtitle.wide (tr "workspace.options.interaction-animation")]
+ [:select.input-select
+ {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
+ :value (str (-> interaction :animation :animation-type))
+ :on-change change-animation-type}
+ [:option {:value ""} (tr "workspace.options.interaction-animation-none")]
+ (for [[value name] (animation-type-names interaction)]
+ [:option {:value (str value)} name])]]
+
+ ;; Direction
+ (when (ctsi/has-way? interaction)
+ [:div.interactions-element.interactions-way-buttons
+ [:div.input-radio
+ [:input {:type "radio"
+ :id "way-in"
+ :checked (= :in way)
+ :name "animation-way"
+ :value ":in"
+ :on-change change-way}]
+ [:label {:for "way-in"} (tr "workspace.options.interaction-in")]]
+ [:div.input-radio
+ [:input {:type "radio"
+ :id "way-out"
+ :checked (= :out way)
+ :name "animation-way"
+ :value ":out"
+ :on-change change-way}]
+ [:label {:for "way-out"} (tr "workspace.options.interaction-out")]]])
+
+ ;; Direction
+ (when (ctsi/has-direction? interaction)
+ [:div.interactions-element.interactions-direction-buttons
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= direction :right))
+ :data-value :right
+ :on-click change-direction}
+ i/animate-right]
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= direction :down))
+ :data-value :up
+ :on-click change-direction}
+ i/animate-down]
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= direction :left))
+ :data-value :left
+ :on-click change-direction}
+ i/animate-left]
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= direction :up))
+ :data-value :down
+ :on-click change-direction}
+ i/animate-up]])
+
+ ;; Duration
+ (when (ctsi/has-duration? interaction)
+ [:div.interactions-element
+ [:span.element-set-subtitle.wide (tr "workspace.options.interaction-duration")]
+ [:div.input-element {:title (tr "workspace.options.interaction-ms")}
+ [:> numeric-input* {:ref ext-duration-ref
+ :on-change change-duration
+ :value (-> interaction :animation :duration)
+ :title (tr "workspace.options.interaction-ms")}]
+ [:span.after (tr "workspace.options.interaction-ms")]]])
+
+ ;; Easing
+ (when (ctsi/has-easing? interaction)
+ [:div.interactions-element
+ [:span.element-set-subtitle.wide (tr "workspace.options.interaction-easing")]
+ [:select.input-select
+ {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
+ :value (str (-> interaction :animation :easing))
+ :on-change change-easing}
+ (for [[value name] (easing-names)]
+ [:option {:value (str value)} name])]
+ [:div.interactions-easing-icon
+ (case (-> interaction :animation :easing)
+ :linear i/easing-linear
+ :ease i/easing-ease
+ :ease-in i/easing-ease-in
+ :ease-out i/easing-ease-out
+ :ease-in-out i/easing-ease-in-out)]])
+
+ ;; Offset effect
+ (when (ctsi/has-offset-effect? interaction)
+ [:div.interactions-element
+ [:div.input-checkbox
+ [:input {:type "checkbox"
+ :id (str "offset-effect-" index)
+ :checked (-> interaction :animation :offset-effect)
+ :on-change change-offset-effect}]
+ [:label {:for (str "offset-effect-" index)}
+ (tr "workspace.options.interaction-offset-effect")]]])])])])))
(mf/defc interactions-menu
[{:keys [shape] :as props}]
- (let [interactions (get shape :interactions [])
+ (let [new-css-system (mf/use-ctx ctx/new-css-system)
+ interactions (get shape :interactions [])
options (mf/deref refs/workspace-page-options)
flows (:flows options)
@@ -577,35 +1075,76 @@
update-interaction
(fn [index update-fn]
(st/emit! (dwi/update-interaction shape index update-fn)))]
- [:*
- (if shape
- [:& shape-flows {:flows flows
- :shape shape}]
- [:& page-flows {:flows flows}])
+ (if new-css-system
+ [:div {:class (stl/css :interactions-content)}
+ (if shape
+ [:& shape-flows {:flows flows
+ :shape shape}]
+ [:& page-flows {:flows flows}])
+ [:div {:class (stl/css :interaction-options)}
+ (when (and shape (not (cph/unframed-shape? shape)))
+ [:div {:class (stl/css :element-title)}
+ [:& title-bar {:collapsable? false
+ :title (tr "workspace.options.interactions")
+ :class (stl/css :title-spacing-layout-interactions)}
- [:div.element-set.interactions-options
- (when (and shape (not (cph/unframed-shape? shape)))
- [:div.element-set-title
- [:span (tr "workspace.options.interactions")]
- [:div.add-page {:on-click add-interaction}
- i/plus]])
- [:div.element-set-content
- (when (= (count interactions) 0)
- [:*
- (when (and shape (not (cph/unframed-shape? shape)))
- [:*
- [:div.interactions-help-icon i/plus]
- [:div.interactions-help.separator (tr "workspace.options.add-interaction")]])
- [:div.interactions-help-icon i/interaction]
- [:div.interactions-help (tr "workspace.options.select-a-shape")]
- [:div.interactions-help-icon i/play]
- [:div.interactions-help (tr "workspace.options.use-play-button")]])]
- [:div.groups
- (for [[index interaction] (d/enumerate interactions)]
- [:& interaction-entry {:key (dm/str (:id shape) "-" index)
- :index index
- :shape shape
- :interaction interaction
- :update-interaction update-interaction
- :remove-interaction remove-interaction}])]]]))
+ [:button {:class (stl/css :add-interaction-btn)
+ :on-click add-interaction}
+ i/add-refactor]]])
+ [:div {:class (stl/css :help-content)}
+ (when (= (count interactions) 0)
+ [:*
+ (when (and shape (not (cph/unframed-shape? shape)))
+ [:div {:class (stl/css :help-group)}
+ [:div {:class (stl/css :interactions-help-icon)} i/add-refactor]
+ [:div {:class (stl/css :interactions-help)}
+ (tr "workspace.options.add-interaction")]])
+ [:div {:class (stl/css :help-group)}
+ [:div {:class (stl/css :interactions-help-icon)} i/interaction-refactor]
+ [:div {:class (stl/css :interactions-help)}
+ (tr "workspace.options.select-a-shape")]]
+ [:div {:class (stl/css :help-group)}
+ [:div {:class (stl/css :interactions-help-icon)} i/play-refactor]
+ [:div {:class (stl/css :interactions-help)}
+ (tr "workspace.options.use-play-button")]]])]
+ [:div {:class (stl/css :groups)}
+ (for [[index interaction] (d/enumerate interactions)]
+ [:& interaction-entry {:key (dm/str (:id shape) "-" index)
+ :index index
+ :shape shape
+ :interaction interaction
+ :update-interaction update-interaction
+ :remove-interaction remove-interaction}])]]]
+
+ [:*
+ (if shape
+ [:& shape-flows {:flows flows
+ :shape shape}]
+ [:& page-flows {:flows flows}])
+
+ [:div.element-set.interactions-options
+ (when (and shape (not (cph/unframed-shape? shape)))
+ [:div.element-set-title
+ [:span (tr "workspace.options.interactions")]
+ [:div.add-page {:on-click add-interaction}
+ i/plus]])
+ [:div.element-set-content
+ (when (= (count interactions) 0)
+ [:*
+ (when (and shape (not (cph/unframed-shape? shape)))
+ [:*
+ [:div.interactions-help-icon i/plus]
+ [:div.interactions-help.separator (tr "workspace.options.add-interaction")]])
+ [:div.interactions-help-icon i/interaction]
+ [:div.interactions-help (tr "workspace.options.select-a-shape")]
+ [:div.interactions-help-icon i/play]
+ [:div.interactions-help (tr "workspace.options.use-play-button")]])]
+ [:div.groups
+ (for [[index interaction] (d/enumerate interactions)]
+ [:& interaction-entry {:key (dm/str (:id shape) "-" index)
+ :index index
+ :shape shape
+ :interaction interaction
+ :update-interaction update-interaction
+ :remove-interaction remove-interaction}])]]])))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.scss
new file mode 100644
index 0000000000..183d8a5f98
--- /dev/null
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.scss
@@ -0,0 +1,244 @@
+// 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";
+
+.interactions-content {
+ display: flex;
+ flex-direction: column;
+ gap: $s-8;
+ .interaction-options {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ .element-title {
+ .add-interaction-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
+ }
+ }
+ }
+
+ .help-content {
+ .help-group {
+ margin-bottom: $s-40;
+ .interactions-help-icon {
+ @include flexCenter;
+ width: $s-48;
+ height: $s-48;
+ border-radius: $br-circle;
+ background-color: var(--pill-background-color);
+ margin: 0 auto $s-12 auto;
+ svg {
+ @extend .button-icon;
+ stroke: var(--icon-foreground);
+ height: $s-32;
+ width: $s-32;
+ }
+ }
+ .interactions-help {
+ @include titleTipography;
+ text-align: center;
+ }
+ }
+ }
+ .groups {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ .element-set-options-group {
+ &.open {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ .extended-options {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ .property-row {
+ @extend .attr-row;
+ .interaction-name {
+ @include twoLineTextEllipsis;
+ @include titleTipography;
+ padding-left: $s-4;
+ width: $s-92;
+ margin: auto 0;
+ grid-area: name;
+ }
+ .select-wrapper {
+ display: flex;
+ align-items: center;
+ grid-area: content;
+ }
+ .input-element-wrapper {
+ @extend .input-element;
+ grid-area: content;
+ }
+ .checkbox-option {
+ @extend .input-checkbox;
+ grid-area: content;
+ }
+ .position-btns-wrapper {
+ grid-area: content;
+ display: grid;
+ grid-template-areas:
+ "topleft top topright"
+ "left center right"
+ "bottomleft bottom bottomright";
+ grid-template-columns: repeat(3, 1fr);
+ grid-template-rows: repeat(3, 1fr);
+ width: $s-84;
+ height: $s-84;
+ border-radius: $br-8;
+ background-color: var(--color-background-tertiary);
+ .direction-btn {
+ @extend .button-tertiary;
+ height: $s-28;
+ width: $s-28;
+ .rectangle {
+ height: $s-8;
+ width: $s-8;
+ background-color: var(--color-background-quaternary);
+ }
+ &:hover {
+ .rectangle {
+ background-color: var(--color-accent-primary);
+ }
+ }
+ &.active {
+ background-color: var(--color-background-quaternary);
+ .rectangle {
+ background-color: var(--color-accent-primary);
+ }
+ }
+ }
+ .center-btn {
+ grid-area: center;
+ }
+ .top-left-btn {
+ grid-area: topleft;
+ }
+ .top-right-btn {
+ grid-area: topright;
+ }
+ .top-center-btn {
+ grid-area: top;
+ }
+ .bottom-left-btn {
+ grid-area: bottomleft;
+ }
+ .bottom-right-btn {
+ grid-area: bottomright;
+ }
+ .bottom-center-btn {
+ grid-area: bottom;
+ }
+ }
+ .buttons-wrapper {
+ grid-area: content;
+ .right svg {
+ transform: rotate(-90deg);
+ }
+ .left svg {
+ transform: rotate(90deg);
+ }
+ .up svg {
+ transform: rotate(180deg);
+ }
+ }
+ .inputs-wrapper {
+ grid-area: content;
+ display: flex;
+ align-items: center;
+ gap: $s-4;
+ .radio-btn {
+ @extend .input-checkbox;
+ }
+ }
+ }
+ }
+ }
+
+ .interactions-summary {
+ @extend .asset-element;
+ height: $s-44;
+ padding: 0;
+ gap: $s-4;
+ .extend-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+
+ .interactions-info {
+ flex-grow: 1;
+ .trigger-name {
+ color: white;
+ }
+ .action-summary {
+ color: var(--color-foreground-secondary);
+ }
+ }
+ .remove-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+ }
+ }
+ }
+ .element-set {
+ display: flex;
+ flex-direction: column;
+ gap: $s-4;
+ .add-flow-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ }
+}
+.flow-element {
+ @extend .asset-element;
+ padding: 0;
+ gap: $s-4;
+ .start-flow-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+ .input-text {
+ @extend .input-base;
+ }
+ .flow-name-label {
+ flex-grow: 1;
+ }
+ .remove-flow-btn {
+ @extend .button-tertiary;
+ height: $s-32;
+ width: $s-28;
+ svg {
+ @extend .button-icon;
+ }
+ }
+}
diff --git a/frontend/translations/en.po b/frontend/translations/en.po
index daed823526..56ec34a5af 100644
--- a/frontend/translations/en.po
+++ b/frontend/translations/en.po
@@ -3676,6 +3676,10 @@ msgstr "Fill"
msgid "workspace.options.flows.add-flow-start"
msgstr "Add flow start"
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.flows.flow"
+msgstr "Flow"
+
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.flows.flow-start"
msgstr "Flow start"
diff --git a/frontend/translations/es.po b/frontend/translations/es.po
index 45b565ce23..3850af90fc 100644
--- a/frontend/translations/es.po
+++ b/frontend/translations/es.po
@@ -3763,6 +3763,10 @@ msgstr "AƱadir inicio de flujo"
msgid "workspace.options.flows.flow-start"
msgstr "Inicio de flujo"
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.flows.flow"
+msgstr "Flujo"
+
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.flows.flow-starts"
msgstr "Inicios de flujo"