diff --git a/index.html b/index.html index 5a61830..c61915f 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ - Folder Bookmark Tray + Trailhead Path Bookmarker
diff --git a/package.json b/package.json index 71a86f9..a9cb65b 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ }, "build": { "appId": "com.dbeuttel.folder-bookmark-tray", - "productName": "Trailhead", + "productName": "Trailhead Path Bookmarker", "files": [ "electron/**/*", "dist/**/*", diff --git a/src/components/Popup.jsx b/src/components/Popup.jsx index a3d4b99..dbed37b 100644 --- a/src/components/Popup.jsx +++ b/src/components/Popup.jsx @@ -2,6 +2,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import Column from './Column.jsx'; import TabBar from './TabBar.jsx'; import ConfirmDialog from './ConfirmDialog.jsx'; +import iconUrl from '../../assets/tray-icon.png'; const COLUMN_WIDTH = 216; // Padding budget so the popup doesn't clip the tab strip: popup-inner has @@ -41,11 +42,14 @@ export default function Popup({ const heightDebounceRef = useRef(null); const settingsRef = useRef(null); const tabStripRef = useRef(null); + const brandRef = useRef(null); + const actionsRef = useRef(null); const [creatingColumn, setCreatingColumn] = useState(false); const [draftColumnName, setDraftColumnName] = useState(''); const [settingsOpen, setSettingsOpen] = useState(false); const [confirmRequest, setConfirmRequest] = useState(null); const [tabStripScrollWidth, setTabStripScrollWidth] = useState(0); + const [headerMinWidth, setHeaderMinWidth] = useState(0); const requestConfirm = useCallback((opts) => { setConfirmRequest(opts); @@ -86,6 +90,34 @@ export default function Popup({ }; }, []); + // Measure the popup header's intrinsic width so the brand never gets + // ellipsized. The h1 has overflow:hidden + text-overflow:ellipsis to keep + // it from forcing the popup wider than its content; we ask for that width + // explicitly through scrollWidth (which reports the full text width even + // when the element is clipped). + useEffect(() => { + if (!brandRef.current || !actionsRef.current) return undefined; + const update = () => { + const brand = brandRef.current; + const actions = actionsRef.current; + if (!brand || !actions) return; + const iconEl = brand.querySelector('img'); + const titleEl = brand.querySelector('h1'); + const iconW = iconEl ? iconEl.offsetWidth : 0; + const titleW = titleEl ? titleEl.scrollWidth : 0; + const brandW = iconW + (titleW > 0 ? 8 + titleW : 0); + const actionsW = actions.scrollWidth; + // 28px = popup-inner horizontal padding (14 each side); 8px = gap + // between brand and actions inside popup-header. + setHeaderMinWidth(brandW + 8 + actionsW + 28); + }; + update(); + const ro = new ResizeObserver(update); + ro.observe(brandRef.current); + ro.observe(actionsRef.current); + return () => ro.disconnect(); + }, []); + // Watch the tab strip's scrollWidth so renames or new tabs widen the popup. // ResizeObserver picks up both layout changes (window width changes) and // content changes (a tab rename growing the strip). @@ -112,8 +144,8 @@ export default function Popup({ useEffect(() => { const colsWidth = Math.max(1, visibleColumns.length || 1) * COLUMN_WIDTH; const tabsWidth = tabStripScrollWidth > 0 ? tabStripScrollWidth + TAB_STRIP_PADDING : 0; - window.bookmarks.setPopupWidth(Math.max(colsWidth, tabsWidth)); - }, [visibleColumns.length, tabStripScrollWidth]); + window.bookmarks.setPopupWidth(Math.max(colsWidth, tabsWidth, headerMinWidth)); + }, [visibleColumns.length, tabStripScrollWidth, headerMinWidth]); const submitNewColumn = async () => { const name = draftColumnName.trim(); @@ -152,8 +184,11 @@ export default function Popup({
-

Trailhead

-
+
+ +

Trailhead Path Bookmarker

+
+
{!creatingColumn ? (