584 Refactor Tabs (#11008)

Closes https://github.com/twentyhq/core-team-issues/issues/584

This PR:
- Migrates the component state `activeTabIdComponentState` from the
deprecated V1 version to V2.
- Allows the active tab state to be preserved during navigation inside
the side panel and reset when the side panel is closed.
- Allows the active tab state to be preserved when we open a record in
full page from the side panel


https://github.com/user-attachments/assets/f2329d7a-ea15-4bd8-81dc-e98ce11edbd0


https://github.com/user-attachments/assets/474bffd5-29e0-40ba-97f4-fa5e9be34dc2
This commit is contained in:
Raphaël Bosi
2025-03-19 16:53:22 +01:00
committed by GitHub
parent 0d40126a29
commit cfdb3f5778
37 changed files with 299 additions and 609 deletions

View File

@ -1,6 +1,7 @@
import { RecordShowRightDrawerActionMenu } from '@/action-menu/components/RecordShowRightDrawerActionMenu';
import { RecordShowRightDrawerOpenRecordButton } from '@/action-menu/components/RecordShowRightDrawerOpenRecordButton';
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
import { CommandMenuPageComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuPageComponentInstanceContext';
import { CardComponents } from '@/object-record/record-show/components/CardComponents';
import { FieldsCard } from '@/object-record/record-show/components/FieldsCard';
import { SummaryCard } from '@/object-record/record-show/components/SummaryCard';
@ -9,9 +10,13 @@ import { recordStoreFamilyState } from '@/object-record/record-store/states/reco
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { RightDrawerFooter } from '@/ui/layout/right-drawer/components/RightDrawerFooter';
import { ShowPageLeftContainer } from '@/ui/layout/show-page/components/ShowPageLeftContainer';
import { getShowPageTabListComponentId } from '@/ui/layout/show-page/utils/getShowPageTabListComponentId';
import { SingleTabProps, TabList } from '@/ui/layout/tab/components/TabList';
import { useTabList } from '@/ui/layout/tab/hooks/useTabList';
import { activeTabIdComponentState } from '@/ui/layout/tab/states/activeTabIdComponentState';
import { TabListComponentInstanceContext } from '@/ui/layout/tab/states/contexts/TabListComponentInstanceContext';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { useComponentInstanceStateContext } from '@/ui/utilities/state/component-state/hooks/useComponentInstanceStateContext';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import styled from '@emotion/styled';
import { useRecoilState } from 'recoil';
@ -41,8 +46,6 @@ const StyledContentContainer = styled.div<{ isInRightDrawer: boolean }>`
isInRightDrawer ? theme.spacing(16) : 0};
`;
export const TAB_LIST_COMPONENT_ID = 'show-page-right-tab-list';
type ShowPageSubContainerProps = {
layout?: RecordLayout;
tabs: SingleTabProps[];
@ -52,7 +55,6 @@ type ShowPageSubContainerProps = {
>;
isInRightDrawer?: boolean;
loading: boolean;
isNewRightDrawerItemLoading?: boolean;
};
export const ShowPageSubContainer = ({
@ -62,9 +64,18 @@ export const ShowPageSubContainer = ({
loading,
isInRightDrawer = false,
}: ShowPageSubContainerProps) => {
const tabListComponentId = `${TAB_LIST_COMPONENT_ID}-${isInRightDrawer}-${targetableObject.id}`;
const commandMenuPageComponentInstance = useComponentInstanceStateContext(
CommandMenuPageComponentInstanceContext,
);
const { activeTabId } = useTabList(tabListComponentId);
const tabListComponentId = getShowPageTabListComponentId({
pageId: commandMenuPageComponentInstance?.instanceId,
targetObjectId: targetableObject.id,
});
const activeTabId = useRecoilComponentValueV2(
activeTabIdComponentState,
tabListComponentId,
);
const isMobile = useIsMobile();
@ -109,7 +120,9 @@ export const ShowPageSubContainer = ({
layout && !layout.hideSummaryAndFields && !isMobile && !isInRightDrawer;
return (
<>
<TabListComponentInstanceContext.Provider
value={{ instanceId: tabListComponentId }}
>
{displaySummaryAndFields && (
<ShowPageLeftContainer forceMobile={isMobile}>
{summaryCard}
@ -121,9 +134,9 @@ export const ShowPageSubContainer = ({
<StyledTabList
behaveAsLinks={!isInRightDrawer}
loading={loading}
tabListInstanceId={tabListComponentId}
tabs={tabs}
isInRightDrawer={isInRightDrawer}
componentInstanceId={tabListComponentId}
/>
</StyledTabListContainer>
{(isMobile || isInRightDrawer) && summaryCard}
@ -142,6 +155,6 @@ export const ShowPageSubContainer = ({
/>
)}
</StyledShowPageRightContainer>
</>
</TabListComponentInstanceContext.Provider>
);
};

View File

@ -0,0 +1 @@
export const SHOW_PAGE_RIGHT_TAB_LIST = 'show-page-right-tab-list';

View File

@ -0,0 +1,12 @@
import { SHOW_PAGE_RIGHT_TAB_LIST } from '@/ui/layout/show-page/constants/ShowPageTabListComponentId';
export const getShowPageTabListComponentId = ({
pageId,
targetObjectId,
}: {
pageId?: string;
targetObjectId: string;
}): string => {
const id = pageId || targetObjectId;
return `${SHOW_PAGE_RIGHT_TAB_LIST}-${id}`;
};