Files
twenty/packages/twenty-front/src/modules/page-layout/hooks/useMovePageLayoutTab.ts
T
Baptiste Devessier fe4512f80c Add record page layout tabs editing (#18702)
- Fix duplication of tabs in dashboards that didn't open the duplicated
tab in the side panel: replaced the logic that used Math.round with an
algorithm that switches the positions of the elements. We will keep
relying on integers, but it will work well in all cases.
- Make dnd work with record page layouts, where there is a pinned tab
- Make tab movements work with pinned tab, too
- Allow user to set a tab as the pinned tab
- Make backend changes to be able to save tabs with `layoutMode`



https://github.com/user-attachments/assets/ce1130fa-71df-49ba-ba2f-6f971e15dd49

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-03-18 14:48:23 +00:00

84 lines
2.7 KiB
TypeScript

import { PageLayoutComponentInstanceContext } from '@/page-layout/states/contexts/PageLayoutComponentInstanceContext';
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
import { sortTabsByPosition } from '@/page-layout/utils/sortTabsByPosition';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useAtomComponentStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateCallbackState';
import { useStore } from 'jotai';
import { useCallback } from 'react';
export const useMovePageLayoutTab = (pageLayoutIdFromProps?: string) => {
const pageLayoutId = useAvailableComponentInstanceIdOrThrow(
PageLayoutComponentInstanceContext,
pageLayoutIdFromProps,
);
const pageLayoutDraftState = useAtomComponentStateCallbackState(
pageLayoutDraftComponentState,
pageLayoutId,
);
const store = useStore();
const moveLeft = useCallback(
(tabId: string) => {
store.set(pageLayoutDraftState, (prev) => {
const sorted = sortTabsByPosition(prev.tabs);
const index = sorted.findIndex((t) => t.id === tabId);
if (index <= 0) {
return prev;
}
const neighborId = sorted[index - 1].id;
const currentPosition = sorted[index].position;
const neighborPosition = sorted[index - 1].position;
return {
...prev,
tabs: prev.tabs.map((t) => {
if (t.id === tabId) {
return { ...t, position: neighborPosition };
}
if (t.id === neighborId) {
return { ...t, position: currentPosition };
}
return t;
}),
};
});
},
[pageLayoutDraftState, store],
);
const moveRight = useCallback(
(tabId: string) => {
store.set(pageLayoutDraftState, (prev) => {
const sorted = sortTabsByPosition(prev.tabs);
const index = sorted.findIndex((t) => t.id === tabId);
if (index < 0 || index >= sorted.length - 1) {
return prev;
}
const neighborId = sorted[index + 1].id;
const currentPosition = sorted[index].position;
const neighborPosition = sorted[index + 1].position;
return {
...prev,
tabs: prev.tabs.map((t) => {
if (t.id === tabId) {
return { ...t, position: neighborPosition };
}
if (t.id === neighborId) {
return { ...t, position: currentPosition };
}
return t;
}),
};
});
},
[pageLayoutDraftState, store],
);
return { moveLeft, moveRight };
};