fix(theseus): tabs never run under the window controls; the strip scrolls
With many tabs open, the last ones slid under the minimise / maximise / close overlay: the strip reserved that space as padding, and padding does not stop overflowing flex items. The tabs now live in their own row that clips at its own edge, shrink down to icon + close before anything is hidden, and the row scrolls sideways with the wheel once they hit that minimum, keeping the selected tab in view. The + button sits outside the row so it stays reachable no matter how many tabs are open.
This commit is contained in:
parent
5dc90f20b4
commit
f5877bc890
1 changed files with 40 additions and 10 deletions
50
chrome.html
50
chrome.html
|
|
@ -41,13 +41,24 @@
|
|||
opts out, and --wco-reserve keeps tabs clear of the native minimise /
|
||||
maximise / close overlay (set from navigator.windowControlsOverlay, or a
|
||||
fixed 140px when that API isn't exposed). */
|
||||
.tabs { display: flex; align-items: flex-end; gap: 4px; padding: 6px 8px 0; padding-right: calc(8px + var(--wco-reserve, 0px));
|
||||
.tabs { display: flex; align-items: flex-end; padding: 6px 8px 0; padding-right: calc(8px + var(--wco-reserve, 0px));
|
||||
height: 34px; overflow: hidden; -webkit-app-region: drag; }
|
||||
.tabs > *, .grouppop, .ctxmenu { -webkit-app-region: no-drag; }
|
||||
/* The tabs sit in their own row INSIDE the reserved-for-window-controls
|
||||
padding. Padding does not stop overflowing flex items, so with many
|
||||
tabs the last ones used to run under the minimise / close buttons;
|
||||
the row is a sized box (min-width: 0) that clips at its own edge. */
|
||||
.tabrow { display: flex; align-items: flex-end; gap: 4px; flex: 1 1 auto; min-width: 0; height: 100%;
|
||||
overflow-x: auto; overflow-y: hidden; scrollbar-width: none; -webkit-app-region: drag; }
|
||||
.tabrow::-webkit-scrollbar { display: none; }
|
||||
.tabrow > *, .tabs > .newtab, .grouppop, .ctxmenu { -webkit-app-region: no-drag; }
|
||||
/* The + button sits OUTSIDE the scrolling row, so it stays reachable no
|
||||
matter how many tabs are open; the row scrolls (wheel) once tabs hit
|
||||
their minimum width, like Chrome. */
|
||||
.tabs > .newtab { flex: none; margin-left: 2px; }
|
||||
/* Same-size tabs: each tab claims an equal share of the row, capped at
|
||||
200px so 2 tabs don't stretch across the whole window. min-width lets
|
||||
many tabs shrink cleanly while still showing a couple letters. */
|
||||
.tab { display: flex; align-items: center; gap: 8px; flex: 1 1 0; max-width: 200px; min-width: 60px; padding: 6px 10px;
|
||||
200px so 2 tabs don't stretch across the whole window. With many tabs
|
||||
they shrink down to icon + close (34px) before anything is clipped. */
|
||||
.tab { display: flex; align-items: center; gap: 8px; flex: 1 1 0; max-width: 200px; min-width: 34px; padding: 6px 10px;
|
||||
background: var(--surface); border: 1px solid var(--line2); border-bottom: none; border-radius: 8px 8px 0 0;
|
||||
font-size: 12.5px; cursor: default; color: var(--mut); user-select: none; }
|
||||
.tab.dragging { opacity: .45; cursor: grabbing; }
|
||||
|
|
@ -59,7 +70,7 @@
|
|||
.tab.active { background: var(--active); color: var(--ink); border-color: rgb(from var(--acid) r g b / .7);
|
||||
box-shadow: inset 0 2px 0 var(--acid); }
|
||||
.tab.active.grp { box-shadow: inset 0 2px 0 var(--gc, var(--acid)); }
|
||||
.tab .t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
|
||||
.tab .t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0; }
|
||||
.tab .ico { display: flex; align-items: center; flex: none; }
|
||||
.tab .ico:empty { display: none; }
|
||||
.tab .fav { width: 14px; height: 14px; flex: none; border-radius: 2px; object-fit: contain; }
|
||||
|
|
@ -410,7 +421,7 @@
|
|||
.bcnrbar .bdismiss { color: var(--dim); text-decoration: none; } .bcnrbar .bdismiss:hover { color: var(--ink); }
|
||||
</style></head>
|
||||
<body>
|
||||
<div class="tabs" id="tabs"></div>
|
||||
<div class="tabs" id="tabstrip"><div class="tabrow" id="tabs"></div></div>
|
||||
<div class="bar" id="bar">
|
||||
<div class="nav">
|
||||
<button class="ic" id="back" title="Back"><svg viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round"><path d="M13 8H3M6 5L3 8l3 3"/></svg></button>
|
||||
|
|
@ -1318,13 +1329,32 @@
|
|||
updateTab(el, t);
|
||||
order.push(el);
|
||||
}
|
||||
let plus = document.getElementById("newtab");
|
||||
if (!plus) { plus = document.createElement("span"); plus.className = "newtab"; plus.id = "newtab"; plus.textContent = "+"; plus.onclick = () => T.newTab(); }
|
||||
order.push(plus);
|
||||
// "+" lives next to the row, not in it (see CSS) — created once.
|
||||
if (!document.getElementById("newtab")) {
|
||||
const plus = document.createElement("span"); plus.className = "newtab"; plus.id = "newtab"; plus.textContent = "+"; plus.title = "New tab (Ctrl+T)";
|
||||
plus.onclick = () => T.newTab();
|
||||
box.parentElement.appendChild(plus);
|
||||
}
|
||||
const keep = new Set(order);
|
||||
for (const el of [...box.children]) if (!keep.has(el)) el.remove();
|
||||
order.forEach((el, i) => { if (box.children[i] !== el) box.insertBefore(el, box.children[i] || null); });
|
||||
// Keep the selected tab in view when the row has scrolled.
|
||||
const act = box.querySelector(".tab.active");
|
||||
if (act && box.scrollWidth > box.clientWidth) {
|
||||
const l = act.offsetLeft, r = l + act.offsetWidth;
|
||||
if (l < box.scrollLeft) box.scrollLeft = l - 4;
|
||||
else if (r > box.scrollLeft + box.clientWidth) box.scrollLeft = r - box.clientWidth + 4;
|
||||
}
|
||||
}
|
||||
// Wheel over the row scrolls it sideways (there is no visible scrollbar).
|
||||
$("tabs").addEventListener("wheel", (e) => {
|
||||
const box = $("tabs");
|
||||
if (box.scrollWidth <= box.clientWidth) return;
|
||||
const d = Math.abs(e.deltaX) > Math.abs(e.deltaY) ? e.deltaX : e.deltaY;
|
||||
if (!d) return;
|
||||
box.scrollLeft += d;
|
||||
e.preventDefault();
|
||||
}, { passive: false });
|
||||
|
||||
// ---- Tab context menu (right-click a tab) ----
|
||||
const TAB_GROUP_COLORS = [
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue