mirror of
https://github.com/logseq/logseq.git
synced 2026-05-17 09:22:21 +00:00
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:
@@ -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]
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user