From c11bbf302609bc9a9bfeed3ee4eb980c61a787fb Mon Sep 17 00:00:00 2001 From: David Date: Wed, 29 Apr 2026 12:02:23 -0400 Subject: [PATCH] Minimized list view, CSP fix, last-row menu drop-up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Minimized popup now shows a compact bookmark list grouped by column header, with color stripe, alias, and inline action buttons per row - Add img-src 'self' data: to CSP so Vite's inlined tray icon loads in the production build (was blocked by default-src 'self') - Last-row ⋯ menu opens upward to avoid overflowing the popup edge Co-Authored-By: Claude Opus 4.7 (1M context) --- index.html | 2 +- src/components/BookmarkRow.jsx | 2 +- src/components/MinimizedList.jsx | 162 +++++++++++++++++++++++++++++++ src/components/Popup.jsx | 17 +++- src/styles/index.css | 92 ++++++++++++++++++ 5 files changed, 271 insertions(+), 4 deletions(-) create mode 100644 src/components/MinimizedList.jsx diff --git a/index.html b/index.html index c61915f..69c0161 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,7 @@ - + Trailhead Path Bookmarker diff --git a/src/components/BookmarkRow.jsx b/src/components/BookmarkRow.jsx index 49b747b..781e429 100644 --- a/src/components/BookmarkRow.jsx +++ b/src/components/BookmarkRow.jsx @@ -130,7 +130,7 @@ export default function BookmarkRow({ onClick={() => setMenuOpen((v) => !v)} >⋯ {menuOpen && ( -
+
+ {showTerminal && ( + + )} + {!inspect.isNetwork && showClaude && ( + + )} + {!inspect.isNetwork && ( + + )} + {showRedeploy && inspect.redeployPath && !bookmark.hideDeploy && ( + + )} +
+ {status && ( +
+ {status.text} +
+ )} + + ); +} diff --git a/src/components/Popup.jsx b/src/components/Popup.jsx index 7ce7e30..ffb7287 100644 --- a/src/components/Popup.jsx +++ b/src/components/Popup.jsx @@ -2,9 +2,13 @@ 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 MinimizedList from './MinimizedList.jsx'; import iconUrl from '../../assets/tray-icon.png'; const COLUMN_WIDTH = 216; +// Minimized list view: alias + up to 5 inline action buttons. Slightly wider +// than a single column so the alias has room next to the buttons. +const MINIMIZED_WIDTH = 260; // Padding budget so the popup doesn't clip the tab strip: popup-inner has // 14px each side and the tab-bar adds 2px breathing room on either side. const TAB_STRIP_PADDING = 32; @@ -114,7 +118,7 @@ export default function Popup({ // or scroll horizontally inside the popup once they would push it off-screen. useEffect(() => { if (minimized) { - window.bookmarks.setPopupWidth(COLUMN_WIDTH); + window.bookmarks.setPopupWidth(MINIMIZED_WIDTH); return; } const colsWidth = Math.max(1, visibleColumns.length || 1) * COLUMN_WIDTH; @@ -273,7 +277,16 @@ export default function Popup({ /> )} - {minimized ? null : hasNoTabs ? ( + {minimized ? ( + + ) : hasNoTabs ? (
No tabs yet — click + in the tab bar to create your first.
diff --git a/src/styles/index.css b/src/styles/index.css index 7ed1250..b540955 100644 --- a/src/styles/index.css +++ b/src/styles/index.css @@ -390,6 +390,14 @@ button:disabled { opacity: 0.5; cursor: default; } overflow: hidden; } +/* Flip the menu above the row for the last bookmark in a column — otherwise + it overflows the popup's bottom edge (absolutely-positioned children don't + feed into popup-inner.offsetHeight, so auto-resize can't grow to fit). */ +.bookmark-menu.drop-up { + top: auto; + bottom: 30px; +} + .bookmark-menu button { background: transparent; border: none; @@ -818,6 +826,90 @@ button.danger-button:hover:not(:disabled) { background: #f78787; } +/* --- Minimized list view --- */ + +.mini-groups { + display: flex; + flex-direction: column; + gap: 10px; +} + +.mini-group { + display: flex; + flex-direction: column; + gap: 4px; +} + +.mini-group-header { + margin: 0; + padding: 4px 2px 2px 2px; + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.6px; + color: var(--text-dim); + border-bottom: 1px solid var(--border); +} + +.mini-list { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + gap: 4px; +} + +.mini-row { + display: flex; + align-items: center; + gap: 6px; + background: var(--bg-elevated); + border: 1px solid var(--border); + border-left: 3px solid var(--border); + border-radius: var(--radius); + padding: 4px 6px; + min-width: 0; + flex-wrap: wrap; +} + +.mini-alias { + flex: 1; + min-width: 0; + font-size: 12px; + font-weight: 600; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + -webkit-user-select: text; + user-select: text; +} + +.mini-actions { + display: flex; + gap: 2px; + flex: 0 0 auto; +} + +.icon-button.mini-btn { + width: 22px; + height: 22px; + font-size: 11px; + font-weight: 600; + border-radius: 4px; +} + +.mini-status { + flex: 1 0 100%; + font-size: 10px; + padding: 2px 4px; + border-radius: 3px; + margin-top: 2px; +} + +.mini-status.error { background: rgba(239, 107, 107, 0.12); color: var(--error); } +.mini-status.info { background: rgba(127, 201, 127, 0.12); color: var(--ok); } + /* --- Submenu inside column overflow --- */ .bookmark-submenu {