diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/display/components/ChipFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/display/components/ChipFieldDisplay.tsx
index 6f3639143c..4b921623d1 100644
--- a/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/display/components/ChipFieldDisplay.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/display/components/ChipFieldDisplay.tsx
@@ -1,7 +1,5 @@
import { RecordChip } from '@/object-record/components/RecordChip';
import { useChipFieldDisplay } from '@/object-record/record-field/ui/meta-types/hooks/useChipFieldDisplay';
-import { isRecordTableScrolledLeftComponentState } from '@/object-record/record-table/states/isRecordTableScrolledLeftComponentState';
-import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { isDefined } from 'twenty-shared/utils';
import { ChipSize } from 'twenty-ui/components';
import { useIsMobile } from 'twenty-ui/utilities';
@@ -18,12 +16,9 @@ export const ChipFieldDisplay = () => {
} = useChipFieldDisplay();
const isMobile = useIsMobile();
- const isRecordTableScrolledLeftComponent = useRecoilComponentValue(
- isRecordTableScrolledLeftComponentState,
- );
- const isLabelIdentifierCompact =
- isMobile && !isRecordTableScrolledLeftComponent;
+ // TODO: reimplement scrolled horizontally here.
+ const isLabelIdentifierCompact = isMobile;
if (!isDefined(recordValue)) {
return null;
diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableContent.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableContent.tsx
index 803c142a56..55d2dfdc89 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableContent.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableContent.tsx
@@ -1,6 +1,6 @@
import { RecordTableStickyBottomEffect } from '@/object-record/record-table/components/RecordTableStickyBottomEffect';
import { RecordTableStickyEffect } from '@/object-record/record-table/components/RecordTableStickyEffect';
-import { StyledTable } from '@/object-record/record-table/components/RecordTableStyles';
+import { StyledTableDiv } from '@/object-record/record-table/components/RecordTableStyles';
import { RecordTableNoRecordGroupBody } from '@/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBody';
import { RecordTableRecordGroupsBody } from '@/object-record/record-table/record-table-body/components/RecordTableRecordGroupsBody';
import { RecordTableHeader } from '@/object-record/record-table/record-table-header/components/RecordTableHeader';
@@ -12,7 +12,7 @@ import styled from '@emotion/styled';
import { useRef, useState } from 'react';
import { useRecoilCallback } from 'recoil';
-const StyledTableWithPointerEvents = styled(StyledTable)<{
+const StyledTableWithPointerEvents = styled(StyledTableDiv)<{
isDragging: boolean;
}>`
& > * {
diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableEmpty.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableEmpty.tsx
index 8209cbb2ad..a92d21dac5 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableEmpty.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableEmpty.tsx
@@ -1,4 +1,4 @@
-import { StyledTable } from '@/object-record/record-table/components/RecordTableStyles';
+import { StyledTableDiv } from '@/object-record/record-table/components/RecordTableStyles';
import { RecordTableEmptyState } from '@/object-record/record-table/empty-state/components/RecordTableEmptyState';
import { RecordTableHeader } from '@/object-record/record-table/record-table-header/components/RecordTableHeader';
import styled from '@emotion/styled';
@@ -14,9 +14,9 @@ export interface RecordTableEmptyProps {
export const RecordTableEmpty = ({ tableBodyRef }: RecordTableEmptyProps) => (
-
+
-
+
);
diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableStickyEffect.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableStickyEffect.tsx
index 4b9ba847a3..5f51863498 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableStickyEffect.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableStickyEffect.tsx
@@ -1,6 +1,7 @@
import { useEffect } from 'react';
-import { isRecordTableScrolledLeftComponentState } from '@/object-record/record-table/states/isRecordTableScrolledLeftComponentState';
+import { isRecordTableScrolledHorizontallyComponentState } from '@/object-record/record-table/states/isRecordTableScrolledHorizontallyComponentState';
+import { isRecordTableScrolledVerticallyComponentState } from '@/object-record/record-table/states/isRecordTableScrolledVerticallyComponentState';
import { scrollWrapperScrollLeftComponentState } from '@/ui/utilities/scroll/states/scrollWrapperScrollLeftComponentState';
import { scrollWrapperScrollTopComponentState } from '@/ui/utilities/scroll/states/scrollWrapperScrollTopComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
@@ -11,7 +12,13 @@ export const RecordTableStickyEffect = () => {
scrollWrapperScrollTopComponentState,
);
+ const setIsRecordTableScrolledVertically = useSetRecoilComponentState(
+ isRecordTableScrolledVerticallyComponentState,
+ );
+
useEffect(() => {
+ setIsRecordTableScrolledVertically(scrollTop > 0);
+
if (scrollTop > 0) {
document
.getElementById('record-table-header')
@@ -21,18 +28,19 @@ export const RecordTableStickyEffect = () => {
.getElementById('record-table-header')
?.classList.remove('header-sticky');
}
- }, [scrollTop]);
+ }, [scrollTop, setIsRecordTableScrolledVertically]);
const scrollLeft = useRecoilComponentValue(
scrollWrapperScrollLeftComponentState,
);
- const setIsRecordTableScrolledLeft = useSetRecoilComponentState(
- isRecordTableScrolledLeftComponentState,
+ const setIsRecordTableScrolledHorizontally = useSetRecoilComponentState(
+ isRecordTableScrolledHorizontallyComponentState,
);
useEffect(() => {
- setIsRecordTableScrolledLeft(scrollLeft === 0);
+ setIsRecordTableScrolledHorizontally(scrollLeft > 0);
+
if (scrollLeft > 0) {
document
.getElementById('record-table-body')
@@ -54,7 +62,7 @@ export const RecordTableStickyEffect = () => {
.getElementById('record-table-footer')
?.classList.remove('first-columns-sticky');
}
- }, [scrollLeft, setIsRecordTableScrolledLeft]);
+ }, [scrollLeft, setIsRecordTableScrolledHorizontally]);
return <>>;
};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableStyles.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableStyles.tsx
index bcf481903b..4d67f8eb86 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableStyles.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableStyles.tsx
@@ -1,9 +1,8 @@
import styled from '@emotion/styled';
-export const StyledTable = styled.table`
+export const StyledTableDiv = styled.div`
border-radius: ${({ theme }) => theme.border.radius.sm};
border-spacing: 0;
- table-layout: fixed;
width: 100%;
.footer-sticky tr:nth-last-of-type(2) td {
diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableWithWrappers.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableWithWrappers.tsx
index 6cd4f31456..9d4967aef6 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableWithWrappers.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableWithWrappers.tsx
@@ -17,7 +17,7 @@ const StyledTableContainer = styled.div`
display: flex;
flex-direction: column;
position: relative;
- width: 100%;
+ width: fit-content;
height: 100%;
`;
diff --git a/packages/twenty-front/src/modules/object-record/record-table/constants/TableZIndex.ts b/packages/twenty-front/src/modules/object-record/record-table/constants/TableZIndex.ts
index 662a488b95..c717959611 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/constants/TableZIndex.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/constants/TableZIndex.ts
@@ -1,17 +1,37 @@
export const TABLE_Z_INDEX = {
base: 1,
cell: {
- default: 1,
- sticky: 4,
- editMode: 6,
+ default: 3,
+ sticky: 10,
+ editMode: 20,
},
footer: {
- default: 4,
- stickyColumn: 5,
+ default: 12,
+ stickyColumn: 20,
},
- header: {
- default: 6,
- stickyColumn: 10,
+ noScrollAtAll: {
+ hoverPortalCell: 17,
+ headerRow: 13,
+ headerColumnsSticky: 16,
+ headerColumnsNormal: 15,
+ },
+ scrolledBothVerticallyAndHorizontally: {
+ headerColumnsSticky: 13,
+ headerColumnsNormal: 12,
+ headerRow: 11,
+ hoverPortalCell: 2,
+ },
+ scrolledHorizontallyOnly: {
+ headerColumnsSticky: 13,
+ headerColumnsNormal: 12,
+ headerRow: 11,
+ hoverPortalCell: 9,
+ },
+ scrolledVerticallyOnly: {
+ headerColumnsSticky: 14,
+ headerColumnsNormal: 13,
+ headerRow: 12,
+ hoverPortalCell: 11,
},
columnGrip: 30,
};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBody.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBody.tsx
index e9bc21fde5..e7d8ecc7a7 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBody.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBody.tsx
@@ -1,38 +1,32 @@
import styled from '@emotion/styled';
import { TABLE_Z_INDEX } from '@/object-record/record-table/constants/TableZIndex';
+import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
const StyledTbody = styled.tbody`
- &.first-columns-sticky {
- td:nth-of-type(1) {
- position: sticky;
- left: 0;
- z-index: ${TABLE_Z_INDEX.cell.sticky};
- transition: transform 0.3s ease;
- }
- td:nth-of-type(2) {
- position: sticky;
- left: 11px;
- z-index: ${TABLE_Z_INDEX.cell.sticky};
- transition: transform 0.3s ease;
- }
- tr:not(:last-child) td:nth-of-type(3) {
- // Last row is aggregate footer
- position: sticky;
- left: 39px;
- z-index: ${TABLE_Z_INDEX.cell.sticky};
- transition: transform 0.3s ease;
+ // TODO: re-implement horizontal scroll here after table have been refactored to divs
+ td:nth-of-type(1) {
+ position: sticky;
+ left: 0px;
+ z-index: ${TABLE_Z_INDEX.cell.sticky};
+ }
- &:not(.disable-shadow)::after {
- content: '';
- position: absolute;
- top: -1px;
- height: calc(100% + 2px);
- width: 4px;
- right: 0px;
- box-shadow: ${({ theme }) => theme.boxShadow.light};
- clip-path: inset(0px -4px 0px 0px);
- }
+ td:nth-of-type(2) {
+ position: sticky;
+ left: 16px;
+ z-index: ${TABLE_Z_INDEX.cell.sticky};
+ }
+
+ tr:not(:last-child) td:nth-of-type(3) {
+ position: sticky;
+ left: 49px;
+ z-index: ${TABLE_Z_INDEX.cell.sticky};
+ }
+
+ td:nth-of-type(3) {
+ @media (max-width: ${MOBILE_VIEWPORT}px) {
+ width: ${38}px;
+ max-width: ${38}px;
}
}
`;
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyDroppable.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyDroppable.tsx
index 0593f5e6f3..bbadbab21a 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyDroppable.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyDroppable.tsx
@@ -2,10 +2,19 @@ import { RecordTableBody } from '@/object-record/record-table/record-table-body/
import { RecordTableBodyDroppableContextProvider } from '@/object-record/record-table/record-table-body/contexts/RecordTableBodyDroppableContext';
import { recordTableHoverPositionComponentState } from '@/object-record/record-table/states/recordTableHoverPositionComponentState';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
+import styled from '@emotion/styled';
import { Droppable } from '@hello-pangea/dnd';
import { type ReactNode, useState } from 'react';
import { v4 } from 'uuid';
+const StyledTable = styled.table`
+ table-layout: fixed;
+
+ border-radius: ${({ theme }) => theme.border.radius.sm};
+ border-spacing: 0;
+ width: 100%;
+`;
+
type RecordTableBodyDroppableProps = {
children: ReactNode;
recordGroupId?: string;
@@ -30,19 +39,21 @@ export const RecordTableBodyDroppable = ({
isDropDisabled={isDropDisabled}
>
{(provided) => (
- setRecordTableHoverPosition(null)}
- >
-
+ setRecordTableHoverPosition(null)}
>
- {children}
-
-
+
+ {children}
+
+
+
)}
);
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellGrip.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellGrip.tsx
index a7da7822b6..28e12c2884 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellGrip.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellGrip.tsx
@@ -5,7 +5,7 @@ import { useRecordTableRowDraggableContextOrThrow } from '@/object-record/record
import { RecordTableTd } from '@/object-record/record-table/record-table-cell/components/RecordTableTd';
import { IconListViewGrip } from 'twenty-ui/input';
-export const TABLE_CELL_GRIP_WIDTH = '16px';
+export const TABLE_CELL_GRIP_WIDTH = 16;
const StyledContainer = styled.div`
height: 32px;
@@ -40,6 +40,7 @@ export const RecordTableCellGrip = () => {
data-select-disable
hasRightBorder={false}
hasBottomBorder={false}
+ width={TABLE_CELL_GRIP_WIDTH}
>
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellHoveredPortal.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellHoveredPortal.tsx
index c968180845..75db4572cb 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellHoveredPortal.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellHoveredPortal.tsx
@@ -6,12 +6,15 @@ import styled from '@emotion/styled';
import { FieldDisplay } from '@/object-record/record-field/ui/components/FieldDisplay';
import { FieldContext } from '@/object-record/record-field/ui/contexts/FieldContext';
import { useIsFieldInputOnly } from '@/object-record/record-field/ui/hooks/useIsFieldInputOnly';
+import { TABLE_Z_INDEX } from '@/object-record/record-table/constants/TableZIndex';
import { useRecordTableRowContextOrThrow } from '@/object-record/record-table/contexts/RecordTableRowContext';
import { RecordTableCellDisplayMode } from '@/object-record/record-table/record-table-cell/components/RecordTableCellDisplayMode';
import { RecordTableCellEditButton } from '@/object-record/record-table/record-table-cell/components/RecordTableCellEditButton';
import { RecordTableCellEditMode } from '@/object-record/record-table/record-table-cell/components/RecordTableCellEditMode';
import { RecordTableCellFieldInput } from '@/object-record/record-table/record-table-cell/components/RecordTableCellFieldInput';
import { isRecordTableRowActiveComponentFamilyState } from '@/object-record/record-table/states/isRecordTableRowActiveComponentFamilyState';
+import { isRecordTableScrolledHorizontallyComponentState } from '@/object-record/record-table/states/isRecordTableScrolledHorizontallyComponentState';
+import { isRecordTableScrolledVerticallyComponentState } from '@/object-record/record-table/states/isRecordTableScrolledVerticallyComponentState';
import { useRecoilComponentFamilyValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue';
import { useContext } from 'react';
import { BORDER_COMMON } from 'twenty-ui/theme';
@@ -20,6 +23,7 @@ import { useIsMobile } from 'twenty-ui/utilities';
const StyledRecordTableCellHoveredPortalContent = styled.div<{
isReadOnly: boolean;
isRowActive: boolean;
+ zIndex: number;
}>`
align-items: center;
background: ${({ theme }) => theme.background.transparent.secondary};
@@ -42,6 +46,8 @@ const StyledRecordTableCellHoveredPortalContent = styled.div<{
position: relative;
user-select: none;
+
+ z-index: ${({ zIndex }) => zIndex};
`;
const RecordTableCellHoveredPortalContent = () => {
@@ -67,10 +73,28 @@ const RecordTableCellHoveredPortalContent = () => {
rowIndex,
);
+ const isRecordTableScrolledHorizontally = useRecoilComponentValue(
+ isRecordTableScrolledHorizontallyComponentState,
+ );
+
+ const isRecordTableScrolledVertically = useRecoilComponentValue(
+ isRecordTableScrolledVerticallyComponentState,
+ );
+
+ const computedZIndex =
+ isRecordTableScrolledHorizontally && isRecordTableScrolledVertically
+ ? TABLE_Z_INDEX.scrolledBothVerticallyAndHorizontally.hoverPortalCell
+ : isRecordTableScrolledHorizontally
+ ? TABLE_Z_INDEX.scrolledHorizontallyOnly.hoverPortalCell
+ : isRecordTableScrolledVertically
+ ? TABLE_Z_INDEX.scrolledVerticallyOnly.hoverPortalCell
+ : TABLE_Z_INDEX.noScrollAtAll.hoverPortalCell;
+
return (
{isFieldInputOnly ? (
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableTd.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableTd.tsx
index 376f946174..b20e29c745 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableTd.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableTd.tsx
@@ -1,22 +1,23 @@
import { type DraggableProvidedDragHandleProps } from '@hello-pangea/dnd';
import { styled } from '@linaria/react';
import { type ReactNode, useContext } from 'react';
-import { MOBILE_VIEWPORT, ThemeContext } from 'twenty-ui/theme';
+import { ThemeContext } from 'twenty-ui/theme';
-export const RECORD_TABLE_TD_WIDTH = '32px';
+export const DEFAULT_RECORD_TABLE_TD_WIDTH = 32;
const StyledTd = styled.td<{
backgroundColor: string;
borderColor: string;
isDragging?: boolean;
fontColor: string;
- sticky?: boolean;
- freezeFirstColumns?: boolean;
- left?: number;
hasRightBorder?: boolean;
hasBottomBorder?: boolean;
- width?: number;
+ width: number;
}>`
+ min-width: ${({ width }) => width}px;
+ width: ${({ width }) => width}px;
+ max-width: ${({ width }) => width}px;
+
border-bottom: 1px solid
${({ borderColor, hasBottomBorder, isDragging }) =>
hasBottomBorder && !isDragging ? borderColor : 'transparent'};
@@ -26,46 +27,31 @@ const StyledTd = styled.td<{
hasRightBorder && !isDragging ? `1px solid ${borderColor}` : 'none'};
padding: 0;
- transition: transform 0.3s ease;
text-align: left;
background: ${({ backgroundColor, isDragging }) =>
isDragging ? 'transparent' : backgroundColor};
- ${({ freezeFirstColumns }) =>
- freezeFirstColumns
- ? `@media (max-width: ${MOBILE_VIEWPORT}px) {
- width: ${RECORD_TABLE_TD_WIDTH};
- max-width: ${RECORD_TABLE_TD_WIDTH};
- }`
- : ''}
+ // TODO: reimplement horizontal scroll here once we have refactored body with divs
`;
export const RecordTableTd = ({
children,
isSelected,
isDragging,
- sticky,
- freezeFirstColumns,
- left,
hasRightBorder = true,
hasBottomBorder = true,
- width,
- colSpan,
+ width = DEFAULT_RECORD_TABLE_TD_WIDTH,
...dragHandleProps
}: {
className?: string;
children?: ReactNode;
isSelected?: boolean;
isDragging?: boolean;
- sticky?: boolean;
- freezeFirstColumns?: boolean;
hasRightBorder?: boolean;
hasBottomBorder?: boolean;
- left?: number;
width?: number;
- colSpan?: number;
} & (Partial | null)) => {
const { theme } = useContext(ThemeContext);
@@ -83,13 +69,9 @@ export const RecordTableTd = ({
backgroundColor={tdBackgroundColor}
borderColor={borderColor}
fontColor={fontColor}
- sticky={sticky}
- freezeFirstColumns={freezeFirstColumns}
- left={left}
hasRightBorder={hasRightBorder}
hasBottomBorder={hasBottomBorder}
width={width}
- colSpan={colSpan}
// eslint-disable-next-line react/jsx-props-no-spreading
{...dragHandleProps}
>
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-footer/components/RecordTableAggregateFooter.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-footer/components/RecordTableAggregateFooter.tsx
index 5338d6adc3..36159d6042 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-footer/components/RecordTableAggregateFooter.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-footer/components/RecordTableAggregateFooter.tsx
@@ -20,44 +20,45 @@ const StyledTableRow = styled.tr<{
position: sticky;
border: none;
- &.footer-sticky {
- td {
- border-top: ${({ theme }) => `1px solid ${theme.border.color.light}`};
- z-index: ${TABLE_Z_INDEX.footer.default};
- position: sticky;
- bottom: 0;
- }
+ // TODO: see how we reimplement horizontal scrolling after all table has been refactored
+ td {
+ border-top: ${({ theme }) => `1px solid ${theme.border.color.light}`};
+ z-index: ${TABLE_Z_INDEX.footer.default};
+ position: sticky;
+ bottom: 0;
}
+
cursor: pointer;
td:nth-of-type(1) {
width: ${FIRST_TH_WIDTH};
left: 0;
border-top: none;
}
- &.first-columns-sticky {
- td:nth-of-type(1) {
- z-index: ${TABLE_Z_INDEX.footer.stickyColumn};
+
+ td:nth-of-type(1) {
+ position: sticky;
+ z-index: ${TABLE_Z_INDEX.footer.stickyColumn};
+ }
+ td:nth-of-type(2) {
+ position: sticky;
+ z-index: ${TABLE_Z_INDEX.footer.stickyColumn};
+ transition: 0.3s ease;
+ &::after {
+ content: '';
+ position: absolute;
+ top: -1px;
+ height: calc(100% + 2px);
+ width: 4px;
+ right: 0px;
+ box-shadow: ${({ theme }) => theme.boxShadow.light};
+ clip-path: inset(0px -4px 0px 0px);
}
- td:nth-of-type(2) {
- position: sticky;
- z-index: ${TABLE_Z_INDEX.footer.stickyColumn};
- transition: 0.3s ease;
- &::after {
- content: '';
- position: absolute;
- top: -1px;
- height: calc(100% + 2px);
- width: 4px;
- right: 0px;
- box-shadow: ${({ theme }) => theme.boxShadow.light};
- clip-path: inset(0px -4px 0px 0px);
- }
- @media (max-width: ${MOBILE_VIEWPORT}px) {
- width: 34px;
- max-width: 34px;
- }
+ @media (max-width: ${MOBILE_VIEWPORT}px) {
+ width: 38px;
+ max-width: 38px;
}
}
+
background: ${({ theme }) => theme.background.primary};
${({ hasHorizontalOverflow }) =>
`.footer-sticky {
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableColumnHead.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableColumnHead.tsx
index 05d2b3b0b9..dbe7bac4bd 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableColumnHead.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableColumnHead.tsx
@@ -1,7 +1,7 @@
import { css, useTheme } from '@emotion/react';
import styled from '@emotion/styled';
-import { isRecordTableScrolledLeftComponentState } from '@/object-record/record-table/states/isRecordTableScrolledLeftComponentState';
+import { isRecordTableScrolledHorizontallyComponentState } from '@/object-record/record-table/states/isRecordTableScrolledHorizontallyComponentState';
import { fieldMetadataItemByIdSelector } from '@/object-metadata/states/fieldMetadataItemByIdSelector';
import { isFieldMetadataItemLabelIdentifierSelector } from '@/object-metadata/states/isFieldMetadataItemLabelIdentifierSelector';
@@ -61,8 +61,8 @@ export const RecordTableColumnHead = ({
}),
);
- const isRecordTableScrolledLeft = useRecoilComponentValue(
- isRecordTableScrolledLeftComponentState,
+ const isRecordTableScrolledHorizontally = useRecoilComponentValue(
+ isRecordTableScrolledHorizontallyComponentState,
);
const { getIcon } = useIcons();
@@ -77,7 +77,9 @@ export const RecordTableColumnHead = ({
);
return (
-
+
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeader.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeader.tsx
index 563be9bbd8..853d7c1f05 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeader.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeader.tsx
@@ -2,99 +2,140 @@ import styled from '@emotion/styled';
import { TABLE_Z_INDEX } from '@/object-record/record-table/constants/TableZIndex';
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
+import { RecordTableHeaderAddColumnButton } from '@/object-record/record-table/record-table-header/components/RecordTableHeaderAddColumnButton';
import { RecordTableHeaderCell } from '@/object-record/record-table/record-table-header/components/RecordTableHeaderCell';
import { RecordTableHeaderCheckboxColumn } from '@/object-record/record-table/record-table-header/components/RecordTableHeaderCheckboxColumn';
import { RecordTableHeaderDragDropColumn } from '@/object-record/record-table/record-table-header/components/RecordTableHeaderDragDropColumn';
import { RecordTableHeaderLastColumn } from '@/object-record/record-table/record-table-header/components/RecordTableHeaderLastColumn';
+import { isRecordTableScrolledHorizontallyComponentState } from '@/object-record/record-table/states/isRecordTableScrolledHorizontallyComponentState';
+import { isRecordTableScrolledVerticallyComponentState } from '@/object-record/record-table/states/isRecordTableScrolledVerticallyComponentState';
+import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
export const FIRST_TH_WIDTH = '10px';
-const StyledTableHead = styled.thead`
+const StyledTableHead = styled.div<{
+ stickyColumnZIndex: number;
+ normalColumnZIndex: number;
+ entireRowZIndex: number;
+}>`
cursor: pointer;
- th:nth-of-type(1) {
- width: ${FIRST_TH_WIDTH};
- left: 0;
- border-right-color: ${({ theme }) => theme.background.primary};
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+
+ height: 32px;
+ background-color: ${({ theme }) => theme.background.primary};
+
+ div.header-cell:nth-of-type(n + 3) {
+ z-index: ${({ normalColumnZIndex }) => normalColumnZIndex};
}
- th:nth-of-type(2) {
- border-right-color: ${({ theme }) => theme.background.primary};
+ div.header-cell:nth-of-type(1) {
+ position: sticky;
+ left: 0px;
+ z-index: ${({ stickyColumnZIndex }) => stickyColumnZIndex};
+ transition: 0.3s ease;
+ background-color: ${({ theme }) => theme.background.primary};
}
- &.first-columns-sticky {
- th:nth-of-type(1) {
- position: sticky;
- left: 0;
- z-index: ${TABLE_Z_INDEX.header.default};
- transition: 0.3s ease;
- }
+ div.header-cell:nth-of-type(2) {
+ position: sticky;
+ left: 17px;
+ top: 0;
+ z-index: ${({ stickyColumnZIndex }) => stickyColumnZIndex};
+ transition: 0.3s ease;
+ background-color: ${({ theme }) => theme.background.primary};
+ }
- th:nth-of-type(2) {
- position: sticky;
- left: 11px;
- z-index: ${TABLE_Z_INDEX.header.default};
- transition: 0.3s ease;
- }
+ div.header-cell:nth-of-type(3) {
+ position: sticky;
+ left: 49px;
+ right: 0;
+ z-index: ${({ stickyColumnZIndex }) => stickyColumnZIndex};
+ transition: 0.3s ease;
+ background-color: ${({ theme }) => theme.background.primary};
- th:nth-of-type(3) {
- position: sticky;
- left: 39px;
- z-index: ${TABLE_Z_INDEX.header.default};
- transition: 0.3s ease;
+ // &::after {
+ // content: '';
+ // position: absolute;
+ // top: -1px;
+ // height: calc(100% + 2px);
+ // width: 4px;
+ // right: 0px;
+ // box-shadow: ${({ theme }) => theme.boxShadow.light};
+ // clip-path: inset(0px -4px 0px 0px);
+ // }
- &::after {
- content: '';
- position: absolute;
- top: -1px;
- height: calc(100% + 2px);
- width: 4px;
- right: 0px;
- box-shadow: ${({ theme }) => theme.boxShadow.light};
- clip-path: inset(0px -4px 0px 0px);
- }
-
- @media (max-width: ${MOBILE_VIEWPORT}px) {
- width: 34px;
- max-width: 34px;
- }
+ @media (max-width: ${MOBILE_VIEWPORT}px) {
+ width: 38px;
+ max-width: 38px;
+ min-width: 38px;
}
}
- &.header-sticky {
- th {
- position: sticky;
- top: 0;
- z-index: ${TABLE_Z_INDEX.header.default};
- }
- }
-
- &.header-sticky.first-columns-sticky {
- th:nth-of-type(1),
- th:nth-of-type(2),
- th:nth-of-type(3) {
- z-index: ${TABLE_Z_INDEX.header.stickyColumn};
- }
- }
+ position: sticky;
+ top: 0px;
+ z-index: ${({ entireRowZIndex }) => entireRowZIndex};
`;
export const RecordTableHeader = () => {
const { visibleRecordFields } = useRecordTableContextOrThrow();
+ const isRecordTableScrolledHorizontally = useRecoilComponentValue(
+ isRecordTableScrolledHorizontallyComponentState,
+ );
+
+ const isRecordTableScrolledVertically = useRecoilComponentValue(
+ isRecordTableScrolledVerticallyComponentState,
+ );
+
+ const computedStickyColumnZIndex =
+ isRecordTableScrolledHorizontally && isRecordTableScrolledVertically
+ ? TABLE_Z_INDEX.scrolledBothVerticallyAndHorizontally.headerColumnsSticky
+ : isRecordTableScrolledHorizontally
+ ? TABLE_Z_INDEX.scrolledHorizontallyOnly.headerColumnsSticky
+ : isRecordTableScrolledVertically
+ ? TABLE_Z_INDEX.scrolledVerticallyOnly.headerColumnsSticky
+ : TABLE_Z_INDEX.noScrollAtAll.headerColumnsSticky;
+
+ const computedNormalColumnZIndex =
+ isRecordTableScrolledHorizontally && isRecordTableScrolledVertically
+ ? TABLE_Z_INDEX.scrolledBothVerticallyAndHorizontally.headerColumnsNormal
+ : isRecordTableScrolledHorizontally
+ ? TABLE_Z_INDEX.scrolledHorizontallyOnly.headerColumnsNormal
+ : isRecordTableScrolledVertically
+ ? TABLE_Z_INDEX.scrolledVerticallyOnly.headerColumnsNormal
+ : TABLE_Z_INDEX.noScrollAtAll.headerColumnsNormal;
+
+ const computedHeaderRowZIndex =
+ isRecordTableScrolledHorizontally && isRecordTableScrolledVertically
+ ? TABLE_Z_INDEX.scrolledBothVerticallyAndHorizontally.headerRow
+ : isRecordTableScrolledHorizontally
+ ? TABLE_Z_INDEX.scrolledHorizontallyOnly.headerRow
+ : isRecordTableScrolledVertically
+ ? TABLE_Z_INDEX.scrolledVerticallyOnly.headerRow
+ : TABLE_Z_INDEX.noScrollAtAll.headerRow;
+
return (
-