Skip to content

Commit b44af11

Browse files
authored
fix(app): restore tab layout consistency (#33804)
1 parent 717b740 commit b44af11

7 files changed

Lines changed: 73 additions & 21 deletions

File tree

packages/app/src/components/titlebar-tab-drag.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,28 @@ describe("titlebar tab drag", () => {
5656
expect(captureTabDragLayout(list, ["a", "b"]).dividerWidth).toBe(13)
5757
list.remove()
5858
})
59+
60+
test("uses the list gap as the divider width", () => {
61+
const list = document.createElement("div")
62+
const first = document.createElement("div")
63+
const second = document.createElement("div")
64+
const firstTab = document.createElement("div")
65+
const secondTab = document.createElement("div")
66+
first.dataset.titlebarTabSlot = ""
67+
first.dataset.tabKey = "a"
68+
second.dataset.titlebarTabSlot = ""
69+
second.dataset.tabKey = "b"
70+
firstTab.dataset.titlebarTab = ""
71+
secondTab.dataset.titlebarTab = ""
72+
first.append(firstTab)
73+
second.append(secondTab)
74+
list.append(first, second)
75+
list.style.columnGap = "13.5px"
76+
document.body.append(list)
77+
78+
expect(captureTabDragLayout(list, ["a", "b"]).dividerWidth).toBe(13.5)
79+
list.remove()
80+
})
5981
})
6082

