fix: heading icon alignment and menu active state

1. Derive the effective heading level consistently for auto headings, and reuse it for block icons, page-ref icons, and heading layout attributes.
2. Align heading bullets and page-ref icons so h3-h6 and auto heading changes no longer shift vertically.
3. Show the active heading and background color in the single-block context menu.
This commit is contained in:
megayu
2026-05-11 23:26:46 +08:00
committed by GitHub
parent f42da95204
commit 755840c474
5 changed files with 174 additions and 67 deletions

View File

@@ -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 <open-page-ref
[config page-entity e page-name contents-page?]
(when (not (util/right-click? e))
@@ -695,7 +723,8 @@
untitled? (when page-name
(or (model/untitled-page? (:block/title page-entity))
(and (ldb/page? page-entity) (string/blank? (:block/title page-entity)))))
show-icon? (:show-icon? config)]
show-icon? (:show-icon? config)
icon-size (heading-icon-size (:parent-heading config))]
[:a.relative
(cond->
{: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]

View File

@@ -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;

View File

@@ -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/<get-block (state/get-current-repo) sel-block-id {:children? false})
(show! (cp-content/block-context-menu-content
target sel-block-id property-default-value?)))))
(show! (cp-content/custom-context-menu-content)
{:id :blocks-selection-context-menu})))
;; block bullet
(and block-id (parse-uuid block-id))

View File

@@ -153,21 +153,33 @@
(rum/defc ^:large-vars/cleanup-todo block-context-menu-content
[_target block-id property-default-value?]
(let [[set-icon-sub-menu-open? set-icon-sub-menu-open] (rum/use-state false)]
(when-let [block (db/entity [:block/uuid block-id])]
(let [heading (or (pu/lookup block :logseq.property/heading)
false)]
[:<>
(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]

View File

@@ -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