feat: finalisation split view #75 — boutons, nav clavier, palette, ROADMAP
CI / lint (push) Failing after 12s
CI / test (push) Has been skipped
CI / build (push) Has been skipped
CI / e2e (push) Has been skipped
CI / security (push) Successful in 13s
Desktop Build / build-windows (push) Has been cancelled
Desktop Build / build-linux (push) Has been cancelled

Ajouts:
- C3: Boutons Split ⊞→ ⊞↓ dans la barre d'onglets (visibles au survol)
- C2: Ctrl+Alt+←/→/↑/↓ navigation entre panneaux
- C2: Ctrl+Shift+Alt+W fermer tous les autres panneaux
- H1: 5 commandes palette (Split R/D, Close Pane, Focus Next/Prev)
- ROADMAP.md: section 75 mise à jour avec statut 80% complété

CSS: .tab-split-buttons, .tab-split-btn avec opacity hover
This commit is contained in:
2026-07-28 10:08:11 -04:00
parent ed5cf597f9
commit 804e6313b3
4 changed files with 160 additions and 118 deletions
+6
View File
@@ -51,6 +51,12 @@ function getCMDS() {
{ id:'reindex', label:'🔄 '+t('vault.reindex'), desc:t('palette.reindex_desc'), cat:'Actions', act:async()=>{close();try{await api('/api/index/reload');showToast(t('sync.index_reloaded'),'success');}catch{showToast(t('common.error'),'error');}} },
{ id:'help', label:'❓ '+t('help.help_title'), desc:t('palette.help_desc'), cat:'Système', act:()=>{close();const b=document.getElementById('help-open-btn');if(b)b.click();} },
{ id:'config', label:t('palette.cmd_config'), desc:t('palette.cmd_config_desc'), cat:'Système', act:()=>{close();const b=document.getElementById('config-open-btn');if(b)b.click();} },
// Pane / Split commands
{ id:'split-right', label:'⊞→ Diviser à droite', desc:'Crée un panneau à droite avec cet onglet', cat:'Panneaux', act:()=>{close();if(window.PaneManager)window.PaneManager.splitRight();} },
{ id:'split-down', label:'⊞↓ Diviser en bas', desc:'Crée un panneau en dessous avec cet onglet', cat:'Panneaux', act:()=>{close();if(window.PaneManager)window.PaneManager.splitDown();} },
{ id:'close-pane', label:'✕ Fermer le panneau actif', desc:'Ferme le panneau actif et tous ses onglets', cat:'Panneaux', act:()=>{close();if(window.PaneManager&&window.PaneManager.isSplit())window.PaneManager.closeActivePane();} },
{ id:'focus-next', label:'→ Panneau suivant', desc:'Active le panneau suivant (Ctrl+Alt+→)', cat:'Panneaux', act:()=>{close();if(window.PaneManager&&window.PaneManager.isSplit()){const n=(window.PaneManager.activePaneId+1)%window.PaneManager.panes.length;window.PaneManager.setActivePane(n);}} },
{ id:'focus-prev', label:'← Panneau précédent', desc:'Active le panneau précédent (Ctrl+Alt+←)', cat:'Panneaux', act:()=>{close();if(window.PaneManager&&window.PaneManager.isSplit()){const n=(window.PaneManager.activePaneId-1+window.PaneManager.panes.length)%window.PaneManager.panes.length;window.PaneManager.setActivePane(n);}} },
];
return _cmdsCache;
}
+57
View File
@@ -46,6 +46,37 @@ function createPaneTabManager(paneId) {
this._tabList = document.getElementById('tab-list-' + paneId);
if (!this._contentArea)
this._contentArea = document.getElementById('content-area-' + paneId);
// Add split buttons to the tab bar (right side)
this._ensureSplitButtons();
},
_ensureSplitButtons() {
if (!this._tabBar) return;
// Remove existing split buttons if any
const existing = this._tabBar.querySelector('.tab-split-buttons');
if (existing) existing.remove();
const btns = document.createElement('div');
btns.className = 'tab-split-buttons';
btns.innerHTML = `
<button class="tab-split-btn" title="Diviser à droite (Ctrl+Alt+\\)" data-action="split-right">
<i data-lucide="panel-right" style="width:13px;height:13px"></i>
</button>
<button class="tab-split-btn" title="Diviser en bas (Ctrl+Alt+Shift+\\)" data-action="split-down">
<i data-lucide="panel-bottom" style="width:13px;height:13px"></i>
</button>
`;
btns.querySelector('[data-action="split-right"]').addEventListener('click', (e) => {
e.stopPropagation();
if (window.PaneManager) window.PaneManager.splitRight();
});
btns.querySelector('[data-action="split-down"]').addEventListener('click', (e) => {
e.stopPropagation();
if (window.PaneManager) window.PaneManager.splitDown();
});
this._tabBar.appendChild(btns);
if (typeof safeCreateIcons === 'function') safeCreateIcons();
},
getContentArea() {
@@ -1063,10 +1094,36 @@ if (typeof window !== 'undefined') {
e.preventDefault();
PaneManager.splitDown();
}
// Close active pane
if (e.ctrlKey && e.altKey && !e.shiftKey && (e.key === 'w' || e.key === 'W') && PaneManager.isSplit()) {
e.preventDefault();
PaneManager.closeActivePane();
}
// Close all other panes
if (e.ctrlKey && e.shiftKey && e.altKey && (e.key === 'w' || e.key === 'W') && PaneManager.isSplit()) {
e.preventDefault();
PaneManager.closeOtherPanes();
}
// Navigate between panes
if (e.ctrlKey && e.altKey && PaneManager.isSplit()) {
if (e.key === 'ArrowRight') {
e.preventDefault();
const next = (PaneManager.activePaneId + 1) % PaneManager.panes.length;
PaneManager.setActivePane(next);
} else if (e.key === 'ArrowLeft') {
e.preventDefault();
const prev = (PaneManager.activePaneId - 1 + PaneManager.panes.length) % PaneManager.panes.length;
PaneManager.setActivePane(prev);
} else if (e.key === 'ArrowDown' && PaneManager.layout === 'vertical') {
e.preventDefault();
const next = (PaneManager.activePaneId + 1) % PaneManager.panes.length;
PaneManager.setActivePane(next);
} else if (e.key === 'ArrowUp' && PaneManager.layout === 'vertical') {
e.preventDefault();
const prev = (PaneManager.activePaneId - 1 + PaneManager.panes.length) % PaneManager.panes.length;
PaneManager.setActivePane(prev);
}
}
});
// Init — wait for DOM + singleton TabManager to be ready
setTimeout(() => {
+35
View File
@@ -6526,6 +6526,41 @@ body.popup-mode .content-area {
scrollbar-width: thin;
}
/* Split buttons in tab bar */
.tab-split-buttons {
display: flex;
align-items: center;
gap: 2px;
padding: 0 4px;
flex-shrink: 0;
opacity: 0.3;
transition: opacity 150ms ease;
}
.tab-bar:hover .tab-split-buttons,
.tab-split-buttons:hover {
opacity: 1;
}
.tab-split-btn {
display: flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
border: none;
border-radius: 4px;
background: transparent;
color: var(--text-muted);
cursor: pointer;
transition: background 100ms ease, color 100ms ease;
}
.tab-split-btn:hover {
background: var(--bg-hover);
color: var(--accent);
}
.tab-list::-webkit-scrollbar {
height: 3px;
}