From 138d58be613db2a65daa5e0462c74c24ccea28da Mon Sep 17 00:00:00 2001 From: franmagn Date: Wed, 22 Oct 2025 11:20:58 +0200 Subject: [PATCH] style(#4): :art: some small UI changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - made it possible to click everywhere on the single annotation panel to open it, and not only on the toggle triangle - added a small pencil icon to indicate the possibility to edit the title text - switched “camera coordinates” with “saved point coordinates” in the annotation panel - made it that the coordinates are listed below the “type of coordinate” title, and are on different lines --- src/AnnotationControl/annotationPanel.css | 15 ++++++ src/AnnotationControl/annotationPanel.js | 66 ++++++++++++++++++++++- 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/src/AnnotationControl/annotationPanel.css b/src/AnnotationControl/annotationPanel.css index f8bebc8..1c95c7b 100644 --- a/src/AnnotationControl/annotationPanel.css +++ b/src/AnnotationControl/annotationPanel.css @@ -218,6 +218,21 @@ img.button-icon[src$="/annotation.svg"]{ .annotation-header .annotation-label { margin-right: 8px; } + +/* tiny pencil hint showing that the title is editable via double-click */ +.annotation-header .annotation-label .annotation-edit-hint { + margin-left: 8px; + font-size: 0.85em; + color: rgba(223,230,233,0.72); + opacity: 0.9; + cursor: default; + user-select: none; + vertical-align: middle; + margin-top: -1px; +} +.annotation-header .annotation-label:hover .annotation-edit-hint { + color: rgba(255,255,255,0.95); +} .annotation-header .controls { margin-left: auto; display: flex; diff --git a/src/AnnotationControl/annotationPanel.js b/src/AnnotationControl/annotationPanel.js index 5c4a9f9..7ead99b 100644 --- a/src/AnnotationControl/annotationPanel.js +++ b/src/AnnotationControl/annotationPanel.js @@ -244,6 +244,14 @@ export function initAnnotationsPanel(viewer) { if (uuid) startInlineEditForUUID(uuid) }) + // Small edit hint icon to indicate double-click to edit + const editHint = document.createElement('span') + editHint.className = 'annotation-edit-hint' + editHint.title = 'Double-click to edit title' + editHint.textContent = '🖉' + // keep the hint non-interactive (don't steal pointer events) + label.appendChild(editHint) + // triangular toggle (collapsed/open) const toggle = document.createElement('span') toggle.className = 'toggle-triangle' @@ -363,6 +371,31 @@ export function initAnnotationsPanel(viewer) { header.appendChild(controls) row.appendChild(header) + // Allow clicking anywhere on the header to toggle the details, but + // ignore clicks that originate from interactive controls (jump/delete) + // so those buttons keep their original behavior. + try { + header.addEventListener('click', (ev) => { + try { + // If the click was inside the controls area (jump/delete), do nothing + if (ev.target && ev.target.closest && ev.target.closest('.controls')) { + return + } + + // If the click was on an interactive element (button, input, textarea, a), ignore + const interactive = ['BUTTON', 'INPUT', 'TEXTAREA', 'A', 'SELECT', 'LABEL'] + if (ev.target && ev.target.tagName && interactive.indexOf(ev.target.tagName) >= 0) { + return + } + + // Otherwise toggle the row + row.classList.toggle('open') + } catch (e) { + // fail silently + } + }) + } catch (e) {} + // Wire toggle to show/hide details try { toggle.addEventListener('click', (ev) => { @@ -419,11 +452,14 @@ export function initAnnotationsPanel(viewer) { const PLACEHOLDER_POS = [589748.27, 231444.54, 753.675] if (pointPos && approxEqual(pointPos, PLACEHOLDER_POS)) pointPos = null + // Format the camera and point positions for display if (cam || pointPos) { const info = document.createElement('div') info.className = 'annotation-info' const fmt = (v) => (v ? v.map((c) => Number(c).toFixed(3)).join(', ') : '—') - info.innerHTML = `Camera coordinates: ${fmt(cam)}

Saved Point coordinates: ${fmt(pointPos)}` + const fmtPoint = fmt(pointPos) ? String(fmt(pointPos)).replace(/,\s*/g, ',
') : '—' + const fmtCam = fmt(cam) ? String(fmt(cam)).replace(/,\s*/g, ',
') : '—' + info.innerHTML = `Saved Point coordinates:
${fmtPoint}

Camera coordinates:
${fmtCam}` body.appendChild(info) // Enable or disable jump button depending on whether we have a saved point position @@ -451,7 +487,23 @@ export function initAnnotationsPanel(viewer) { if (!uuid) return const labelEl = targetContainer.querySelector(`.annotation-label[data-uuid="${uuid}"]`) if (!labelEl) return - const oldText = labelEl.textContent || '' + // Compute the visible title text without the edit-hint glyph. + // The label contains a text node (the title) and a child .annotation-edit-hint span. + let oldText = '' + try { + for (const node of Array.from(labelEl.childNodes)) { + if (node.nodeType === Node.TEXT_NODE) { + oldText += node.nodeValue || '' + } + } + oldText = (oldText || '').trim() + } catch (e) { + oldText = labelEl.textContent || '' + } + // Capture existing hint so we can re-attach it after editing + const existingHint = labelEl.querySelector && labelEl.querySelector('.annotation-edit-hint') + const existingHintText = existingHint ? existingHint.textContent : null + const existingHintTitle = existingHint ? existingHint.title : null const input = document.createElement('input') input.type = 'text' input.value = oldText @@ -471,6 +523,16 @@ export function initAnnotationsPanel(viewer) { ev.stopPropagation() startInlineEditForUUID(uuid) }) + // Re-attach the edit hint so the hint persists after editing + try { + const hint = document.createElement('span') + hint.className = 'annotation-edit-hint' + if (existingHintTitle) hint.title = existingHintTitle + hint.textContent = existingHintText != null ? existingHintText : '✎' + newLabel.appendChild(hint) + } catch (e) { + // ignore hint restoration errors + } try { if (input.isConnected) {