mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-19 13:33:35 +08:00
Preserve tab reordering without losing title-bar drag fallback
The recent macOS title-bar drag fix marked the entire session tab strip as a native drag region. That restored window movement in the overlay title area, but it also intercepted the tab component's own HTML drag events and regressed manual tab reordering. This narrows the native drag surface to a small gutter beside the tabs while keeping the explicit empty-space startDragging fallback, and adds a focused regression test for drag-to-reorder. Constraint: Must preserve window dragging from non-tab title-bar space on macOS overlay windows Rejected: Keep the whole tab bar as a drag region | conflicts with tab-level drag-and-drop reordering Confidence: high Scope-risk: narrow Reversibility: clean Directive: Do not reapply data-tauri-drag-region to the full tab strip unless tab reordering is redesigned around a different drag mechanism Tested: bun run test -- src/components/layout/TabBar.test.tsx; bun run lint; bun run build Not-tested: Manual desktop runtime verification after this commit
This commit is contained in:
parent
eaa4a8435a
commit
5f86585c34
@ -149,7 +149,8 @@ describe('TabBar', () => {
|
||||
render(<TabBar />)
|
||||
})
|
||||
|
||||
expect(screen.getByTestId('tab-bar')).toHaveAttribute('data-tauri-drag-region')
|
||||
expect(screen.getByTestId('tab-bar')).not.toHaveAttribute('data-tauri-drag-region')
|
||||
expect(screen.getByTestId('tab-bar-drag-gutter')).toHaveAttribute('data-tauri-drag-region')
|
||||
})
|
||||
|
||||
it('starts dragging when clicking the empty tab-bar gutter', async () => {
|
||||
@ -214,4 +215,39 @@ describe('TabBar', () => {
|
||||
|
||||
expect(startDraggingMock).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('reorders tabs via drag and drop', async () => {
|
||||
const { TabBar } = await import('./TabBar')
|
||||
const { useTabStore } = await import('../../stores/tabStore')
|
||||
const { useChatStore } = await import('../../stores/chatStore')
|
||||
|
||||
useTabStore.setState({
|
||||
tabs: [
|
||||
{ sessionId: 'tab-1', title: 'First Session', type: 'session', status: 'idle' },
|
||||
{ sessionId: 'tab-2', title: 'Second Session', type: 'session', status: 'idle' },
|
||||
],
|
||||
activeTabId: 'tab-1',
|
||||
})
|
||||
useChatStore.setState({
|
||||
sessions: {},
|
||||
disconnectSession: vi.fn(),
|
||||
} as Partial<ReturnType<typeof useChatStore.getState>>)
|
||||
|
||||
await act(async () => {
|
||||
render(<TabBar />)
|
||||
})
|
||||
|
||||
const firstTab = screen.getByText('First Session').closest('[draggable="true"]')
|
||||
const secondTab = screen.getByText('Second Session').closest('[draggable="true"]')
|
||||
|
||||
expect(firstTab).toBeTruthy()
|
||||
expect(secondTab).toBeTruthy()
|
||||
|
||||
fireEvent.dragStart(firstTab!)
|
||||
fireEvent.dragOver(secondTab!)
|
||||
fireEvent.drop(secondTab!)
|
||||
fireEvent.dragEnd(firstTab!)
|
||||
|
||||
expect(useTabStore.getState().tabs.map((tab) => tab.sessionId)).toEqual(['tab-2', 'tab-1'])
|
||||
})
|
||||
})
|
||||
|
||||
@ -169,7 +169,6 @@ export function TabBar() {
|
||||
return (
|
||||
<div
|
||||
data-testid="tab-bar"
|
||||
data-tauri-drag-region
|
||||
className="flex items-stretch bg-[var(--color-surface-container)] min-h-[37px] select-none border-b border-[var(--color-border)]"
|
||||
>
|
||||
|
||||
@ -202,6 +201,15 @@ export function TabBar() {
|
||||
))}
|
||||
</div>
|
||||
|
||||
{isTauri && (
|
||||
<div
|
||||
data-testid="tab-bar-drag-gutter"
|
||||
data-tauri-drag-region
|
||||
aria-hidden="true"
|
||||
className={`flex-shrink-0 min-h-[37px] ${showWindowControls ? 'w-3' : 'w-4'}`}
|
||||
/>
|
||||
)}
|
||||
|
||||
{canScrollRight && (
|
||||
<button onClick={() => scroll('right')} className="flex-shrink-0 w-7 h-[37px] flex items-center justify-center text-[var(--color-text-tertiary)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-surface-hover)]">
|
||||
<span className="material-symbols-outlined text-[16px]">chevron_right</span>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user