mirror of
https://github.com/penpot/penpot.git
synced 2026-04-25 11:18:36 +00:00
🎉 Add new page separators feature (#8561)
* 🎉 Add new page separators feature * 📎 Add PR feedback changes * 🐛 Fix page sitemap icons --------- Co-authored-by: Andrey Antukh <niwi@niwi.nz>
This commit is contained in:
parent
adea81ceee
commit
876b8d645d
@ -43,6 +43,8 @@
|
|||||||
- Edit ruler guide position by double-clicking the guide pill (by @eureka0928) [Github #2311](https://github.com/penpot/penpot/issues/2311)
|
- Edit ruler guide position by double-clicking the guide pill (by @eureka0928) [Github #2311](https://github.com/penpot/penpot/issues/2311)
|
||||||
- Add a search bar to filter colors in the color palette toolbar (by @eureka0928) [Github #7653](https://github.com/penpot/penpot/issues/7653)
|
- Add a search bar to filter colors in the color palette toolbar (by @eureka0928) [Github #7653](https://github.com/penpot/penpot/issues/7653)
|
||||||
- Allow customising the OIDC login button label (by @wdeveloper16) [Github #7027](https://github.com/penpot/penpot/issues/7027)
|
- Allow customising the OIDC login button label (by @wdeveloper16) [Github #7027](https://github.com/penpot/penpot/issues/7027)
|
||||||
|
- Add page separators in Workspace [Taiga #13611](https://tree.taiga.io/project/penpot/us/13611?milestone=262806)
|
||||||
|
|
||||||
|
|
||||||
### :bug: Bugs fixed
|
### :bug: Bugs fixed
|
||||||
|
|
||||||
|
|||||||
@ -331,8 +331,21 @@
|
|||||||
(let [page (dsh/lookup-page state id)
|
(let [page (dsh/lookup-page state id)
|
||||||
changes (-> (pcb/empty-changes it)
|
changes (-> (pcb/empty-changes it)
|
||||||
(pcb/with-page page)
|
(pcb/with-page page)
|
||||||
(pcb/mod-page page {:name name}))]
|
(pcb/mod-page page {:name name}))
|
||||||
(rx/of (dch/commit-changes changes))))))
|
pages (-> (dsh/lookup-file-data state) :pages)
|
||||||
|
index (d/index-of pages id)
|
||||||
|
prev-id (when (and (some? index) (pos? index))
|
||||||
|
(nth pages (dec index) nil))
|
||||||
|
next-id (when (some? index)
|
||||||
|
(nth pages (inc index) nil))
|
||||||
|
fallback-page-id (or prev-id next-id)
|
||||||
|
separator? (= "---" (str/trim name))]
|
||||||
|
(rx/concat
|
||||||
|
(rx/of (dch/commit-changes changes))
|
||||||
|
(when (and separator?
|
||||||
|
(= id (:current-page-id state))
|
||||||
|
(some? fallback-page-id))
|
||||||
|
(rx/of (dcm/go-to-workspace :page-id fallback-page-id))))))))
|
||||||
|
|
||||||
(defn- delete-page-components
|
(defn- delete-page-components
|
||||||
[changes page]
|
[changes page]
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
[:tooltip-class {:optional true} [:maybe :string]]
|
[:tooltip-class {:optional true} [:maybe :string]]
|
||||||
[:type {:optional true} [:maybe [:enum "button" "submit" "reset"]]]
|
[:type {:optional true} [:maybe [:enum "button" "submit" "reset"]]]
|
||||||
[:icon-class {:optional true} :string]
|
[:icon-class {:optional true} :string]
|
||||||
|
[:icon-size {:optional true} [:maybe [:enum "s" "m" "l"]]]
|
||||||
[:icon
|
[:icon
|
||||||
[:and :string [:fn #(contains? icon-list %)]]]
|
[:and :string [:fn #(contains? icon-list %)]]]
|
||||||
[:aria-label :string]
|
[:aria-label :string]
|
||||||
@ -30,7 +31,7 @@
|
|||||||
(mf/defc icon-button*
|
(mf/defc icon-button*
|
||||||
{::mf/schema schema:icon-button
|
{::mf/schema schema:icon-button
|
||||||
::mf/memo true}
|
::mf/memo true}
|
||||||
[{:keys [class icon icon-class variant aria-label children tooltip-placement tooltip-class type] :rest props}]
|
[{:keys [class icon icon-class icon-size variant aria-label children tooltip-placement tooltip-class type] :rest props}]
|
||||||
(let [variant
|
(let [variant
|
||||||
(d/nilv variant "primary")
|
(d/nilv variant "primary")
|
||||||
|
|
||||||
@ -60,5 +61,5 @@
|
|||||||
:placement tooltip-placement
|
:placement tooltip-placement
|
||||||
:id tooltip-id}
|
:id tooltip-id}
|
||||||
[:> :button props
|
[:> :button props
|
||||||
[:> icon* {:icon-id icon :aria-hidden true :class icon-class}]
|
[:> icon* {:icon-id icon :aria-hidden true :class icon-class :size icon-size}]
|
||||||
children]]))
|
children]]))
|
||||||
|
|||||||
@ -322,22 +322,16 @@
|
|||||||
(mf/defc icon*
|
(mf/defc icon*
|
||||||
{::mf/schema schema:icon}
|
{::mf/schema schema:icon}
|
||||||
[{:keys [icon-id size class] :rest props}]
|
[{:keys [icon-id size class] :rest props}]
|
||||||
(let [props (mf/spread-props props
|
(let [size-px (cond (= size "l") icon-size-l
|
||||||
{:class [class (stl/css :icon)]
|
|
||||||
:width icon-size-m
|
|
||||||
:height icon-size-m})
|
|
||||||
|
|
||||||
size-px (cond (= size "l") icon-size-l
|
|
||||||
(= size "s") icon-size-s
|
(= size "s") icon-size-s
|
||||||
:else icon-size-m)
|
:else icon-size-m)
|
||||||
|
|
||||||
offset (if (or (= size "s") (= size "m"))
|
props (mf/spread-props props
|
||||||
(/ (- icon-size-m size-px) 2)
|
{:class [class (stl/css :icon)]
|
||||||
0)]
|
:width size-px
|
||||||
|
:height size-px})]
|
||||||
|
|
||||||
[:> :svg props
|
[:> :svg props
|
||||||
[:use {:href (dm/str "#icon-" icon-id)
|
[:use {:href (dm/str "#icon-" icon-id)
|
||||||
:width size-px
|
:width size-px
|
||||||
:height size-px
|
:height size-px}]]))
|
||||||
:x offset
|
|
||||||
:y offset}]]))
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
|
[app.common.types.page :as ctp]
|
||||||
[app.main.data.common :as dcm]
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.helpers :as dsh]
|
[app.main.data.helpers :as dsh]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
@ -19,9 +20,8 @@
|
|||||||
[app.main.ui.components.title-bar :refer [title-bar*]]
|
[app.main.ui.components.title-bar :refer [title-bar*]]
|
||||||
[app.main.ui.context :as ctx]
|
[app.main.ui.context :as ctx]
|
||||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||||
[app.main.ui.ds.foundations.assets.icon :as i]
|
[app.main.ui.ds.foundations.assets.icon :as i :refer [icon*]]
|
||||||
[app.main.ui.hooks :as hooks]
|
[app.main.ui.hooks :as hooks]
|
||||||
[app.main.ui.icons :as deprecated-icon]
|
|
||||||
[app.main.ui.notifications.badge :refer [badge-notification]]
|
[app.main.ui.notifications.badge :refer [badge-notification]]
|
||||||
[app.render-wasm.api :as wasm.api]
|
[app.render-wasm.api :as wasm.api]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
@ -50,8 +50,10 @@
|
|||||||
each object change)"
|
each object change)"
|
||||||
[page-id]
|
[page-id]
|
||||||
(l/derived (fn [fdata]
|
(l/derived (fn [fdata]
|
||||||
(-> (dsh/get-page fdata page-id)
|
(let [page (dsh/get-page fdata page-id)]
|
||||||
(dissoc :objects)))
|
(-> page
|
||||||
|
(assoc :empty? (ctp/is-empty? page))
|
||||||
|
(dissoc :objects))))
|
||||||
refs/workspace-data
|
refs/workspace-data
|
||||||
=))
|
=))
|
||||||
|
|
||||||
@ -64,14 +66,17 @@
|
|||||||
[{:keys [page index deletable? selected? editing? hovering? current-page-id]}]
|
[{:keys [page index deletable? selected? editing? hovering? current-page-id]}]
|
||||||
(let [input-ref (mf/use-ref)
|
(let [input-ref (mf/use-ref)
|
||||||
id (:id page)
|
id (:id page)
|
||||||
|
name (:name page "")
|
||||||
|
is-separator? (and (= "---" (str/trim name)) (:empty? page))
|
||||||
delete-fn (mf/use-fn (mf/deps id) #(st/emit! (dw/delete-page id)))
|
delete-fn (mf/use-fn (mf/deps id) #(st/emit! (dw/delete-page id)))
|
||||||
navigate-fn (mf/use-fn (mf/deps id) #(st/emit! :interrupt (dcm/go-to-workspace :page-id id)))
|
navigate-fn (mf/use-fn (mf/deps id) #(st/emit! :interrupt (dcm/go-to-workspace :page-id id)))
|
||||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||||
|
|
||||||
on-click
|
on-click
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps id current-page-id)
|
(mf/deps id current-page-id is-separator?)
|
||||||
(fn []
|
(fn []
|
||||||
|
(when-not is-separator?
|
||||||
;; For the wasm renderer, apply a blur effect to the viewport canvas
|
;; For the wasm renderer, apply a blur effect to the viewport canvas
|
||||||
;; when we navigate to a different page.
|
;; when we navigate to a different page.
|
||||||
(if (and (features/active-feature? @st/state "render-wasm/v1")
|
(if (and (features/active-feature? @st/state "render-wasm/v1")
|
||||||
@ -84,7 +89,7 @@
|
|||||||
(timers/raf
|
(timers/raf
|
||||||
(fn []
|
(fn []
|
||||||
(timers/raf navigate-fn))))
|
(timers/raf navigate-fn))))
|
||||||
(navigate-fn))))
|
(navigate-fn)))))
|
||||||
|
|
||||||
on-delete
|
on-delete
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@ -106,11 +111,14 @@
|
|||||||
|
|
||||||
on-blur
|
on-blur
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
(mf/deps id is-separator?)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [name (str/trim (dom/get-target-val event))]
|
(let [new-name (str/trim (dom/get-target-val event))]
|
||||||
(when-not (str/empty? name)
|
(if (str/empty? new-name)
|
||||||
(st/emit! (dw/rename-page id name)))
|
(when is-separator?
|
||||||
(st/emit! (dw/stop-rename-page-item)))))
|
(st/emit! (dw/delete-page id)))
|
||||||
|
(st/emit! (dw/rename-page id new-name))))
|
||||||
|
(st/emit! (dw/stop-rename-page-item))))
|
||||||
|
|
||||||
on-key-down
|
on-key-down
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@ -166,40 +174,49 @@
|
|||||||
(dom/select-text! edit-input))
|
(dom/select-text! edit-input))
|
||||||
nil)))
|
nil)))
|
||||||
|
|
||||||
|
(let [selected? (and selected? (not is-separator?))]
|
||||||
[:li {:class (stl/css-case
|
[:li {:class (stl/css-case
|
||||||
:page-element true
|
:page-element true
|
||||||
|
:separator is-separator?
|
||||||
:selected selected?
|
:selected selected?
|
||||||
:dnd-over-top (= (:over dprops) :top)
|
:dnd-over-top (= (:over dprops) :top)
|
||||||
:dnd-over-bot (= (:over dprops) :bot))
|
:dnd-over-bot (= (:over dprops) :bot))
|
||||||
:ref dref}
|
:ref dref}
|
||||||
[:div {:class (stl/css-case
|
[:div {:class (stl/css-case
|
||||||
:element-list-body true
|
:element-list-body true
|
||||||
:hover hovering?
|
:separator-body is-separator?
|
||||||
|
:hover (and hovering? (not is-separator?))
|
||||||
:selected selected?)
|
:selected selected?)
|
||||||
:data-testid (dm/str "page-" id)
|
:data-testid (dm/str "page-" id)
|
||||||
:tab-index "0"
|
:tab-index "0"
|
||||||
:on-click on-click
|
:on-click on-click
|
||||||
:on-double-click on-double-click
|
:on-double-click on-double-click
|
||||||
:on-context-menu on-context-menu}
|
:on-context-menu on-context-menu}
|
||||||
[:div {:class (stl/css :page-icon)}
|
(if (and is-separator? (not editing?))
|
||||||
deprecated-icon/document]
|
[:div {:class (stl/css :page-separator)
|
||||||
|
:data-testid "page-separator"}]
|
||||||
(if editing?
|
|
||||||
[:*
|
[:*
|
||||||
|
(when-not is-separator?
|
||||||
|
[:div {:class (stl/css :page-icon)}
|
||||||
|
[:> icon* {:icon-id i/document :size "s"}]])
|
||||||
|
(if editing?
|
||||||
[:input {:class (stl/css :element-name)
|
[:input {:class (stl/css :element-name)
|
||||||
:type "text"
|
:type "text"
|
||||||
:ref input-ref
|
:ref input-ref
|
||||||
:on-blur on-blur
|
:on-blur on-blur
|
||||||
:on-key-down on-key-down
|
:on-key-down on-key-down
|
||||||
:auto-focus true
|
:auto-focus true
|
||||||
:default-value (:name page "")}]]
|
:default-value name}]
|
||||||
[:*
|
[:*
|
||||||
[:span {:class (stl/css :page-name) :title (:name page) :data-testid "page-name"}
|
[:span {:class (stl/css :page-name) :title name :data-testid "page-name"}
|
||||||
(:name page)]
|
name]
|
||||||
[:div {:class (stl/css :page-actions)}
|
[:div {:class (stl/css :page-actions)}
|
||||||
(when (and deletable? (not read-only?))
|
(when (and deletable? (not read-only?))
|
||||||
[:button {:on-click on-delete}
|
[:> icon-button* {:variant "ghost"
|
||||||
deprecated-icon/delete])]])]]))
|
:aria-label (tr "modals.delete-page.title")
|
||||||
|
:on-click on-delete
|
||||||
|
:icon-size "s"
|
||||||
|
:icon i/delete}])]])])]])))
|
||||||
|
|
||||||
;; --- Page Item Wrapper
|
;; --- Page Item Wrapper
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
// Copyright (c) KALEIDOS INC
|
// Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
@use "refactor/common-refactor.scss" as deprecated;
|
@use "refactor/common-refactor.scss" as deprecated;
|
||||||
|
@use "ds/_borders.scss" as *;
|
||||||
|
|
||||||
.sitemap {
|
.sitemap {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -99,8 +100,6 @@
|
|||||||
svg {
|
svg {
|
||||||
@extend %button-icon-small;
|
@extend %button-icon-small;
|
||||||
|
|
||||||
height: deprecated.$s-12;
|
|
||||||
width: deprecated.$s-12;
|
|
||||||
color: transparent;
|
color: transparent;
|
||||||
fill: none;
|
fill: none;
|
||||||
stroke: var(--icon-foreground);
|
stroke: var(--icon-foreground);
|
||||||
@ -109,6 +108,8 @@
|
|||||||
|
|
||||||
.page-actions {
|
.page-actions {
|
||||||
height: deprecated.$s-32;
|
height: deprecated.$s-32;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
@include deprecated.buttonStyle;
|
@include deprecated.buttonStyle;
|
||||||
@ -121,8 +122,6 @@
|
|||||||
svg {
|
svg {
|
||||||
@extend %button-icon-small;
|
@extend %button-icon-small;
|
||||||
|
|
||||||
height: deprecated.$s-12;
|
|
||||||
width: deprecated.$s-12;
|
|
||||||
color: transparent;
|
color: transparent;
|
||||||
fill: none;
|
fill: none;
|
||||||
stroke: var(--icon-foreground);
|
stroke: var(--icon-foreground);
|
||||||
@ -253,6 +252,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.element-list-body.separator-body {
|
||||||
|
height: auto;
|
||||||
|
min-height: var(--sp-xxxl);
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-separator {
|
||||||
|
width: 100%;
|
||||||
|
height: $b-1;
|
||||||
|
margin: var(--sp-s);
|
||||||
|
background-color: var(--color-background-quaternary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-element.separator:hover .element-list-body,
|
||||||
|
.page-element.separator.hover .element-list-body {
|
||||||
|
color: var(--layer-row-foreground-color);
|
||||||
|
background-color: transparent;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
.title-spacing-sitemap {
|
.title-spacing-sitemap {
|
||||||
padding-inline-start: deprecated.$s-8;
|
padding-inline-start: deprecated.$s-8;
|
||||||
margin-block: deprecated.$s-8 deprecated.$s-4;
|
margin-block: deprecated.$s-8 deprecated.$s-4;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user