diff --git a/frontend/resources/images/icons/grid-justify-content-column-around.svg b/frontend/resources/images/icons/grid-justify-content-column-around.svg
new file mode 100644
index 000000000..65cd17d58
--- /dev/null
+++ b/frontend/resources/images/icons/grid-justify-content-column-around.svg
@@ -0,0 +1,38 @@
+
+
diff --git a/frontend/resources/images/icons/grid-justify-content-column-between.svg b/frontend/resources/images/icons/grid-justify-content-column-between.svg
new file mode 100644
index 000000000..783d91a21
--- /dev/null
+++ b/frontend/resources/images/icons/grid-justify-content-column-between.svg
@@ -0,0 +1,38 @@
+
+
diff --git a/frontend/resources/images/icons/grid-justify-content-column-center.svg b/frontend/resources/images/icons/grid-justify-content-column-center.svg
new file mode 100644
index 000000000..fc52ce5ed
--- /dev/null
+++ b/frontend/resources/images/icons/grid-justify-content-column-center.svg
@@ -0,0 +1,38 @@
+
+
diff --git a/frontend/resources/images/icons/grid-justify-content-column-end.svg b/frontend/resources/images/icons/grid-justify-content-column-end.svg
new file mode 100644
index 000000000..18825a412
--- /dev/null
+++ b/frontend/resources/images/icons/grid-justify-content-column-end.svg
@@ -0,0 +1,38 @@
+
+
diff --git a/frontend/resources/images/icons/grid-justify-content-column-start.svg b/frontend/resources/images/icons/grid-justify-content-column-start.svg
new file mode 100644
index 000000000..823ef4ebf
--- /dev/null
+++ b/frontend/resources/images/icons/grid-justify-content-column-start.svg
@@ -0,0 +1,38 @@
+
+
diff --git a/frontend/resources/images/icons/grid-justify-content-row-around.svg b/frontend/resources/images/icons/grid-justify-content-row-around.svg
new file mode 100644
index 000000000..41a980b7f
--- /dev/null
+++ b/frontend/resources/images/icons/grid-justify-content-row-around.svg
@@ -0,0 +1,38 @@
+
+
diff --git a/frontend/resources/images/icons/grid-justify-content-row-between.svg b/frontend/resources/images/icons/grid-justify-content-row-between.svg
new file mode 100644
index 000000000..bfc38460a
--- /dev/null
+++ b/frontend/resources/images/icons/grid-justify-content-row-between.svg
@@ -0,0 +1,38 @@
+
+
diff --git a/frontend/resources/images/icons/grid-justify-content-row-center.svg b/frontend/resources/images/icons/grid-justify-content-row-center.svg
new file mode 100644
index 000000000..402b8dba2
--- /dev/null
+++ b/frontend/resources/images/icons/grid-justify-content-row-center.svg
@@ -0,0 +1,38 @@
+
+
diff --git a/frontend/resources/images/icons/grid-justify-content-row-end.svg b/frontend/resources/images/icons/grid-justify-content-row-end.svg
new file mode 100644
index 000000000..3515d5a95
--- /dev/null
+++ b/frontend/resources/images/icons/grid-justify-content-row-end.svg
@@ -0,0 +1,38 @@
+
+
diff --git a/frontend/resources/images/icons/grid-justify-content-row-start.svg b/frontend/resources/images/icons/grid-justify-content-row-start.svg
new file mode 100644
index 000000000..6539a9314
--- /dev/null
+++ b/frontend/resources/images/icons/grid-justify-content-row-start.svg
@@ -0,0 +1,38 @@
+
+
diff --git a/frontend/resources/styles/main/partials/sidebar-element-options.scss b/frontend/resources/styles/main/partials/sidebar-element-options.scss
index 914a88b61..f5265b7bd 100644
--- a/frontend/resources/styles/main/partials/sidebar-element-options.scss
+++ b/frontend/resources/styles/main/partials/sidebar-element-options.scss
@@ -1649,6 +1649,12 @@
align-items: start;
margin-top: 4px;
}
+
+ &.align-items-grid,
+ &.jusfiy-content-grid {
+ align-items: start;
+ margin-top: 11px;
+ }
}
.btn-wrapper {
display: flex;
@@ -1748,6 +1754,34 @@
width: 30px;
}
}
+
+ .edit-mode {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin-left: 5px;
+
+ button {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ background: transparent;
+ border: none;
+ cursor: pointer;
+ &.active,
+ &:hover {
+ svg {
+ fill: $color-primary;
+ }
+ }
+ }
+ }
+
+ &.align-grid {
+ flex-direction: column;
+ gap: 7px;
+ margin: 7px 0;
+ }
}
}
.no-wrap {
@@ -2076,6 +2110,116 @@
}
}
}
+
+ .grid-columns {
+ border: 1px solid $color-gray-60;
+ padding: 5px;
+ min-height: 38px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ &:not(:first-child) {
+ margin-top: 5px;
+ }
+ .grid-columns-header {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+ height: 100%;
+ flex-grow: 1;
+ min-height: 36px;
+ .columns-info {
+ flex-grow: 1;
+ font-size: 12px;
+ }
+ .expand-icon,
+ .add-column {
+ cursor: pointer;
+ background-color: transparent;
+ border: none;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ &.active,
+ &:hover {
+ svg {
+ fill: $color-primary;
+ }
+ }
+ }
+
+ .add-column svg {
+ height: 12px;
+ width: 12px;
+ fill: $color-gray-20;
+ }
+ }
+ .columns-info-wrapper {
+ .column-info {
+ display: grid;
+ grid-template-columns: 35px 1fr 1fr auto;
+ background-color: $color-gray-60;
+ padding: 3px;
+ &:not(:first-child) {
+ margin-top: 3px;
+ }
+ .direction-grid-icon {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 5px;
+ }
+ input {
+ background-color: $color-gray-60;
+ }
+ .grid-column-value,
+ .grid-column-unit {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 30px;
+ &.active,
+ &:focus,
+ &:focus-within {
+ border-bottom: 1px solid $color-primary;
+ }
+ }
+ .grid-column-unit-selector {
+ border: none;
+ border-bottom: 1px solid $color-gray-30;
+ margin: 0.25rem 0;
+ height: 23px;
+ width: 100%;
+ &:hover {
+ border-bottom: 1px solid $color-gray-20;
+ }
+ }
+
+ .remove-grid-column {
+ cursor: pointer;
+ background-color: transparent;
+ border: none;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin-left: 40px;
+ svg {
+ height: 12px;
+ width: 12px;
+ fill: $color-gray-20;
+ }
+ &.active,
+ &:hover {
+ svg {
+ fill: $color-primary;
+ }
+ }
+ }
+ }
+ }
+ }
}
.advanced-ops {
diff --git a/frontend/src/app/main/ui/icons.cljs b/frontend/src/app/main/ui/icons.cljs
index e7427a13e..6d511b0d8 100644
--- a/frontend/src/app/main/ui/icons.cljs
+++ b/frontend/src/app/main/ui/icons.cljs
@@ -114,6 +114,16 @@
(def full-screen-off (icon-xref :full-screen-off))
(def grid (icon-xref :grid))
(def grid-snap (icon-xref :grid-snap))
+(def grid-justify-content-column-around (icon-xref :grid-justify-content-column-around))
+(def grid-justify-content-column-between (icon-xref :grid-justify-content-column-between))
+(def grid-justify-content-column-center (icon-xref :grid-justify-content-column-center))
+(def grid-justify-content-column-end (icon-xref :grid-justify-content-column-end))
+(def grid-justify-content-column-start (icon-xref :grid-justify-content-column-start))
+(def grid-justify-content-row-around (icon-xref :grid-justify-content-row-around))
+(def grid-justify-content-row-between (icon-xref :grid-justify-content-row-between))
+(def grid-justify-content-row-center (icon-xref :grid-justify-content-row-center))
+(def grid-justify-content-row-end (icon-xref :grid-justify-content-row-end))
+(def grid-justify-content-row-start (icon-xref :grid-justify-content-row-start))
(def go-next (icon-xref :go-next))
(def go-prev (icon-xref :go-prev))
(def help (icon-xref :help))
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs
index 925d0a84c..fd4f032e1 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs
@@ -11,6 +11,7 @@
[app.main.data.workspace.shape-layout :as dwsl]
[app.main.store :as st]
[app.main.ui.components.numeric-input :refer [numeric-input]]
+ [app.main.ui.components.select :refer [select]]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[cuerdas.core :as str]
@@ -94,8 +95,25 @@
:stretch i/align-self-column-strech
:baseline i/align-self-column-baseline))))
+(defn get-layout-grid-icon
+ [type val is-col?]
+ (case type
+ :justify-content (if is-col?
+ (case val
+ :start i/grid-justify-content-column-start
+ :end i/grid-justify-content-column-end
+ :center i/grid-justify-content-column-center
+ :space-around i/grid-justify-content-column-around
+ :space-between i/grid-justify-content-column-between)
+ (case val
+ :start i/grid-justify-content-row-start
+ :end i/grid-justify-content-row-end
+ :center i/grid-justify-content-row-center
+ :space-around i/grid-justify-content-row-around
+ :space-between i/grid-justify-content-row-between))))
+
(mf/defc direction-btn
- [{:keys [dir saved-dir set-direction] :as props}]
+ [{:keys [dir saved-dir set-direction icon?] :as props}]
(let [handle-on-click
(mf/use-callback
(mf/deps set-direction dir)
@@ -112,7 +130,9 @@
:key (dm/str "direction-" dir)
:alt (str/replace (str/capital (d/name dir)) "-" " ")
:on-click handle-on-click}
- i/auto-direction]))
+ (if icon?
+ i/auto-direction
+ (str/replace (str/capital (d/name dir)) "-" " "))]))
(mf/defc wrap-row
[{:keys [wrap-type set-wrap] :as props}]
@@ -299,6 +319,108 @@
:value (:row-gap gap-value)
:disabled (and (= :nowrap wrap-type) (not is-col?))}]]]])
+(mf/defc grid-edit-mode
+ [{:keys [active toggle-edit-mode] :as props}]
+ [:*
+ [:button.tooltip.tooltip-bottom-left
+ {:class (dom/classnames :active (= active true))
+ :alt "Grid edit mode"
+ :on-click #(toggle-edit-mode)
+ :style {:padding 0}}
+ i/set-thumbnail]])
+
+(mf/defc align-grid-row
+ [{:keys [is-col? align-items set-align] :as props}]
+ (let [type (if is-col?
+ :column
+ :row)]
+ [:div.align-items-style
+ (for [align [:start :center :end :stretch :baseline]]
+ [:button.align-start.tooltip
+ {:class (dom/classnames :active (= align-items align)
+ :tooltip-bottom-left (not= align :start)
+ :tooltip-bottom (= align :start))
+ :alt (dm/str "Align items " (d/name align))
+ :on-click #(set-align align % type)
+ :key (dm/str "align-items" (d/name align))}
+ (get-layout-flex-icon :align-items align is-col?)])]))
+
+(mf/defc justify-grid-row
+ [{:keys [is-col? justify-items set-justify] :as props}]
+ (let [type (if is-col?
+ :column
+ :row)]
+ [:div.justify-content-style
+ (for [align [:start :center :end :space-around :space-between]]
+ [:button.align-start.tooltip
+ {:class (dom/classnames :active (= justify-items align)
+ :tooltip-bottom-left (not= align :start)
+ :tooltip-bottom (= align :start))
+ :alt (dm/str "Justify content " (d/name align))
+ :on-click #(set-justify align % type)
+ :key (dm/str "justify-content" (d/name align))}
+ (get-layout-grid-icon :justify-content align is-col?)])]))
+
+(defn manage-values [value]
+ (let [quantity (:value value)
+ unit (:unit value)]
+ (case unit
+ :auto (d/name unit)
+ :perc (str/join [quantity "%"])
+ (str/join [quantity (d/name unit)]))))
+
+(mf/defc grid-columns-row
+ [{:keys [is-col? expanded? column-values toggle add-new-element set-column-value handle-focus handle-blur on-unit-change remove-column] :as props}]
+ (let [column-num (count column-values)
+ direction (if (< 1 column-num)
+ (if is-col?
+ "Columns "
+ "Rows ")
+ (if is-col?
+ "Column "
+ "Row "))
+ column-vals (str/join ", " (map manage-values column-values))
+ generated-name (str direction column-num " (" column-vals ")")]
+ [:div.grid-columns
+ [:div.grid-columns-header
+ [:button.expand-icon
+ {:on-click toggle}
+ i/actions]
+
+ [:div.columns-info
+ generated-name]
+ [:button.add-column
+ {:on-click add-new-element}
+ i/plus]]
+ (when expanded?
+ [:div.columns-info-wrapper
+ (for [column column-values]
+ [:div.column-info
+ [:div.direction-grid-icon
+ (if is-col?
+ i/layout-rows
+ i/layout-columns)]
+
+ [:div.grid-column-value
+ [:> numeric-input {:no-validate true
+ :value (:value column)
+ :on-change set-column-value
+ :on-focus handle-focus
+ :on-blur handle-blur
+ :placeholder "--"}]]
+ [:div.grid-column-unit
+ [:& select
+ {:class "grid-column-unit-selector"
+ :default-value (:unit column)
+ :options [{:value :fr :label "fr"}
+ {:value :auto :label "auto"}
+ {:value :px :label "px"}
+ {:value :perc :label "%"}]
+ :on-change on-unit-change}]]
+ [:button.remove-grid-column
+ {:on-change remove-column}
+ i/minus]])])]))
+
(mf/defc layout-container-menu
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "type" "multiple"]))]}
[{:keys [ids _type values multiple] :as props}]
@@ -322,7 +444,7 @@
set-flex (fn []
(st/emit! (dwsl/remove-layout ids))
(on-add-layout :flex))
-
+
set-grid (fn []
(st/emit! (dwsl/remove-layout ids))
(on-add-layout :grid))
@@ -331,9 +453,6 @@
saved-dir (:layout-flex-dir values)
is-col? (or (= :column saved-dir) (= :column-reverse saved-dir))
- set-direction
- (fn [dir]
- (st/emit! (dwsl/update-layout ids {:layout-flex-dir dir})))
;; Wrap type
@@ -386,7 +505,63 @@
(st/emit! (dwsl/update-layout ids {:layout-padding {:p2 val :p4 val}}))
:else
- (st/emit! (dwsl/update-layout ids {:layout-padding {prop val}}))))]
+ (st/emit! (dwsl/update-layout ids {:layout-padding {prop val}}))))
+
+ ;; Grid-direction
+
+ saved-grid-dir (:layout-grid-dir values)
+
+ set-direction
+ (fn [dir type]
+ (if (= :flex type)
+ (st/emit! (dwsl/update-layout ids {:layout-flex-dir dir}))
+ (st/emit! (dwsl/update-layout ids {:layout-grid-dir dir}))))
+
+ ;; Align grid
+ align-items-row (:layout-grid-align-row values)
+ align-items-column (:layout-grid-align-column values)
+ set-align-grid (fn [value type]
+ (if (= type :row)
+ (st/emit! (dwsl/update-layout ids {:layout-grid-align-row value}))
+ (st/emit! (dwsl/update-layout ids {:layout-grid-align-column value}))))
+
+ ;; Justify grid
+ grid-justify-content-row (:layout-grid-justify-row values)
+ grid-justify-content-column (:layout-grid-justify-column values)
+ set-justify-grid (fn [value type]
+ (if (= type :row)
+ (st/emit! (dwsl/update-layout ids {:layout-grid-justify-row value}))
+ (st/emit! (dwsl/update-layout ids {:layout-grid-justify-column value}))))
+
+
+ ;;Grid columns
+
+ column-grid-values (:layout-grid-column-values values)
+ grid-columns-open? (mf/use-state false)
+ toggle-columns-info (mf/use-callback
+ (fn [_]
+ (swap! grid-columns-open? not)))
+
+
+
+ ; Grid rows / columns
+ rows-grid-values (:layout-grid-row-values values)
+ grid-rows-open? (mf/use-state false)
+ toggle-rows-info (mf/use-callback
+ (fn [_]
+ (swap! grid-rows-open? not)))
+
+ ;; TODO -> fix this, is doing nothing
+ add-new-element (fn [value type]
+ (if (= type :row)
+ (st/emit! (dwsl/update-layout ids {:layout-grid-row-values value}))
+ (st/emit! (dwsl/update-layout ids {:layout-grid-column-values value}))))
+
+ set-column-value (fn[] )
+ handle-focus (fn [])
+ handle-blur (fn [])
+ set-colum-unit (fn [])
+ remove-column (fn [])]
[:div.element-set
[:div.element-set-title
@@ -395,12 +570,12 @@
(if (and (not multiple) (:layout values))
[:div.title-actions
[:div.layout-btns
- [:button {:on-click set-flex
- :class (dom/classnames
- :active (= :flex layout-type))} "Flex"]
- [:button {:on-click set-grid
- :class (dom/classnames
- :active (= :grid layout-type))} "Grid"]]
+ [:button {:on-click set-flex
+ :class (dom/classnames
+ :active (= :flex layout-type))} "Flex"]
+ [:button {:on-click set-grid
+ :class (dom/classnames
+ :active (= :grid layout-type))} "Grid"]]
[:button.remove-layout {:on-click on-remove-layout} i/minus]]
[:button.add-page {:on-click #(on-add-layout :flex)} i/close])]]
@@ -418,7 +593,8 @@
[:& direction-btn {:key (d/name dir)
:dir dir
:saved-dir saved-dir
- :set-direction set-direction}])]]
+ :set-direction #(set-direction dir :flex)
+ :icon? true}])]]
[:div.wrap-type
[:& wrap-row {:wrap-type wrap-type
@@ -456,4 +632,73 @@
:on-change-style change-padding-type
:on-change on-padding-change}]]
- [:div "GRID TO COME"])))]))
+ [:div.element-set-content.layout-menu
+ [:div.layout-row
+ [:div.direction-wrap.row-title "Direction"]
+ [:div.btn-wrapper
+ [:div.direction
+ [:*
+ (for [dir [:row :column]]
+ [:& direction-btn {:key (d/name dir)
+ :dir dir
+ :saved-dir saved-grid-dir
+ :set-direction #(set-direction dir :grid)
+ :icon? false}])]]
+
+ [:div.edit-mode
+ [:& grid-edit-mode
+ {:active false
+ :toggle-edit-mode ()}]]]]
+
+ [:div.layout-row
+ [:div.align-items-grid.row-title "Align"]
+ [:div.btn-wrapper.align-grid
+ [:& align-grid-row {:is-col? false
+ :align-items align-items-row
+ :set-align set-align-grid}]
+
+ [:& align-grid-row {:is-col? true
+ :align-items align-items-column
+ :set-align set-align-grid}]]]
+
+ [:div.layout-row
+ [:div.jusfiy-content-grid.row-title "Justify"]
+ [:div.btn-wrapper.align-grid
+ [:& justify-grid-row {:is-col? true
+ :align-items grid-justify-content-column
+ :set-justify set-justify-grid}]
+ [:& justify-grid-row {:is-col? false
+ :align-items grid-justify-content-row
+ :set-justify set-justify-grid}]]]
+
+ [:& grid-columns-row {:is-col? true
+ :expanded? @grid-columns-open?
+ :toggle toggle-columns-info
+ :column-values [{:value 1 :unit :fr} {:value 1 :unit :fr}];; column-grid-values
+ :add-new-column add-new-element
+ :set-column-value set-column-value
+ :handle-focus handle-focus
+ :handle-blur handle-blur
+ :set-colum-unit set-colum-unit
+ :remove-column remove-column}]
+
+ [:& grid-columns-row {:is-col? false
+ :expanded? @grid-rows-open?
+ :toggle toggle-rows-info
+ :column-values [{:value "--" :unit :auto} {:value "--" :unit :auto}] ;; column-grid-values
+ :add-new-column add-new-element
+ :set-column-value set-column-value
+ :handle-focus handle-focus
+ :handle-blur handle-blur
+ :set-colum-unit set-colum-unit
+ :remove-column remove-column}]
+
+ [:& gap-section {:is-col? is-col?
+ :wrap-type wrap-type
+ :gap-selected? gap-selected?
+ :set-gap set-gap
+ :gap-value (:layout-gap values)}]
+
+ [:& padding-section {:values values
+ :on-change-style change-padding-type
+ :on-change on-padding-change}]])))]))