From 31fba6da39d1591894ec557b32c2e443c70f0734 Mon Sep 17 00:00:00 2001 From: bruno Date: Sun, 19 Jul 2026 13:12:44 -0400 Subject: [PATCH] =?UTF-8?q?fix(library):=20layout=20Notion-style=20?= =?UTF-8?q?=E2=80=94=20drag+checkbox+OPEN=20dans=20colonne=20name,=20hover?= =?UTF-8?q?-only=20CSS=20corrig=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Drag handle (6 dots), checkbox, OPEN bouton intégrés dans la colonne Page name - CSS hover-only: opacity 0 → 1 au mouseover (pas de visibilité permanente) - Checkbox checked toujours visible (opacity:1) même sans hover - OPEN bouton aligné à droite via margin-left:auto dans le name cell - Double-clic sur le nom ouvre la page, simple clic = rename - toggleExpand() force la réactivité Alpine via this.items = [...this.items] - Colonnes drag/select/open séparées supprimées (layout Notion) --- app/templates/library.html | 93 ++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/app/templates/library.html b/app/templates/library.html index 5fc54e4..9a9447a 100644 --- a/app/templates/library.html +++ b/app/templates/library.html @@ -41,42 +41,44 @@ .lib-table-header .th.sortable:hover{color:var(--text-primary);} .lib-table-body{} -/* Column widths */ -.lib-col-select{width:32px;text-align:center;flex-shrink:0;} -.lib-col-drag{width:28px;flex-shrink:0;} +/* Column widths — Notion-style: no separate drag/select columns */ .lib-col-name{flex:1;min-width:0;} .lib-col-author{width:160px;flex-shrink:0;} .lib-col-source{width:130px;flex-shrink:0;} .lib-col-edited{width:100px;flex-shrink:0;} .lib-col-visited{width:100px;flex-shrink:0;} -.lib-col-open{width:80px;text-align:right;flex-shrink:0;} /* ── Row ── */ .lib-row{display:flex;align-items:center;height:36px;transition:background 0.1s;position:relative;} -.lib-row:hover{background:var(--bg-hover);cursor:pointer;} +.lib-row:hover{background:var(--bg-hover);} .lib-row.selected{background:rgba(35,131,226,0.08);} .lib-row .row-cell{display:flex;align-items:center;padding:0 8px;height:100%;overflow:hidden;} -/* Hover-only elements */ -.lib-row .hover-only{opacity:0.35;transition:opacity 0.15s;} +/* ── Name cell — contains drag handle, checkbox, chevron, icon, name, OPEN ── */ +.row-name{display:flex;align-items:center;gap:4px;min-width:0;flex:1;position:relative;} +.row-icon{font-size:15px;flex-shrink:0;width:20px;text-align:center;} +.row-title{font-size:13px;font-weight:400;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;cursor:pointer;} +.row-title:hover{color:var(--accent);} +.row-title input{width:100%;font-size:13px;padding:2px 4px;background:var(--bg-primary);border:1px solid var(--accent);border-radius:4px;color:var(--text-primary);outline:none;} + +/* ── Hover-only elements (appear on row hover) ── */ +.hover-only{opacity:0;transition:opacity 0.12s;flex-shrink:0;} .lib-row:hover .hover-only{opacity:1;} -/* Drag handle — 6 dots */ -.drag-handle{display:flex;flex-wrap:wrap;width:16px;height:16px;cursor:grab;align-content:space-between;justify-content:space-between;flex-shrink:0;opacity:0.45;} -.lib-row:hover .drag-handle{opacity:1;} +/* Drag handle — 6 dots (hover-only, far left of name cell) */ +.drag-handle{display:flex;flex-wrap:wrap;width:14px;height:14px;cursor:grab;align-content:space-between;justify-content:space-between;flex-shrink:0;} .drag-handle .dot{width:3px;height:3px;background:var(--text-tertiary);border-radius:50%;} +.drag-handle:active{cursor:grabbing;} -/* Checkbox */ -.lib-checkbox{width:15px;height:15px;border:1.5px solid var(--text-tertiary);border-radius:3px;cursor:pointer;flex-shrink:0;display:flex;align-items:center;justify-content:center;transition:all 0.15s;} -.lib-row:hover .lib-checkbox{border-color:var(--text-secondary);} -.lib-checkbox.checked{background:var(--accent);border-color:var(--accent);} +/* Checkbox (hover-only) */ +.lib-checkbox{width:15px;height:15px;border:1.5px solid var(--text-tertiary);border-radius:3px;cursor:pointer;flex-shrink:0;display:flex;align-items:center;justify-content:center;transition:all 0.1s;} +.lib-checkbox:hover{border-color:var(--text-primary);} +.lib-checkbox.checked{background:var(--accent);border-color:var(--accent);opacity:1;} .lib-checkbox.checked::after{content:'✓';color:#fff;font-size:10px;font-weight:700;} -/* ── Name cell ── */ -.row-name{display:flex;align-items:center;gap:6px;min-width:0;flex:1;} -.row-icon{font-size:15px;flex-shrink:0;width:20px;text-align:center;} -.row-title{font-size:13px;font-weight:400;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;} -.row-title input{width:100%;font-size:13px;padding:2px 4px;background:var(--bg-primary);border:1px solid var(--accent);border-radius:4px;color:var(--text-primary);outline:none;} +/* OPEN button (hover-only, right side of name cell) */ +.btn-open{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border:1px solid var(--border);border-radius:4px;font-size:11px;color:var(--text-secondary);background:var(--bg-tertiary);cursor:pointer;white-space:nowrap;transition:all 0.1s;flex-shrink:0;text-decoration:none;margin-left:auto;} +.btn-open:hover{background:var(--bg-hover);color:var(--text-primary);border-color:var(--text-primary);} /* Expand chevron */ .tree-chevron{width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;background:none;border:none;color:var(--text-tertiary);cursor:pointer;font-size:8px;padding:0;border-radius:3px;transition:transform 0.15s;} @@ -84,6 +86,7 @@ .tree-chevron.open{transform:rotate(90deg);} /* Indent levels */ +.indent-0{padding-left:4px;} .indent-1{padding-left:24px!important;} .indent-2{padding-left:44px!important;} .indent-3{padding-left:64px!important;} @@ -98,10 +101,9 @@ /* ── Time cells ── */ .row-time{font-size:13px;color:var(--text-secondary);white-space:nowrap;} -/* ── OPEN button ── */ -.btn-open{display:inline-flex;align-items:center;gap:4px;padding:3px 10px;border:1px solid var(--border);border-radius:4px;font-size:12px;color:var(--text-secondary);background:var(--bg-tertiary);cursor:pointer;white-space:nowrap;transition:all 0.1s;opacity:0;} -.lib-row:hover .btn-open{opacity:1;} -.btn-open:hover{background:var(--bg-hover);color:var(--text-primary);border-color:var(--text-primary);} +/* "+ Add new" under expanded parent */ +.add-new-under{padding:4px 8px 4px 28px;color:var(--text-tertiary);font-size:12px;cursor:pointer;transition:color 0.15s;} +.add-new-under:hover{color:var(--text-primary);} /* ── Side Peek Panel ── */ .peek-overlay{position:fixed;top:0;right:0;width:560px;max-width:90vw;height:100vh;background:var(--bg-modal);border-left:1px solid var(--border);box-shadow:-8px 0 32px rgba(0,0,0,0.25);z-index:500;display:flex;flex-direction:column;transform:translateX(100%);transition:transform 0.2s cubic-bezier(0.16,1,0.3,1);} @@ -206,33 +208,26 @@
-
-
-
-
Page name
Created by
Source
Last edited
Last visited
-
@@ -489,6 +486,7 @@ function libraryPage() { // Collapse delete this.expanded[item.id]; this.expanded = Object.assign({}, this.expanded); + this.items = [...this.items]; // force reactivity return; } // Expand — load children if not loaded yet @@ -500,13 +498,12 @@ function libraryPage() { var d = await r.json(); item.children = d.items || []; // Mark the tree for depth calculation - if (typeof this._markChildren === 'function') { - this._markChildren(item.children, (item.depth || 0) + 1); - } + this._markChildren(item.children, (item.depth || 0) + 1); } catch(e) { item.children = []; } } + this.items = [...this.items]; // force Alpine reactivity }, _markChildren(nodes, depth) {