From f54ed2164da7c5353acf61ef8226d13567cd3efd Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 14 Aug 2025 11:57:32 +1200 Subject: [PATCH] Add multi-library icon picker and favicon support Introduces a unified icon picker supporting Material, Lucide, Tabler, Phosphor, Remix, Bootstrap, Heroicons, Feather, Simple Icons, and Radix, with category navigation and search. Adds option to use site favicon for bookmarks, updates bookmark rendering to support SVG and image icons, and refines popup and icon grid UI. Includes new iconSets.js for icon set management and updates CSS/HTML for improved icon selection experience. --- bookmarks.backup.json | 7 +- bookmarks.json | 4 +- renderer/home.css | 148 ++++++++--------- renderer/home.html | 25 ++- renderer/home.js | 359 +++++++++++++++++++++++++++++++++++++----- renderer/iconSets.js | 148 +++++++++++++++++ site-history.json | 3 +- 7 files changed, 576 insertions(+), 118 deletions(-) create mode 100644 renderer/iconSets.js diff --git a/bookmarks.backup.json b/bookmarks.backup.json index c9c513b..15807e2 100644 --- a/bookmarks.backup.json +++ b/bookmarks.backup.json @@ -1,3 +1,8 @@ [ - + { + "title": "Apple", + "url": "apple.com", + "icon": "data:image/svg+xml;utf8,%3Csvg%20role%3D%22img%22%20viewBox%3D%220%200%2024%2024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20style%3D%22color%3A%20white%3B%22%3E%3Ctitle%3EApple%3C%2Ftitle%3E%3Cpath%20d%3D%22M12.152%206.896c-.948%200-2.415-1.078-3.96-1.04-2.04.027-3.91%201.183-4.961%203.014-2.117%203.675-.546%209.103%201.519%2012.09%201.013%201.454%202.208%203.09%203.792%203.039%201.52-.065%202.09-.987%203.935-.987%201.831%200%202.35.987%203.96.948%201.637-.026%202.676-1.48%203.676-2.948%201.156-1.688%201.636-3.325%201.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04%202.48-4.494%202.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675%201.09-4.61%201.09zM15.53%203.83c.843-1.012%201.4-2.427%201.245-3.83-1.207.052-2.662.805-3.532%201.818-.78.896-1.454%202.338-1.273%203.714%201.338.104%202.715-.688%203.559-1.701%22%2F%3E%3C%2Fsvg%3E", + "iconSet": "simple" + } ] \ No newline at end of file diff --git a/bookmarks.json b/bookmarks.json index c44dc44..0637a08 100644 --- a/bookmarks.json +++ b/bookmarks.json @@ -1,3 +1 @@ -[ - -] \ No newline at end of file +[] \ No newline at end of file diff --git a/renderer/home.css b/renderer/home.css index 3dbad4d..93627da 100644 --- a/renderer/home.css +++ b/renderer/home.css @@ -227,6 +227,51 @@ body, html { color: var(--accent); } +/* Favicon image in bookmark tile */ +.bookmark-favicon { + width: 28px; + height: 28px; + object-fit: contain; + margin-bottom: 0.25rem; + image-rendering: -webkit-optimize-contrast; + filter: drop-shadow(0 0 2px rgba(0,0,0,0.4)); +} + +/* SVG icons in picker grid */ +.icon-item .grid-svg { + width: 24px; + height: 24px; + display: block; + pointer-events: none; +} + +/* Icon category navigation */ +.icon-categories-bar { + display: flex; + flex-wrap: wrap; + gap: 0.4rem; + margin: 0.25rem 0 0.75rem; +} +.icon-picker-layout { display:flex; gap:1rem; align-items:stretch; background:#f6f7f9; border:1px solid #e2e5ea; border-radius:14px; padding:0.85rem 0.85rem 0.85rem 0.75rem; box-shadow:inset 0 0 0 1px #ffffff, 0 2px 4px rgba(0,0,0,0.05); min-height:280px; max-height:320px; overflow:hidden; } +.icon-side-nav { width:200px; display:flex; flex-direction:column; gap:0.3rem; overflow-y:auto; padding:0.3rem; background:linear-gradient(180deg,#fff,#f4f5f7); border:1px solid #d9dde2; border-radius:10px; max-height:100%; } +.icon-main { flex:1; min-width:0; display:flex; flex-direction:column; } +.icon-header { display:flex; justify-content:space-between; align-items:center; margin-bottom:0.5rem; } +.icon-filter-label { font-size:0.875rem; color:#555; font-weight:600; } +.favicon-toggle { display:flex; align-items:center; gap:0.4rem; } +.favicon-checkbox { width:16px; height:16px; accent-color:var(--accent); } +.favicon-label { font-size:0.75rem; color:#666; cursor:pointer; user-select:none; } +.icon-filter { margin-bottom:0.5rem; background:#fff; border:1px solid #d4d9df; border-radius:8px; padding:0.5rem 0.7rem; font-size:0.8rem; } +.icon-filter:focus { outline:none; border-color:var(--accent); box-shadow:0 0 0 2px rgba(123,46,255,0.25); } +.icon-cat-btn { width:100%; text-align:left; padding:0.55rem 0.65rem 0.55rem 0.55rem; font-size:0.7rem; font-weight:600; letter-spacing:.5px; background:transparent; border:1px solid transparent; border-radius:8px; cursor:pointer; color:#4a4f55; display:flex; align-items:center; gap:0.55rem; transition: background .18s, color .18s, border-color .2s; position:relative; } +.icon-cat-btn .material-symbols-outlined { font-size:18px; width:30px; height:30px; background:#e9edf1; border:1px solid #d4d9df; border-radius:8px; flex-shrink:0; display:flex; align-items:center; justify-content:center; box-shadow:0 0 0 1px #fff inset; } +.icon-cat-btn::before { display:none; } +.icon-cat-btn:hover { background:#eef2f6; } +.icon-cat-btn.active { background:linear-gradient(135deg,var(--accent),var(--primary)); color:#fff; border-color:rgba(255,255,255,0.35); box-shadow:0 2px 6px -2px rgba(0,0,0,0.35); } +.icon-cat-btn.active .material-symbols-outlined { background:rgba(255,255,255,0.22); border-color:rgba(255,255,255,0.4); color:#fff; } + +.icon-section-label { display:none; } +.icon-section-anchor { height:1px; width:100%; margin-top:4px; } + .bookmark-title { font-size: 0.8rem; white-space: nowrap; @@ -245,6 +290,18 @@ body, html { cursor: pointer; } +/* Dynamic bookmark icon colors based on theme */ +.bookmark .material-symbols-outlined { + color: var(--text, #E0E0E0) !important; + transition: color 0.2s ease; +} + +/* Ensure dark theme compatibility - fallback rules */ +body[data-theme="dark"] .bookmark .material-symbols-outlined, +.bookmark .material-symbols-outlined[style*="color: white"] { + color: white !important; +} + /* Add button style */ .add-bookmark { display: flex; @@ -286,29 +343,10 @@ body, html { } /* Popup inner as white Material card */ -.popup-inner { - display: flex; - flex-direction: column; - gap: 1.5rem; - color: #222222; - min-width: 320px; - /* existing styling */ - background: #ffffff; - border-radius: 8px; - box-shadow: 0 8px 24px rgba(0,0,0,0.3); - padding: 1.5rem; - transition: transform 0.3s ease-out, opacity 0.3s ease-out; - transform: translateY(-10px) scale(0.95); - opacity: 0; - width: 500px; /* make popup wider */ - max-width: 90vw; /* keep it responsive on small screens */ -} +.popup-inner { display:flex; flex-direction:column; gap:1.1rem; color:#222; min-width:400px; background:#ffffff; border-radius:16px; box-shadow:0 12px 40px -8px rgba(0,0,0,0.35), 0 0 0 1px rgba(0,0,0,0.06); padding:1.5rem 1.5rem 1.25rem; transition:transform .35s cubic-bezier(.16,.84,.44,1), opacity .35s; transform:translateY(14px) scale(.94); opacity:0; width:760px; max-width:90vw; max-height:85vh; overflow:hidden; } /* animate in when not hidden */ -.popup:not(.hidden) .popup-inner { - transform: translateY(0) scale(1); - opacity: 1; -} +.popup:not(.hidden) .popup-inner { transform:translateY(0) scale(1); opacity:1; } /* dialog title */ .popup-inner h2 { @@ -347,34 +385,7 @@ body, html { box-shadow: 0 0 0 2px rgba(123,46,255,0.2); } -/* icon-grid container */ -.icon-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(40px, 1fr)); - gap: 8px; - max-height: 200px; - overflow-y: auto; - margin: 0 -0.5rem 1rem; - padding: 0.5rem; - background: #fafafa; - border: 1px solid #eee; - border-radius: 4px; -} - -/* individual icon items */ -.icon-item { - background: #ffffff; - border: 1px solid #ddd; - box-shadow: 0 1px 2px rgba(0,0,0,0.05); - border-radius: 4px; - cursor: pointer; - padding: 4px; - text-align: center; -} - -.icon-item:hover { - background: #f0f0f0; -} +/* Removed earlier duplicate icon-grid + icon-item block (consolidated below) */ /* action buttons container */ .popup-buttons { @@ -422,26 +433,21 @@ body, html { --text: #E0E0E0; } -/* Icon grid styling */ -.icon-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(40px, 1fr)); - gap: 8px; - max-height: 200px; - overflow-y: auto; - margin-bottom: 8px; -} -.icon-item { - cursor: pointer; - padding: 4px; - border: 1px solid transparent; - border-radius: 4px; - text-align: center; -} -.icon-item:hover { - background: rgba(0, 0, 0, 0.1); -} -.icon-item.selected { - border-color: #0078d4; - background: rgba(0, 120, 212, 0.1); +/* Unified icon grid styling */ +.icon-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(42px,1fr)); gap:5px; flex:1 1 auto; min-height:160px; max-height:260px; overflow-y:auto; overflow-x:hidden; padding:0.6rem 0.6rem 0.7rem; background:rgba(255,255,255,0.45); backdrop-filter:blur(6px); border:1px solid rgba(0,0,0,0.08); border-radius:10px; position:relative; scroll-behavior:smooth; } +.icon-main { flex:1; min-height:300px; } +.icon-item { cursor:pointer; padding:6px; border:1px solid rgba(255,255,255,0.06); border-radius:10px; text-align:center; display:flex; align-items:center; justify-content:center; background:rgba(255,255,255,0.05); transition: background .15s, transform .15s, box-shadow .2s; font-size:0.65rem; line-height:1; font-weight:500; position:relative; } +.icon-item::after { content:""; position:absolute; inset:0; border-radius:inherit; box-shadow:0 0 0 0 rgba(0,0,0,0); transition:box-shadow .25s; } +.icon-item:hover { background:rgba(255,255,255,0.12); } +.icon-item:active { transform:scale(.92); } +.icon-item.selected { background:linear-gradient(135deg,var(--accent),var(--primary)); color:#fff; border-color:transparent; box-shadow:0 4px 10px -3px rgba(0,0,0,.6); } +.icon-item.selected::after { box-shadow:0 0 0 2px rgba(255,255,255,0.65); } + +/* Icon set selector row */ +.icon-set-row { + display: flex; + align-items: center; + gap: 0.5rem; + margin-top: 0.75rem; } +.icon-section-label { display:none; } diff --git a/renderer/home.html b/renderer/home.html index b7c6125..1532689 100644 --- a/renderer/home.html +++ b/renderer/home.html @@ -7,6 +7,8 @@ + +
@@ -59,11 +61,24 @@ - - -
- +
+ +
+
+ +
+ + +
+
+ +
+ +
+