diff --git a/src/main/frontend/components/block.cljs b/src/main/frontend/components/block.cljs index 79b24d68c5..d06f2d8dfb 100644 --- a/src/main/frontend/components/block.cljs +++ b/src/main/frontend/components/block.cljs @@ -638,6 +638,34 @@ (declare page-reference) +(defn- heading-value->level + [heading level] + (cond + (and (integer? heading) (<= 1 heading 6)) heading + (true? heading) (min (inc (or level 0)) 6) + :else nil)) + +(defn- block-heading-level + [block level] + (or (when-let [heading-level (:block/heading-level block)] + (when (and (integer? heading-level) + (<= 1 heading-level 6)) + heading-level)) + (heading-value->level (or (pu/lookup block :logseq.property/heading) + (:block.temp/heading block)) + level))) + +(defn- heading-icon-size + [heading-level] + (case heading-level + 1 28 + 2 24 + 3 20 + 4 16 + 5 13 + 6 12 + 14)) + (defn {:tabIndex "0" @@ -745,7 +774,8 @@ (let [own-icon (get page-entity :logseq.property/icon) emoji? (and (map? own-icon) (= (:type own-icon) :emoji))] (when-let [icon (icon-component/get-node-icon-cp page-entity {:color? true - :not-text-or-page? true})] + :not-text-or-page? true + :size icon-size})] [:span {:class (str "icon-emoji-wrap " (when emoji? "as-emoji"))} icon]))) @@ -2015,7 +2045,9 @@ :ignore-children? page-title? :page-title? page-title?}) link? (boolean (:original-block config)) - icon-size (if collapsed? 12 14) + heading-level (when-not collapsed? + (block-heading-level block (:level config))) + icon-size (if collapsed? 12 (heading-icon-size heading-level)) icon (icon-component/get-node-icon-cp block {:size icon-size :color? true :link? link?}) with-icon? (and (some? icon) (or (and (db/page? block) @@ -2156,15 +2188,7 @@ level (:level config) block-ref? (:block-ref? config) block-type (or (keyword (pu/lookup block :logseq.property/ls-type)) :default) - ;; `heading-level` is for backward compatibility, will remove it in later releases - heading-level (:block/heading-level block) - heading (or - (and heading-level - (<= heading-level 6) - heading-level) - (pu/lookup block :logseq.property/heading) - (:block.temp/heading block)) - heading (if (true? heading) (min (inc level) 6) heading) + heading (block-heading-level block level) elem (if heading (keyword (str "h" heading ".block-title-wrap.as-heading" (when block-ref? ".as-inline"))) @@ -2209,7 +2233,9 @@ (and (:page-ref? config) (= 1 (count block-ast-title)) (= "Link" (ffirst block-ast-title))) - (assoc :node-ref-link-only? true))] + (assoc :node-ref-link-only? true) + (integer? heading) + (assoc :parent-heading heading))] (map-inline config' block-ast-title)))))))) (rum/defc block-title-aux @@ -3885,7 +3911,7 @@ (util/mobile?) 0 page-icon -36 :else -30)}) - :data-has-heading (some-> block (pu/lookup :logseq.property/heading)) + :data-has-heading (block-heading-level block level) :on-mouse-enter (fn [e] (block-mouse-over e block *control-show? block-id doc-mode?)) :on-mouse-move (fn [e] diff --git a/src/main/frontend/components/block.css b/src/main/frontend/components/block.css index 25c7c47b93..f7dff314be 100644 --- a/src/main/frontend/components/block.css +++ b/src/main/frontend/components/block.css @@ -59,11 +59,14 @@ .icon-emoji-wrap { position: relative; - top: 0.08em; + top: 0; + display: inline-flex; + align-items: center; + line-height: 1; + vertical-align: middle; padding-left: 1px; &.as-emoji { - top: 0.02em; padding-right: 1px; } } @@ -72,9 +75,18 @@ @apply inline-flex items-center pr-0.5; } + &:has(> .icon-emoji-wrap), + &:has(> .icon-cp-container) { + display: inline-flex; + align-items: center; + vertical-align: baseline; + } + .icon-emoji-wrap em-emoji, .icon-cp-container .ui__icon { - vertical-align: middle; + display: inline-flex; + align-items: center; + line-height: 1; } .block-title-wrap.as-heading { @@ -364,6 +376,10 @@ } } + h3&, h4&, h5&, h6& { + min-height: 24px; + } + &.as-inline { @apply inline; } @@ -559,8 +575,39 @@ .block-main-container { @apply min-h-[24px]; + --ls-heading-control-icon-size: 14px; + + > .block-control-wrap.is-with-icon { + .bullet-container { + width: var(--ls-heading-control-icon-size); + min-width: var(--ls-heading-control-icon-size); + height: var(--ls-heading-control-icon-size); + } + + .icon-cp-container, + .ls-icon-color-wrap, + .ui__icon { + display: inline-flex; + align-items: center; + justify-content: center; + line-height: 1; + } + + .ls-icon-color-wrap em-emoji, + .ui__icon em-emoji { + display: block; + line-height: 1; + } + + .ui__icon.ti svg { + width: var(--ls-heading-control-icon-size); + height: var(--ls-heading-control-icon-size); + } + } &[data-has-heading="1"], &:has(textarea.h1) { + --ls-heading-control-icon-size: 28px; + > .block-control-wrap { @apply relative top-4; } @@ -573,6 +620,8 @@ } &[data-has-heading="2"], &:has(textarea.h2) { + --ls-heading-control-icon-size: 24px; + > .block-control-wrap { @apply relative top-2.5; } @@ -585,9 +634,8 @@ } &[data-has-heading="3"], &:has(textarea.h3) { - > .block-control-wrap { - @apply relative top-[2px]; - } + --ls-heading-control-icon-size: 20px; + align-items: center; .block-content-or-editor-wrap { .positioned-properties { @@ -596,16 +644,19 @@ } } - &[data-has-heading="5"] { - > .block-control-wrap { - @apply relative -top-[1px]; - } + &[data-has-heading="4"], &:has(textarea.h4) { + --ls-heading-control-icon-size: 16px; + align-items: center; + } + + &[data-has-heading="5"], &:has(textarea.h5) { + --ls-heading-control-icon-size: 13px; + align-items: center; } &[data-has-heading="6"], &:has(textarea.h6) { - h6.as-heading, textarea.h6 { - @apply pt-1; - } + --ls-heading-control-icon-size: 12px; + align-items: center; } } @@ -872,6 +923,8 @@ .bullet { @apply rounded-full opacity-80; + display: block; + flex: none; width: 0.4em; height: 0.4em; diff --git a/src/main/frontend/components/container.cljs b/src/main/frontend/components/container.cljs index 47de27a509..ee6d3cbf54 100644 --- a/src/main/frontend/components/container.cljs +++ b/src/main/frontend/components/container.cljs @@ -333,10 +333,22 @@ (show! (cp-content/block-ref-custom-context-menu-content block block-ref)) (state/set-state! :block-ref/context nil)) - ;; block selection + ;; block selection (and (state/selection?) (not (d/has-class? target "bullet"))) - (show! (cp-content/custom-context-menu-content) - {:id :blocks-selection-context-menu}) + (let [selection-blocks (state/get-selection-blocks)] + (if (= 1 (count selection-blocks)) + (let [selected-block (first selection-blocks) + property-default-value? (when selected-block + (= "true" (d/attr selected-block "data-is-property-default-value")))] + (when-let [sel-block-id (some-> selected-block + (.getAttribute "blockid") + (parse-uuid))] + (p/do! + (db-async/ - (ui/menu-background-color #(property-handler/set-block-property! block-id - :logseq.property/background-color - %) - #(property-handler/remove-block-property! block-id - :logseq.property/background-color)) + (let [block (db/entity [:block/uuid block-id]) + [set-icon-sub-menu-open? set-icon-sub-menu-open] (rum/use-state false) + [heading set-heading!] (rum/use-state (or (pu/lookup block :logseq.property/heading) false)) + [current-color set-current-color!] (rum/use-state (pu/lookup block :logseq.property/background-color))] + (when block + [:<> + (ui/menu-background-color current-color + (fn [color] + (set-current-color! color) + (property-handler/set-block-property! block-id + :logseq.property/background-color + color)) + (fn [] + (set-current-color! nil) + (property-handler/remove-block-property! block-id + :logseq.property/background-color))) - (ui/menu-heading heading - #(editor-handler/set-heading! block-id %) - #(editor-handler/set-heading! block-id true) - #(editor-handler/remove-heading! block-id)) + (ui/menu-heading heading + (fn [i] + (set-heading! i) + (editor-handler/set-heading! block-id i)) + (fn [] + (set-heading! true) + (editor-handler/set-heading! block-id true)) + (fn [] + (set-heading! false) + (editor-handler/remove-heading! block-id))) (shui/dropdown-menu-separator) @@ -352,7 +364,7 @@ {:created-at (tc/from-long (* (:created-at version) 1000)) :content (:value version)}) versions))))))} - "(Dev) Show block content history")))])])))) + "(Dev) Show block content history")))])]))) (rum/defc block-ref-custom-context-menu-content [block block-ref-id] diff --git a/src/main/frontend/ui.cljs b/src/main/frontend/ui.cljs index 3ac9c53037..52d9168dfa 100644 --- a/src/main/frontend/ui.cljs +++ b/src/main/frontend/ui.cljs @@ -93,19 +93,26 @@ (some #{color} built-in-colors)) (rum/defc menu-background-color - [add-bgcolor-fn rm-bgcolor-fn] - [:div.flex.flex-row.justify-between.py-1.px-2.items-center - [:div.flex.flex-row.justify-between.flex-1.mx-2.mt-2 - (for [color built-in-colors] - [:a - {:key (str "key-" color) - :title (t (keyword "color" color)) - :on-click #(add-bgcolor-fn color)} - [:div.heading-bg {:style {:background-color (str "var(--color-" color "-500)")}}]]) - [:a - {:title (t :ui/remove-background) - :on-click rm-bgcolor-fn} - [:div.heading-bg.remove "-"]]]]) + ([add-bgcolor-fn rm-bgcolor-fn] + (menu-background-color ::unknown add-bgcolor-fn rm-bgcolor-fn)) + ([current-color add-bgcolor-fn rm-bgcolor-fn] + (let [known-color? (not= current-color ::unknown) + active-ring "0 0 0 2px var(--lx-gray-12, var(--ls-primary-text-color))"] + [:div.flex.flex-row.justify-between.py-1.px-2.items-center + [:div.flex.flex-row.justify-between.flex-1.mx-2.mt-2 + (for [color built-in-colors] + [:a + {:key (str "key-" color) + :title (t (keyword "color" color)) + :on-click #(add-bgcolor-fn color)} + [:div.heading-bg {:style {:background-color (str "var(--color-" color "-500)") + :box-shadow (when (and known-color? (= current-color color)) + active-ring)}}]]) + [:a + {:title (t :ui/remove-background) + :on-click rm-bgcolor-fn} + [:div.heading-bg.remove {:style {:box-shadow (when (and known-color? (nil? current-color)) + active-ring)}} "-"]]]]))) (rum/defc ls-textarea < rum/reactive @@ -929,31 +936,28 @@ (for [i (range 1 7)] (rum/with-key (button "" - :disabled? (and (some? heading) (= heading i)) :icon (str "h-" i) :title (t :editor/heading i) - :class "to-heading-button" + :class (str "to-heading-button" (when (= heading i) " is-active")) :on-click #(add-heading-fn i) - :intent "link" + :intent (when-not (= heading i) "link") :small? true) (str "key-h-" i))) (button "" :icon "h-auto" - :disabled? (and (some? heading) (true? heading)) - :class "to-heading-button" + :class (str "to-heading-button" (when (true? heading) " is-active")) :title (t :editor/auto-heading) :on-click auto-heading-fn - :intent "link" + :intent (when-not (true? heading) "link") :small? true) (button "" :icon "heading-off" - :disabled? (and (some? heading) (not heading)) - :class "to-heading-button" + :class (str "to-heading-button" (when (false? heading) " is-active")) :title (t :editor/remove-heading) :on-click rm-heading-fn - :intent "link" + :intent (when-not (false? heading) "link") :small? true)]])) (rum/defc tooltip