Skip to content

Commit 4069c8f

Browse files
authored
Merge pull request #1076 from org2AI/fix/chat-pane-collapsed-drag-region
fix(chat-panel): restore the window drag zone in the folded header
2 parents 6427fb2 + 8bf2597 commit 4069c8f

5 files changed

Lines changed: 70 additions & 4 deletions

File tree

src/components/WindowChrome/PublishedHeaderSlotsView.tsx

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,23 @@ export interface PublishedHeaderSlots {
1414
joinWithFollowingRow?: boolean;
1515
}
1616

17+
const DRAG_STYLE = { WebkitAppRegion: "drag" } as React.CSSProperties;
18+
1719
interface PublishedHeaderSlotsViewProps {
1820
slots: PublishedHeaderSlots | null;
1921
/** Left inset for host-specific chrome alignment. */
2022
paddingLeftClassName?: string;
23+
/**
24+
* Hand the space after `content` to the host window as a drag handle
25+
* instead of stretching `content` across it.
26+
*
27+
* `content` normally carries the `flex-1`, which makes the whole middle of
28+
* the row one no-drag region. That is fine while a tab bar sits above and
29+
* owns dragging, but a row that is its own pane's only chrome has to offer
30+
* a handle of its own — exactly as the tab strip does, where the strip is
31+
* draggable and only the pills opt out.
32+
*/
33+
dragFiller?: boolean;
2134
}
2235

2336
/**
@@ -26,7 +39,11 @@ interface PublishedHeaderSlotsViewProps {
2639
*/
2740
export const PublishedHeaderSlotsView: React.FC<PublishedHeaderSlotsViewProps> =
2841
memo(
29-
({ slots, paddingLeftClassName = HEADER_CONTENT_LEFT_PADDING_CLASS }) => {
42+
({
43+
slots,
44+
paddingLeftClassName = HEADER_CONTENT_LEFT_PADDING_CLASS,
45+
dragFiller = false,
46+
}) => {
3047
return (
3148
<div
3249
className={`flex min-w-0 flex-1 items-center ${paddingLeftClassName}`}
@@ -36,9 +53,20 @@ export const PublishedHeaderSlotsView: React.FC<PublishedHeaderSlotsViewProps> =
3653
{slots.leading}
3754
</NoDragRegion>
3855
)}
39-
<NoDragRegion className="flex min-w-0 flex-1 items-center">
56+
<NoDragRegion
57+
className={`flex min-w-0 items-center ${dragFiller ? "" : "flex-1"}`}
58+
>
4059
{slots?.content}
4160
</NoDragRegion>
61+
{dragFiller && (
62+
<div
63+
className="h-full min-w-0 flex-1"
64+
data-tauri-drag-region
65+
data-testid="published-header-drag-filler"
66+
style={DRAG_STYLE}
67+
aria-hidden
68+
/>
69+
)}
4270
{slots?.trailing && (
4371
<NoDragRegion className="flex shrink-0 items-center gap-px">
4472
{slots.trailing}

src/engines/ChatPanel/ChatPanelHeader.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ describe("ChatPanelHeader tab row collapse", () => {
104104
expect(markup).not.toContain(
105105
'data-testid="chat-panel-collapsed-tab-controls"'
106106
);
107+
// The tab row above still owns window dragging here.
108+
expect(markup).not.toContain('data-testid="published-header-drag-filler"');
107109
expect(markup).toContain('style="height:80px"');
108110
});
109111

@@ -124,8 +126,10 @@ describe("ChatPanelHeader tab row collapse", () => {
124126
expect(markup).not.toContain("transition-opacity");
125127
expect(markup).toContain('data-icon="x"');
126128
expect(markup).toContain('style="height:44px"');
127-
// The maximized pane's only chrome — no rule under it.
129+
// The maximized pane's only chrome — no rule under it, and it has to
130+
// offer the window-drag handle the folded tab row used to provide.
128131
expect(markup).not.toContain("border-b border-border-2");
132+
expect(markup).toContain('data-testid="published-header-drag-filler"');
129133
// The window-edge gap the folded 44px row used to hold (its pt-2).
130134
expect(markup).toContain('data-testid="chat-panel-collapsed-header"');
131135
expect(markup).toContain("padding-top:8px");

src/engines/ChatPanel/ChatPanelHeader.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ export function ChatPanelHeader({
421421
? getCollapsedSidebarChromeOffset()
422422
: undefined
423423
}
424+
dragFiller
424425
/>
425426
</div>
426427
) : (

src/engines/ChatPanel/header/ChatPanelPublishedHeader.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,33 @@ describe("ChatPanelPublishedHeader", () => {
4747
expect(markup).not.toContain("border-b border-border-2");
4848
});
4949

50+
it("stretches content over the row when a tab bar above owns dragging", () => {
51+
const markup = renderToStaticMarkup(
52+
React.createElement(ChatPanelPublishedHeader, {
53+
windowsHost: false,
54+
slots: { content: React.createElement("span", null, "Content") },
55+
})
56+
);
57+
58+
expect(markup).toContain("flex min-w-0 flex-1 items-center");
59+
expect(markup).not.toContain('data-testid="published-header-drag-filler"');
60+
});
61+
62+
it("hands the space after content to the window when it is the only chrome", () => {
63+
const markup = renderToStaticMarkup(
64+
React.createElement(ChatPanelPublishedHeader, {
65+
windowsHost: false,
66+
dragFiller: true,
67+
slots: { content: React.createElement("span", null, "Content") },
68+
})
69+
);
70+
71+
// The filler is draggable; content no longer swallows the row.
72+
expect(markup).toContain('data-testid="published-header-drag-filler"');
73+
expect(markup).toContain("-webkit-app-region:drag");
74+
expect(markup).toContain("Content");
75+
});
76+
5077
it("does not add an empty row when no pane has published controls", () => {
5178
expect(
5279
renderToStaticMarkup(

src/engines/ChatPanel/header/ChatPanelPublishedHeader.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,16 @@ interface ChatPanelPublishedHeaderProps {
1717
* set, and is only passed once this row inherited the pane's top edge.
1818
*/
1919
leadingInsetPx?: number;
20+
/**
21+
* Offer the space after the title as a window-drag handle. Set once this row
22+
* is the pane's only chrome and no tab bar above it owns dragging.
23+
*/
24+
dragFiller?: boolean;
2025
}
2126

2227
/** Chat-pane counterpart of My Station's shared 36px published header. */
2328
export const ChatPanelPublishedHeader: React.FC<ChatPanelPublishedHeaderProps> =
24-
memo(({ slots, windowsHost, leadingInsetPx }) => {
29+
memo(({ slots, windowsHost, leadingInsetPx, dragFiller }) => {
2530
if (!slots) return null;
2631

2732
return (
@@ -41,6 +46,7 @@ export const ChatPanelPublishedHeader: React.FC<ChatPanelPublishedHeaderProps> =
4146
<PublishedHeaderSlotsView
4247
slots={slots}
4348
paddingLeftClassName={leadingInsetPx === undefined ? undefined : ""}
49+
dragFiller={dragFiller}
4450
/>
4551
</div>
4652
);

0 commit comments

Comments
 (0)