From 7d65070f59bf151f7366d4dfee02cd6f7c0a8ae8 Mon Sep 17 00:00:00 2001 From: CODEX Date: Sat, 20 Jun 2026 19:40:32 +0300 Subject: [PATCH] Refine BIM comment panel interactions --- frontend/dcViewer.css | 20 ++++++++++++---- frontend/dcViewer.js | 54 +++++++++++++++++++++++++++++++++++-------- frontend/index.html | 4 ++-- 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/frontend/dcViewer.css b/frontend/dcViewer.css index cabe8f2..4d0f604 100644 --- a/frontend/dcViewer.css +++ b/frontend/dcViewer.css @@ -612,14 +612,24 @@ header { .comment-list-item:hover, .comment-list-item.active { - border-color: color-mix(in srgb, var(--comment-target-active) 55%, var(--modal-border)); - background: color-mix(in srgb, var(--comment-target-active) 16%, var(--modal-focus)); + border-color: transparent; + background: var(--toolbar-bg-active, var(--comment-target-active)); + color: var(--toolbar-bg-active-contrast, #15170f); } .comment-list-item:active { transform: translateY(1px); } +.comment-list-item:hover .comment-list-title, +.comment-list-item:hover .comment-list-body, +.comment-list-item:hover .comment-list-meta, +.comment-list-item.active .comment-list-title, +.comment-list-item.active .comment-list-body, +.comment-list-item.active .comment-list-meta { + color: inherit; +} + .comment-list-title { min-width: 0; overflow: hidden; @@ -726,7 +736,7 @@ header { .nodedc-dropdown-surface { position: fixed; - z-index: 30041; + z-index: 50000; padding: 0.65rem; border: 0; border-radius: 1.25rem; @@ -1225,7 +1235,7 @@ header { } .nodedc-dropdown-surface.nodedc-select__menu { - z-index: 30060; + z-index: 50010; display: grid; gap: 2px; max-height: 232px; @@ -1843,7 +1853,7 @@ header { } .bim-subitem-menu { - z-index: 30070; + z-index: 50020; display: grid; gap: 0.18rem; min-width: 17.25rem; diff --git a/frontend/dcViewer.js b/frontend/dcViewer.js index 595f24f..8c82ab5 100644 --- a/frontend/dcViewer.js +++ b/frontend/dcViewer.js @@ -554,7 +554,7 @@ const setCommentModalError = (message = "") => { const bringFloatingWindowToFront = (id) => { if (!id) return; floatingWindowOrder = [...floatingWindowOrder.filter((item) => item !== id), id]; - const zBase = 21000; + const zBase = 30080; floatingWindowOrder.forEach((item, index) => { const element = floatingWindowElements.get(item); if (element) element.style.zIndex = `${zBase + index * 10}`; @@ -566,7 +566,7 @@ const registerFloatingWindowElement = (id, element) => { floatingWindowElements.set(id, element); if (!floatingWindowOrder.includes(id)) floatingWindowOrder.push(id); element.addEventListener("pointerdown", (event) => { - if (event.button !== 0) return; + if (event.pointerType === "mouse" && event.button !== 0) return; bringFloatingWindowToFront(id); }, true); bringFloatingWindowToFront(id); @@ -666,6 +666,14 @@ const getCommentDisplayBody = (comment) => { return lastMessage?.body || ""; }; +const syncCommentListActiveState = () => { + if (!commentsList) return; + commentsList.querySelectorAll(".comment-list-item").forEach((item) => { + const commentId = item.dataset.commentId; + item.classList.toggle("active", activeCommentId === commentId || hoverCommentId === commentId); + }); +}; + const renderCommentsPanel = () => { if (!commentsList) return; commentsList.replaceChildren(); @@ -697,12 +705,12 @@ const renderCommentsPanel = () => { item.append(title, body, meta); item.addEventListener("mouseenter", () => { hoverCommentId = comment.id; - renderCommentsPanel(); + syncCommentListActiveState(); renderCommentTargets(); }); item.addEventListener("mouseleave", () => { if (hoverCommentId === comment.id) hoverCommentId = null; - renderCommentsPanel(); + syncCommentListActiveState(); renderCommentTargets(); }); item.addEventListener("click", () => openCommentModalForComment(comment.id)); @@ -770,6 +778,17 @@ const stopCommentTargetLoop = () => { } }; +const syncCommentTargetActiveState = () => { + if (!commentTargetsLayer) return; + commentTargetsLayer.querySelectorAll(".comment-target").forEach((targetEl) => { + const commentId = targetEl.dataset.commentId; + targetEl.classList.toggle( + "active", + commentId === "__draft_comment__" || activeCommentId === commentId || hoverCommentId === commentId + ); + }); +}; + const renderCommentTargets = () => { if (!commentTargetsLayer) return; commentTargetsLayer.replaceChildren(); @@ -790,13 +809,13 @@ const renderCommentTargets = () => { btn.innerHTML = COMMENT_TARGET_ICON; btn.addEventListener("mouseenter", () => { if (!comment.draft) hoverCommentId = comment.id; - renderCommentTargets(); - renderCommentsPanel(); + syncCommentTargetActiveState(); + syncCommentListActiveState(); }); btn.addEventListener("mouseleave", () => { if (hoverCommentId === comment.id) hoverCommentId = null; - renderCommentTargets(); - renderCommentsPanel(); + syncCommentTargetActiveState(); + syncCommentListActiveState(); }); btn.addEventListener("click", (event) => { event.stopPropagation(); @@ -1227,7 +1246,7 @@ const openCommentModalForTarget = () => { renderCommentThread(null); commentModalBackdrop?.classList.remove("hidden"); commentModal.classList.remove("hidden"); - bringFloatingWindowToFront("comments"); + bringFloatingWindowToFront("commentModal"); updateCommentsVisibility(); commentTitleInput?.focus(); }; @@ -1258,6 +1277,11 @@ const openCommentModalForComment = (commentId) => { renderCommentThread(comment); commentModalBackdrop?.classList.remove("hidden"); commentModal.classList.remove("hidden"); + commentsModeActive = true; + commentsCollapsed = false; + bringFloatingWindowToFront("commentModal"); + updateCommentsVisibility(); + commentTitleInput?.focus(); renderCommentsPanel(); renderCommentTargets(); }; @@ -1968,12 +1992,14 @@ const closeTemplatesPanel = () => { const openSettingsPanel = () => { closeTemplatesPanel(); settingsMenu?.show(); + bringFloatingWindowToFront("settings"); setToolbarButtonActive(settingsButton, true); }; const openTemplatesPanel = () => { closeSettingsPanel(); templatesMenu?.show(); + bringFloatingWindowToFront("templates"); setToolbarButtonActive(templatesButton, true); }; @@ -5164,6 +5190,7 @@ const loadProjectSnapshot = async (project) => { fetchProjects: () => loadProjectsList(), openProject: (projectId) => loadProjectFromServer(projectId), onShow: () => { + bringFloatingWindowToFront("templates"); setToolbarButtonActive(templatesButton, true); setToolbarButtonActive(settingsButton, false); }, @@ -5197,6 +5224,7 @@ const loadProjectSnapshot = async (project) => { focusCanvasAndControls(); }, onShow: () => { + bringFloatingWindowToFront("settings"); setToolbarButtonActive(settingsButton, true); setToolbarButtonActive(templatesButton, false); closeTemplatesPanel(); @@ -5269,9 +5297,15 @@ const loadProjectSnapshot = async (project) => { zoomSpeedControl.replaceChildren(zoomSpeedSlider); } inspectorCollapseButton?.addEventListener("click", () => setInspectorCollapsed(true)); - inspectorRestoreButton?.addEventListener("click", () => setInspectorCollapsed(false)); + inspectorRestoreButton?.addEventListener("click", () => { + setInspectorCollapsed(false); + bringFloatingWindowToFront("inspector"); + }); registerFloatingWindowElement("inspector", sidePanelEl); registerFloatingWindowElement("comments", commentsPanel); + registerFloatingWindowElement("settings", settingsPanel); + registerFloatingWindowElement("templates", templatesPanel); + registerFloatingWindowElement("commentModal", commentModal); setupDraggableFixedWindow(commentsPanel, commentsPanelHeader); setupDraggableFixedWindow(commentModal, commentModalHeader); commentsCollapseButton?.addEventListener("click", () => setCommentsCollapsed(true)); diff --git a/frontend/index.html b/frontend/index.html index 100b5f6..9bca116 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -134,7 +134,7 @@ - +
@@ -570,6 +570,6 @@ - +