Baptiste Devessier
2025-12-05 16:10:08 +01:00
committed by GitHub
parent 58b8b49d1d
commit 2466d81ace
8 changed files with 130 additions and 134 deletions
@@ -6,23 +6,10 @@ import { usePageLayoutContentContext } from '@/page-layout/contexts/PageLayoutCo
import { usePageLayoutTabWithVisibleWidgetsOrThrow } from '@/page-layout/hooks/usePageLayoutTabWithVisibleWidgetsOrThrow';
import { useReorderPageLayoutWidgets } from '@/page-layout/hooks/useReorderPageLayoutWidgets';
import { isPageLayoutInEditModeComponentState } from '@/page-layout/states/isPageLayoutInEditModeComponentState';
import { useIsInPinnedTab } from '@/page-layout/widgets/hooks/useIsInPinnedTab';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import styled from '@emotion/styled';
import { FeatureFlagKey } from '~/generated/graphql';
const StyledContainer = styled.div<{ isInPinnedTab: boolean }>`
background: ${({ theme }) => theme.background.primary};
box-sizing: border-box;
flex: 1;
min-height: 100%;
position: relative;
width: 100%;
padding: ${({ theme, isInPinnedTab }) =>
isInPinnedTab ? 0 : theme.spacing(2)};
`;
export const PageLayoutContent = () => {
const isRecordPageEnabled = useIsFeatureEnabled(
FeatureFlagKey.IS_RECORD_PAGE_LAYOUT_ENABLED,
@@ -39,7 +26,6 @@ export const PageLayoutContent = () => {
const activeTab = usePageLayoutTabWithVisibleWidgetsOrThrow(tabId);
const { layoutMode } = usePageLayoutContentContext();
const { isInPinnedTab } = useIsInPinnedTab();
const isCanvasLayout = isRecordPageEnabled && layoutMode === 'canvas';
const isVerticalList = isRecordPageEnabled && layoutMode === 'vertical-list';
@@ -49,17 +35,13 @@ export const PageLayoutContent = () => {
}
if (isVerticalList) {
return (
<StyledContainer isInPinnedTab={isInPinnedTab}>
{isPageLayoutInEditMode ? (
<PageLayoutVerticalListEditor
widgets={activeTab.widgets}
onReorder={reorderWidgets}
/>
) : (
<PageLayoutVerticalListViewer widgets={activeTab.widgets} />
)}
</StyledContainer>
return isPageLayoutInEditMode ? (
<PageLayoutVerticalListEditor
widgets={activeTab.widgets}
onReorder={reorderWidgets}
/>
) : (
<PageLayoutVerticalListViewer widgets={activeTab.widgets} />
);
}
@@ -36,7 +36,6 @@ import {
import { isDefined } from 'twenty-shared/utils';
const StyledGridContainer = styled.div`
background: ${({ theme }) => theme.background.primary};
box-sizing: border-box;
flex: 1;
min-height: 100%;
@@ -139,65 +138,61 @@ export const PageLayoutGridLayout = ({ tabId }: PageLayoutGridLayoutProps) => {
);
return (
<>
<StyledGridContainer ref={gridContainerRef}>
{isPageLayoutInEditMode && (
<>
<PageLayoutGridOverlay />
<PageLayoutGridLayoutDragSelector
gridContainerRef={gridContainerRef}
/>
</>
)}
<StyledGridContainer ref={gridContainerRef}>
{isPageLayoutInEditMode && (
<>
<PageLayoutGridOverlay />
<PageLayoutGridLayoutDragSelector
gridContainerRef={gridContainerRef}
/>
</>
)}
<ResponsiveGridLayout
className="layout"
layouts={layouts}
breakpoints={PAGE_LAYOUT_CONFIG.breakpoints}
cols={PAGE_LAYOUT_CONFIG.columns}
rowHeight={PAGE_LAYOUT_GRID_ROW_HEIGHT}
maxCols={12}
containerPadding={[0, 0]}
margin={[PAGE_LAYOUT_GRID_MARGIN, PAGE_LAYOUT_GRID_MARGIN]}
isDraggable={isPageLayoutInEditMode}
isResizable={isPageLayoutInEditMode}
draggableHandle=".drag-handle"
compactType="vertical"
preventCollision={false}
resizeHandle={
isPageLayoutInEditMode ? <PageLayoutGridResizeHandle /> : undefined
}
resizeHandles={['n', 's', 'e', 'w', 'ne', 'nw', 'se', 'sw']}
onDragStart={(_layout, _oldItem, newItem) => {
setDraggingWidgetId(newItem.i);
}}
onDragStop={() => {
setDraggingWidgetId(null);
}}
onResizeStart={(_layout, _oldItem, newItem) => {
setResizingWidgetId(newItem.i);
}}
onResizeStop={() => {
setResizingWidgetId(null);
}}
onLayoutChange={handleLayoutChangeWithoutPendingPlaceholder}
onBreakpointChange={(newBreakpoint) =>
setPageLayoutCurrentBreakpoint(
newBreakpoint as PageLayoutBreakpoint,
)
}
>
{gridLayoutItems.map((item) => (
<ReactGridLayoutCardWrapper key={item.id}>
{item.type === 'placeholder' ? (
<WidgetPlaceholder />
) : (
<WidgetRenderer widget={item.widget} />
)}
</ReactGridLayoutCardWrapper>
))}
</ResponsiveGridLayout>
</StyledGridContainer>
</>
<ResponsiveGridLayout
className="layout"
layouts={layouts}
breakpoints={PAGE_LAYOUT_CONFIG.breakpoints}
cols={PAGE_LAYOUT_CONFIG.columns}
rowHeight={PAGE_LAYOUT_GRID_ROW_HEIGHT}
maxCols={12}
containerPadding={[0, 0]}
margin={[PAGE_LAYOUT_GRID_MARGIN, PAGE_LAYOUT_GRID_MARGIN]}
isDraggable={isPageLayoutInEditMode}
isResizable={isPageLayoutInEditMode}
draggableHandle=".drag-handle"
compactType="vertical"
preventCollision={false}
resizeHandle={
isPageLayoutInEditMode ? <PageLayoutGridResizeHandle /> : undefined
}
resizeHandles={['n', 's', 'e', 'w', 'ne', 'nw', 'se', 'sw']}
onDragStart={(_layout, _oldItem, newItem) => {
setDraggingWidgetId(newItem.i);
}}
onDragStop={() => {
setDraggingWidgetId(null);
}}
onResizeStart={(_layout, _oldItem, newItem) => {
setResizingWidgetId(newItem.i);
}}
onResizeStop={() => {
setResizingWidgetId(null);
}}
onLayoutChange={handleLayoutChangeWithoutPendingPlaceholder}
onBreakpointChange={(newBreakpoint) =>
setPageLayoutCurrentBreakpoint(newBreakpoint as PageLayoutBreakpoint)
}
>
{gridLayoutItems.map((item) => (
<ReactGridLayoutCardWrapper key={item.id}>
{item.type === 'placeholder' ? (
<WidgetPlaceholder />
) : (
<WidgetRenderer widget={item.widget} />
)}
</ReactGridLayoutCardWrapper>
))}
</ResponsiveGridLayout>
</StyledGridContainer>
);
};
@@ -6,9 +6,21 @@ import { usePageLayoutTabWithVisibleWidgetsOrThrow } from '@/page-layout/hooks/u
import { getTabLayoutMode } from '@/page-layout/utils/getTabLayoutMode';
import { useLayoutRenderingContext } from '@/ui/layout/contexts/LayoutRenderingContext';
import { useTargetRecord } from '@/ui/layout/contexts/useTargetRecord';
import { ShowPageLeftContainer } from '@/ui/layout/show-page/components/ShowPageLeftContainer';
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
import styled from '@emotion/styled';
import { PageLayoutType } from '~/generated/graphql';
const StyledContainer = styled.div`
background: ${({ theme }) => theme.background.secondary};
border-bottom-left-radius: 8px;
border-right: ${({ theme }) => `1px solid ${theme.border.color.medium}`};
border-top-left-radius: 8px;
box-sizing: border-box;
display: grid;
grid-template-rows: auto 1fr;
height: 100%;
`;
type PageLayoutLeftPanelProps = {
pinnedLeftTabId: string;
};
@@ -31,7 +43,7 @@ export const PageLayoutLeftPanel = ({
});
return (
<ShowPageLeftContainer>
<StyledContainer>
<SummaryCard
objectNameSingular={targetRecordIdentifier.targetObjectNameSingular}
objectRecordId={targetRecordIdentifier.id}
@@ -44,8 +56,14 @@ export const PageLayoutLeftPanel = ({
layoutMode,
}}
>
<PageLayoutContent />
<ScrollWrapper
componentInstanceId={`page-layout-left-panel-${pinnedLeftTabId}`}
defaultEnableXScroll={false}
defaultEnableYScroll={true}
>
<PageLayoutContent />
</ScrollWrapper>
</PageLayoutContentProvider>
</ShowPageLeftContainer>
</StyledContainer>
);
};
@@ -4,6 +4,7 @@ import { PageLayoutLeftPanel } from '@/page-layout/components/PageLayoutLeftPane
import { PageLayoutTabHeader } from '@/page-layout/components/PageLayoutTabHeader';
import { PageLayoutTabList } from '@/page-layout/components/PageLayoutTabList';
import { PageLayoutTabListEffect } from '@/page-layout/components/PageLayoutTabListEffect';
import { PAGE_LAYOUT_LEFT_PANEL_CONTAINER_WIDTH } from '@/page-layout/constants/PageLayoutLeftPanelContainerWidth';
import { useCreatePageLayoutTab } from '@/page-layout/hooks/useCreatePageLayoutTab';
import { useCurrentPageLayout } from '@/page-layout/hooks/useCurrentPageLayout';
import { useReorderPageLayoutTabs } from '@/page-layout/hooks/useReorderPageLayoutTabs';
@@ -16,7 +17,6 @@ import { getTabsByDisplayMode } from '@/page-layout/utils/getTabsByDisplayMode';
import { getTabsWithVisibleWidgets } from '@/page-layout/utils/getTabsWithVisibleWidgets';
import { sortTabsByPosition } from '@/page-layout/utils/sortTabsByPosition';
import { useLayoutRenderingContext } from '@/ui/layout/contexts/LayoutRenderingContext';
import { ShowPageContainer } from '@/ui/layout/page/components/ShowPageContainer';
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
@@ -25,22 +25,19 @@ import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state
import styled from '@emotion/styled';
import { isDefined } from 'twenty-shared/utils';
const StyledContainer = styled.div<{ hasPinnedTab: boolean }>`
display: grid;
grid-template-columns: ${({ hasPinnedTab }) =>
hasPinnedTab ? `${PAGE_LAYOUT_LEFT_PANEL_CONTAINER_WIDTH}px 1fr` : '1fr'};
grid-template-rows: minmax(0, 1fr);
height: 100%;
width: 100%;
`;
const StyledTabsAndDashboardContainer = styled.div`
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
overflow: hidden;
background: ${({ theme }) => theme.background.primary};
`;
const StyledShowPageRightContainer = styled.div`
display: flex;
flex-direction: column;
height: 100%;
justify-content: start;
width: 100%;
overflow: auto;
`;
const StyledPageLayoutTabList = styled(PageLayoutTabList)`
@@ -107,44 +104,43 @@ export const PageLayoutRendererContent = () => {
const sortedTabs = sortTabsByPosition(tabsToRenderInTabList);
return (
<ShowPageContainer>
<StyledContainer hasPinnedTab={isDefined(pinnedLeftTab)}>
{isDefined(pinnedLeftTab) && (
<PageLayoutLeftPanel pinnedLeftTabId={pinnedLeftTab.id} />
)}
<StyledShowPageRightContainer>
<StyledTabsAndDashboardContainer>
<PageLayoutTabListEffect
<StyledTabsAndDashboardContainer>
<PageLayoutTabListEffect
tabs={sortedTabs}
componentInstanceId={tabListInstanceId}
defaultTabIdToFocusOnMobileAndSidePanel={
currentPageLayout.defaultTabIdToFocusOnMobileAndSidePanel
}
/>
{(sortedTabs.length > 1 || isPageLayoutInEditMode) && (
<StyledPageLayoutTabList
tabs={sortedTabs}
behaveAsLinks={false}
componentInstanceId={tabListInstanceId}
defaultTabIdToFocusOnMobileAndSidePanel={
currentPageLayout.defaultTabIdToFocusOnMobileAndSidePanel
}
onAddTab={handleAddTab}
isReorderEnabled={isPageLayoutInEditMode}
onReorder={isPageLayoutInEditMode ? reorderTabs : undefined}
/>
{(sortedTabs.length > 1 || isPageLayoutInEditMode) && (
<StyledPageLayoutTabList
tabs={sortedTabs}
behaveAsLinks={false}
componentInstanceId={tabListInstanceId}
onAddTab={handleAddTab}
isReorderEnabled={isPageLayoutInEditMode}
onReorder={isPageLayoutInEditMode ? reorderTabs : undefined}
/>
)}
)}
<PageLayoutTabHeader />
<StyledScrollWrapper
componentInstanceId={getScrollWrapperInstanceIdFromPageLayoutId(
currentPageLayout.id,
)}
defaultEnableXScroll={false}
>
{isDefined(activeTabId) && (
<PageLayoutMainContent tabId={activeTabId} />
)}
</StyledScrollWrapper>
</StyledTabsAndDashboardContainer>
</StyledShowPageRightContainer>
</ShowPageContainer>
<PageLayoutTabHeader />
<StyledScrollWrapper
componentInstanceId={getScrollWrapperInstanceIdFromPageLayoutId(
currentPageLayout.id,
)}
defaultEnableXScroll={false}
>
{isDefined(activeTabId) && (
<PageLayoutMainContent tabId={activeTabId} />
)}
</StyledScrollWrapper>
</StyledTabsAndDashboardContainer>
</StyledContainer>
);
};
@@ -15,6 +15,7 @@ const StyledVerticalListContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
padding: ${({ theme }) => theme.spacing(2)};
`;
const StyledDraggableWrapper = styled.div<{ isDragging: boolean }>`
@@ -6,6 +6,7 @@ const StyledVerticalListContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
padding: ${({ theme }) => theme.spacing(2)};
`;
type PageLayoutVerticalListViewerProps = {
@@ -0,0 +1 @@
export const PAGE_LAYOUT_LEFT_PANEL_CONTAINER_WIDTH = 348;
@@ -1,6 +1,7 @@
import styled from '@emotion/styled';
import { type ReactNode } from 'react';
import { PAGE_LAYOUT_LEFT_PANEL_CONTAINER_WIDTH } from '@/page-layout/constants/PageLayoutLeftPanelContainerWidth';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
@@ -20,7 +21,8 @@ const StyledOuterContainer = styled.div<{ isMobile: boolean }>`
const StyledInnerContainer = styled.div<{ isMobile: boolean }>`
display: flex;
flex-direction: column;
width: ${({ isMobile }) => (isMobile ? `100%` : '348px')};
width: ${({ isMobile }) =>
isMobile ? `100%` : `${PAGE_LAYOUT_LEFT_PANEL_CONTAINER_WIDTH}px`};
`;
const StyledIntermediateContainer = styled.div`