feat: add current page badge functionality

This commit is contained in:
Mega Yu
2026-02-11 17:01:12 +08:00
parent 8d1db4f01d
commit 6b1f4f4ac4
4 changed files with 80 additions and 7 deletions

View File

@@ -8,3 +8,11 @@
.ls-dialog-cmdk {
@apply p-0 w-auto !max-w-fit overflow-hidden;
}
.cp__cmdk-current-page-badge {
@apply inline-flex items-center rounded-full border text-xs font-medium leading-none;
padding: 2px 8px;
color: var(--lx-gray-11, var(--ls-secondary-text-color, rgba(0, 0, 0, 0.7)));
background: var(--lx-gray-04, var(--ls-tertiary-background-color, rgba(0, 0, 0, 0.08)));
border-color: var(--lx-gray-06, var(--ls-border-color, rgba(0, 0, 0, 0.12)));
}

View File

@@ -277,7 +277,7 @@
new-result)))]))
(defn page-item
[repo page input]
[repo page current-page input]
(let [entity (-> (or (db/entity [:block/uuid (:block/uuid page)]) page)
(update :block/tags (fn [tags]
(map (fn [tag]
@@ -286,6 +286,12 @@
tag)) tags))))
source-page (or (model/get-alias-source-page repo (:db/id entity))
(:alias page))
current-page-id (:block/uuid current-page)
result-page-id (or (:block/uuid source-page)
(:block/uuid entity)
(:block/uuid page))
current-page? (and current-page-id
(= current-page-id result-page-id))
icon (icon-component/get-node-icon-cp entity {:ignore-current-icon? true})
title (block-handler/block-unique-title entity
:alias (:block/title source-page)
@@ -300,6 +306,8 @@
(block/breadcrumb {:disable-preview? true
:search? true} repo (:block/uuid page)
{:disabled? true}))
:result-type :page
:current-page? current-page?
:alias (:alias page)
:source-block (or source-page page))))
@@ -314,6 +322,7 @@
:header (block/breadcrumb {:disable-preview? true
:search? true} repo id
{:disabled? true})
:result-type :block
:current-page? (when-let [page-id (:block/page block)]
(= page-id (:block/uuid current-page)))
:source-block block}))
@@ -335,7 +344,7 @@
blocks (remove nil? blocks)
items (keep (fn [block]
(if (:page? block)
(page-item repo block @!input)
(page-item repo block current-page @!input)
(block-item repo block current-page @!input))) blocks)]
(if (= group :current-page)
(let [items-on-current-page (filter :current-page? items)]
@@ -346,6 +355,8 @@
(let [!input (::input state)
!results (::results state)
repo (state/get-current-repo)
current-page (when-let [id (page-util/get-current-page-id)]
(db/entity id))
opts (cmdk-state/cmdk-block-search-options
{:filter-group :code
:dev? config/dev?})]
@@ -353,7 +364,7 @@
(p/let [blocks (search/block-search repo @!input opts)
blocks (remove nil? blocks)
items (map (fn [block]
(block-item repo block nil @!input))
(block-item repo block current-page @!input))
blocks)]
(swap! !results update group merge {:status :success :items items}))))
@@ -428,6 +439,7 @@
:icon-theme :gray
:text (highlight-content-query (:block/title block) @!input)
:header (block/breadcrumb {:search? true} repo id {:disabled? true})
:result-type (if (:page? block) :page :block)
:current-page? true
:source-block block})) blocks)]
(swap! !results update :current-page merge {:status :success :items items})))

View File

@@ -50,13 +50,31 @@
segs))
[:span normal-text])))))
(def current-page-badge-label "Current Page")
(defn current-page-badge-placement
[{:keys [current-page? result-type]}]
(when current-page?
(case result-type
:page {:text-badge current-page-badge-label}
:block {:header-badge current-page-badge-label}
nil)))
(defn current-page-badge-node
[label]
(when-not (string/blank? label)
[:span.cp__cmdk-current-page-badge label]))
(rum/defc root [{:keys [icon icon-theme query text info shortcut value-label value
title highlighted on-highlight on-highlight-dep header on-click
hoverable compact rounded on-mouse-enter component-opts source-block] :as _props
hoverable compact rounded on-mouse-enter component-opts source-block] :as props
:or {hoverable true rounded true}}
{:keys [app-config]}]
(let [ref (hooks/create-ref)
highlight-query (partial highlight-query* app-config query)
badge-placement (current-page-badge-placement props)
text-badge (current-page-badge-node (:text-badge badge-placement))
header-badge (current-page-badge-node (:header-badge badge-placement))
[hover? set-hover?] (rum/use-state false)
mouse-highlighted? (and highlighted hoverable hover?)
keyboard-highlighted? (and highlighted (not mouse-highlighted?))
@@ -99,9 +117,10 @@
component-opts)
;; header
(when header
[:div.text-xs.pl-8.font-light {:class "-mt-1"
[:div.text-xs.pl-8.font-light.flex.items-center.gap-2.flex-wrap {:class "-mt-1"
:style {:color "var(--lx-gray-11)"}}
(highlight-query header)])
(highlight-query header)
header-badge])
;; main row
[:div.flex.items-start.gap-3
[:div.w-5.h-5.rounded.flex.items-center.justify-center
@@ -119,10 +138,11 @@
[:div.flex.flex-1.flex-col
(when title
[:div.text-sm.pb-2.font-bold.text-gray-11 (highlight-query title)])
[:div {:class "text-sm font-medium text-gray-12"}
[:div {:class "text-sm font-medium text-gray-12 flex items-center gap-2 flex-wrap"}
(block-handler/block-title-with-icon source-block
(highlight-query text)
icon-component/icon)
text-badge
(when info
[:span.text-xs.text-gray-11 " — " (highlight-query info)])]]
(when (or value-label value)

View File

@@ -0,0 +1,33 @@
(ns frontend.components.cmdk.list-item-test
(:require [cljs.test :refer [deftest is testing]]
[frontend.components.cmdk.list-item :as list-item]))
(deftest current-page-badge-placement-test
(testing "page result in current page gets text badge"
(is (= {:text-badge "Current Page"}
(list-item/current-page-badge-placement
{:current-page? true
:result-type :page}))))
(testing "block result in current page gets header badge"
(is (= {:header-badge "Current Page"}
(list-item/current-page-badge-placement
{:current-page? true
:result-type :block}))))
(testing "non current-page results do not get badge"
(is (nil? (list-item/current-page-badge-placement
{:current-page? false
:result-type :page})))
(is (nil? (list-item/current-page-badge-placement
{:current-page? false
:result-type :block})))
(is (nil? (list-item/current-page-badge-placement
{:current-page? true
:result-type :unknown})))))
(deftest current-page-badge-node-test
(testing "badge node renders expected class and label"
(is (= [:span.cp__cmdk-current-page-badge "Current Page"]
(list-item/current-page-badge-node "Current Page"))))
(testing "blank labels do not render badge node"
(is (nil? (list-item/current-page-badge-node "")))
(is (nil? (list-item/current-page-badge-node nil)))))