Files
kandev/apps/web/components/task/use-tab-maximize.ts
T
José Almeida 3e676e3bb2 feat(web): double-click tab to toggle maximize (#823)
* feat(web): double-click tab to toggle maximize

Adds a dblclick gesture on dockview tabs that toggles maximize/restore on
the containing group, mirroring the existing maximize button. Preview tabs
keep their promote-to-pin shortcut: first dblclick pins, then dblclick
maximizes. Sidebar group is excluded.

* fix(web): add cursor-pointer to tab wrappers for consistency

* fix(web): add cursor-pointer to plan-tab wrapper

* fix(web): make tab dblclick maximize resilient to layout rebuild

Refactor the dblclick-to-maximize handler so it reads the panel's group ID
and store state at call time instead of from a render-time closure, and
guards against firing while the dockview store is mid-layout-restore.

This addresses oscillation when double-clicking a session tab on a task
that has multiple sessions: the maximize call now stops event propagation,
respects isRestoringLayout, and always uses the live api.group.id, so it
remains correct even after dockview rebuilds groups via fromJSON.
2026-05-05 13:55:46 +01:00

38 lines
1.3 KiB
TypeScript

"use client";
import { useCallback } from "react";
import type { DockviewPanelApi } from "dockview-react";
import { useDockviewStore } from "@/lib/state/dockview-store";
/**
* Returns an `onDoubleClick` handler that toggles the maximize state for the
* dockview group containing the given panel. No-ops for the sidebar group
* (which has no maximize button either) and while the dockview store is in
* the middle of restoring a layout (guards against rapid double-firing on
* back-to-back dblclicks during the maximize/restore animation frame).
*
* Reads `api.group.id` and store state at call time rather than render time
* so the toggle remains correct after dockview rebuilds groups via fromJSON.
*/
export function useTabMaximizeOnDoubleClick(
api: Pick<DockviewPanelApi, "group">,
): (event: React.MouseEvent) => void {
return useCallback(
(event) => {
event.stopPropagation();
event.preventDefault();
const groupId = api.group?.id;
if (!groupId) return;
const state = useDockviewStore.getState();
if (state.isRestoringLayout) return;
if (groupId === state.sidebarGroupId) return;
if (state.preMaximizeLayout) {
state.exitMaximizedLayout();
} else {
state.maximizeGroup(groupId);
}
},
[api],
);
}