mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-08 06:30:04 +00:00
feat: implement NodeLibrarySidebarTabV2 with Reka UI components (#8548)
## Summary Implement a redesigned Node Library sidebar using Reka UI components with virtualized tree rendering and improved UX. ## Changes - **What**: - Add three-tab structure (Essential, All, Custom) using Reka UI Tabs - Implement TreeExplorerV2 with virtualized tree using TreeRoot/TreeVirtualizer for performance - Add node hover preview with teleport to show NodePreview component - Implement context menu for toggling favorites on nodes - Add search functionality that auto-expands matching folders - Create panel components: EssentialNodesPanel, AllNodesPanel, CustomNodesPanel - Add 'Open Manager' button in CustomNodesPanel - Use custom icons: comfy--node for nodes, ph--folder-fill for folders - New node preview component: `NodePreviewCard` - Api node folder icon - Node drag preview - **Feature Flag**: Enabled via URL parameter `?nodeRedesign=true` ## Review Focus - TreeExplorerV2.vue uses `[...expandedKeys]` to prevent internal mutation by Reka UI TreeRoot - Context menu injection key is exported from TreeExplorerV2Node.vue and imported by TreeExplorerV2.vue - Hover preview uses teleport to `#node-library-node-preview-container-v2` ## Screenshots (if applicable) | Feature | Screenshot | |---|---| | All nodes tab |<img width="323" height="761" alt="image" src="https://github.com/user-attachments/assets/1976222b-83dc-4a1b-838a-2d49aedea3b8" />| | Custom nodes tab | <img width="308" height="748" alt="image" src="https://github.com/user-attachments/assets/2c23bffb-bdaa-4c6c-8cac-7610fb7f3fb7" />| |Api nodes icon | <img width="299" height="523" alt="image" src="https://github.com/user-attachments/assets/e9ca05b0-1143-44cf-b227-6462173c7cd0" />| | node preview|<img width="499" height="544" alt="image" src="https://github.com/user-attachments/assets/8961a7b4-77ae-4e57-99cf-62d9e4e17088" />| | node drag preview | <img width="434" height="289" alt="image" src="https://github.com/user-attachments/assets/b5838c90-65d4-4bee-b2b3-c41b57870da8" />| Test by adding `?nodeRedesign=true` to the URL ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8548-WIP-feat-implement-NodeLibrarySidebarTabV2-with-Reka-UI-components-2fb6d73d36508134b7e0f75a2c9b976a) by [Unito](https://www.unito.io) --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: GitHub Action <action@github.com> Co-authored-by: bymyself <cbyrne@comfy.org>
This commit is contained in:
66
src/components/common/TextTickerMultiLine.vue
Normal file
66
src/components/common/TextTickerMultiLine.vue
Normal file
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- Hidden single-line measurement element for overflow detection -->
|
||||
<div
|
||||
ref="measureRef"
|
||||
class="invisible absolute inset-x-0 top-0 overflow-hidden whitespace-nowrap pointer-events-none"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<MarqueeLine v-if="!secondLine">
|
||||
<slot />
|
||||
</MarqueeLine>
|
||||
|
||||
<div v-else class="flex flex-col w-full">
|
||||
<MarqueeLine>{{ firstLine }}</MarqueeLine>
|
||||
<MarqueeLine>{{ secondLine }}</MarqueeLine>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useMutationObserver, useResizeObserver } from '@vueuse/core'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import MarqueeLine from './MarqueeLine.vue'
|
||||
import { splitTextAtWordBoundary } from '@/utils/textTickerUtils'
|
||||
|
||||
const measureRef = ref<HTMLElement | null>(null)
|
||||
const firstLine = ref('')
|
||||
const secondLine = ref('')
|
||||
|
||||
function splitLines() {
|
||||
const el = measureRef.value
|
||||
const text = el?.textContent?.trim()
|
||||
if (!el || !text) {
|
||||
firstLine.value = ''
|
||||
secondLine.value = ''
|
||||
return
|
||||
}
|
||||
|
||||
const containerWidth = el.clientWidth
|
||||
const textWidth = el.scrollWidth
|
||||
|
||||
if (textWidth <= containerWidth) {
|
||||
firstLine.value = text
|
||||
secondLine.value = ''
|
||||
return
|
||||
}
|
||||
|
||||
const [first, second] = splitTextAtWordBoundary(
|
||||
text,
|
||||
containerWidth / textWidth
|
||||
)
|
||||
firstLine.value = first
|
||||
secondLine.value = second
|
||||
}
|
||||
|
||||
useResizeObserver(measureRef, splitLines)
|
||||
useMutationObserver(measureRef, splitLines, {
|
||||
childList: true,
|
||||
characterData: true,
|
||||
subtree: true
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user