6183
describe("titlebar tab gestures", () => {

packages/app/src/components/titlebar-tab-drag.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,19 @@ export function captureTabDragLayout(list: HTMLElement, order: string[]) {
2929

3030
let dividerWidth = 0
3131
if (order.length >= 2) {
32+
const gap = Number.parseFloat(getComputedStyle(list).columnGap) || 0
3233
const secondId = order[1]
3334
for (const slot of slots) {
3435
if (slot.dataset.tabKey !== secondId) continue
3536
const tab = slot.querySelector<HTMLElement>("[data-titlebar-tab]")
3637
if (!tab) break
3738
const style = getComputedStyle(slot)
3839
dividerWidth =
40+
gap ||
3941
slot.getBoundingClientRect().width -
40-
tab.getBoundingClientRect().width +
41-
(Number.parseFloat(style.marginLeft) || 0) +
42-
(Number.parseFloat(style.marginRight) || 0)
42+
tab.getBoundingClientRect().width +
43+
(Number.parseFloat(style.marginLeft) || 0) +
44+
(Number.parseFloat(style.marginRight) || 0)
4345
break
4446
}
4547
}

packages/app/src/components/titlebar-tab-nav.css

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,29 @@
99
justify-content: center;
1010
}
1111

12+
[data-slot="titlebar-tabs"] {
13+
container-type: inline-size;
14+
}
15+
16+
[data-titlebar-tab-list] {
17+
gap: calc(min(12px, 2cqw) + 1.5px);
18+
}
19+
20+
[data-titlebar-tab-slot] {
21+
position: relative;
22+
}
23+
24+
[data-titlebar-tab-slot]:not(:first-child)::before {
25+
content: "";
26+
position: absolute;
27+
top: 8px;
28+
left: calc(0px - min(6px, 1cqw) - 0.75px);
29+
width: 1.5px;
30+
height: 12px;
31+
border-radius: 9999px;
32+
background: var(--v2-background-bg-layer-02);
33+
}
34+
1235
[data-titlebar-tab] [data-slot="tab-close"]::before {
1336
content: "";
1437
position: absolute;
@@ -62,8 +85,14 @@
6285
display: none;
6386
}
6487

65-
[data-titlebar-tab]:hover [data-slot="tab-close"],
66-
[data-titlebar-tab][data-active="true"] [data-slot="tab-close"],
67-
[data-titlebar-tab][data-editing="true"] [data-slot="tab-close"] {
68-
background: var(--tab-bg);
88+
@container (max-width: 64px) {
89+
[data-titlebar-tab-link] {
90+
justify-content: center;
91+
gap: 0;
92+
padding-inline: 0;
93+
}
94+
95+
[data-titlebar-tab-title] {
96+
display: none;
97+
}
6998
}

packages/app/src/components/titlebar-tab-nav.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ export function TabNavItem(props: {
178178
data-slot="titlebar-tab-item"
179179
data-title-overflow={titleOverflowing()}
180180
data-editing={editing()}
181-
class="group relative flex h-7 min-w-24 max-w-60 select-none flex-row items-center gap-1.5 overflow-hidden whitespace-nowrap rounded-[6px] bg-[var(--tab-bg)] px-1.5 [--tab-bg:var(--v2-background-bg-deep)] hover:[--tab-bg:var(--v2-background-bg-layer-02)] has-[>a:focus-visible]:[--tab-bg:var(--v2-background-bg-layer-02)] data-[active='true']:[--tab-bg:var(--v2-background-bg-layer-02)] data-[dragging='true']:[--tab-bg:var(--v2-background-bg-layer-02)] data-[pressed='true']:[--tab-bg:var(--v2-background-bg-layer-02)] data-[editing='true']:[--tab-bg:var(--v2-background-bg-layer-02)]"
181+
class="group relative flex h-7 w-full min-w-0 max-w-56 select-none flex-row items-center gap-1.5 overflow-hidden whitespace-nowrap rounded-[6px] bg-[var(--tab-bg)] px-1.5 [container-type:inline-size] [--tab-bg:var(--v2-background-bg-deep)] hover:[--tab-bg:var(--v2-background-bg-layer-02)] has-[>a:focus-visible]:[--tab-bg:var(--v2-background-bg-layer-02)] data-[active='true']:[--tab-bg:var(--v2-background-bg-layer-02)] data-[dragging='true']:[--tab-bg:var(--v2-background-bg-layer-02)] data-[pressed='true']:[--tab-bg:var(--v2-background-bg-layer-02)] data-[editing='true']:[--tab-bg:var(--v2-background-bg-layer-02)]"
182182
classList={{ invisible: props.hidden }}
183183
data-active={props.active}
184184
data-dragging={props.dragging}
@@ -193,6 +193,7 @@ export function TabNavItem(props: {
193193
return (
194194
<a
195195
data-slot="tab-link"
196+
data-titlebar-tab-link
196197
href={props.href}
197198
draggable={false}
198199
onDragStart={(event) => {
@@ -221,6 +222,7 @@ export function TabNavItem(props: {
221222
titleEl.textContent = session().title
222223
}}
223224
data-slot="tab-title"
225+
data-titlebar-tab-title
224226
class="min-w-0 flex-1 outline-none leading-4"
225227
classList={{
226228
"overflow-hidden text-clip whitespace-nowrap": !editing(),
@@ -297,7 +299,7 @@ export function DraftTabItem(props: {
297299
data-active={props.active}
298300
data-dragging={props.dragging}
299301
data-pressed={props.pressed}
300-
class="group relative shrink-0 flex h-7 max-w-60 flex-row items-center gap-1.5 overflow-hidden rounded-[6px] bg-[var(--tab-bg)] pl-1.5 pr-8 whitespace-nowrap [--tab-bg:var(--v2-background-bg-deep)] hover:[--tab-bg:var(--v2-background-bg-layer-02)] has-[>a:focus-visible]:[--tab-bg:var(--v2-background-bg-layer-02)] data-[active='true']:has-[>a:focus-visible]:[--tab-bg:var(--v2-background-bg-layer-02)] data-[active='true']:[--tab-bg:var(--v2-overlay-simple-overlay-pressed)] data-[dragging='true']:[--tab-bg:var(--v2-background-bg-layer-02)] data-[pressed='true']:[--tab-bg:var(--v2-background-bg-layer-02)]"
302+
class="group relative flex h-7 w-full min-w-0 max-w-56 flex-row items-center gap-1.5 overflow-hidden rounded-[6px] bg-[var(--tab-bg)] pl-1.5 pr-8 [container-type:inline-size] whitespace-nowrap [--tab-bg:var(--v2-background-bg-deep)] hover:[--tab-bg:var(--v2-background-bg-layer-02)] has-[>a:focus-visible]:[--tab-bg:var(--v2-background-bg-layer-02)] data-[active='true']:has-[>a:focus-visible]:[--tab-bg:var(--v2-background-bg-layer-02)] data-[active='true']:[--tab-bg:var(--v2-overlay-simple-overlay-pressed)] data-[dragging='true']:[--tab-bg:var(--v2-background-bg-layer-02)] data-[pressed='true']:[--tab-bg:var(--v2-background-bg-layer-02)] data-[active='true'][data-pressed='true']:[--tab-bg:var(--v2-overlay-simple-overlay-pressed)]"
301303
classList={{ invisible: props.hidden }}
302304
onMouseDown={(event) => {
303305
if (event.button !== 1) return
@@ -306,6 +308,7 @@ export function DraftTabItem(props: {
306308
>
307309
<a
308310
data-slot="tab-link"
311+
data-titlebar-tab-link
309312
href={props.href}
310313
draggable={false}
311314
onDragStart={(event) => {
@@ -322,7 +325,9 @@ export function DraftTabItem(props: {
322325
<span class="flex size-4 shrink-0 items-center justify-center">
323326
<IconV2 name="edit" />
324327
</span>
325-
<span class="truncate leading-5">{props.title}</span>
328+
<span data-titlebar-tab-title class="truncate leading-5">
329+
{props.title}
330+
</span>
326331
</a>
327332
<div data-slot="tab-close" class="absolute right-0 inset-y-0 flex w-7 items-center justify-center">
328333
<IconButtonV2

packages/app/src/components/titlebar-tab-strip.tsx

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ import {
4545
function SessionTabSlot(props: {
4646
tab: SessionTab
4747
id: string
48-
first: () => boolean
4948
active: () => boolean
5049
activeServerKey: ServerConnection.Key
5150
forceTruncate: boolean
@@ -104,10 +103,9 @@ function SessionTabSlot(props: {
104103
<div
105104
data-titlebar-tab-slot
106105
data-tab-key={props.id}
107-
class="flex shrink-0"
106+
class="flex min-w-0 max-w-56 flex-1 basis-0"
108107
classList={{
109108
hidden: !session(),
110-
"ml-1.5 border-l border-[var(--v2-background-bg-layer-02)] pl-1.5": !props.first(),
111109
"pointer-events-none": props.dragActive,
112110
}}
113111
onPointerDown={props.onPointerDown}
@@ -461,17 +459,16 @@ export function TitlebarTabStrip(props: {
461459

462460
return (
463461
<>
464-
<div data-slot="titlebar-tabs" class="relative min-w-0">
462+
<div data-slot="titlebar-tabs" class="relative min-w-0 flex-1">
465463
<div
466464
data-slot="titlebar-tabs-scroll"
467465
class="flex min-w-0 flex-row items-center gap-1.5 overflow-x-auto no-scrollbar [app-region:no-drag]"
468466
ref={scrollRef}
469467
>
470-
<div class="flex min-w-0 flex-row items-center" ref={listRef}>
468+
<div data-titlebar-tab-list class="flex w-full min-w-0 flex-row items-center" ref={listRef}>
471469
<For each={displayTabs()}>
472470
{(tab, index) => {
473471
const id = tabKey(tab)
474-
const first = () => index() === 0
475472
let ref!: HTMLDivElement
476473
useTabShortcut(index, () => props.onNavigate(tab, ref))
477474

@@ -487,7 +484,6 @@ export function TitlebarTabStrip(props: {
487484
<SessionTabSlot
488485
tab={tab}
489486
id={id}
490-
first={first}
491487
active={() => props.currentTab() === tab}
492488
activeServerKey={props.activeServerKey}
493489
forceTruncate={props.forceTruncate}
@@ -510,9 +506,8 @@ export function TitlebarTabStrip(props: {
510506
<div
511507
data-titlebar-tab-slot
512508
data-tab-key={id}
513-
class="flex shrink-0"
509+
class="flex min-w-0 max-w-56 flex-1 basis-0"
514510
classList={{
515-
"ml-1.5 border-l border-[var(--v2-background-bg-layer-02)] pl-1.5": !first(),
516511
"pointer-events-none": drag.active,
517512
}}
518513
onPointerDown={(event) => {

packages/app/src/components/titlebar.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,6 @@ export function Titlebar(props: { update?: TitlebarUpdate }) {
481481
/>
482482
</TooltipV2>
483483
</Show>
484-
<div class="flex-1" />
485484
<TitlebarV2Right state={v2RightState()} />
486485
<Show when={windows() && !electronWindows()}>
487486
<div data-tauri-decorum-tb class="flex flex-row" />

packages/app/src/pages/session/composer/session-composer-region.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ export function SessionComposerRegion(props: {
252252
</Show>
253253
<div
254254
classList={{
255-
"relative z-10": true,
255+
"relative z-30": true,
256256
}}
257257
style={{
258258
"margin-top": `${-lift()}px`,

0 commit comments

Comments
 (0)