diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableStyleWrapper.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableStyleWrapper.tsx index 78bf2d379c..445e430161 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableStyleWrapper.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableStyleWrapper.tsx @@ -113,27 +113,6 @@ const StyledTable = styled.div<{ } } - div.footer-cell:nth-of-type(n + 3) { - z-index: ${TABLE_Z_INDEX.footer.default}; - - position: sticky; - bottom: 0; - } - - div.footer-cell:nth-of-type(1) { - z-index: ${TABLE_Z_INDEX.footer.stickyColumn}; - left: 0px; - bottom: 0; - position: sticky; - } - - div.footer-cell:nth-of-type(2) { - z-index: ${TABLE_Z_INDEX.footer.stickyColumn}; - left: 48px; - bottom: 0; - position: sticky; - } - div.${RECORD_TABLE_COLUMN_DRAG_AND_DROP_WIDTH_CLASS_NAME} { width: ${RECORD_TABLE_COLUMN_DRAG_AND_DROP_WIDTH}px; min-width: ${RECORD_TABLE_COLUMN_DRAG_AND_DROP_WIDTH}px; diff --git a/packages/twenty-front/src/modules/object-record/record-table/constants/RecordTableRowHeight.ts b/packages/twenty-front/src/modules/object-record/record-table/constants/RecordTableRowHeight.ts new file mode 100644 index 0000000000..94195b7c41 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/constants/RecordTableRowHeight.ts @@ -0,0 +1 @@ +export const RECORD_TABLE_ROW_HEIGHT = 32; 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 0ef114ba5c..99fdad1f2f 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,41 +1,85 @@ export const TABLE_Z_INDEX = { base: 1, cell: { - default: 8, + default: 3, sticky: 12, editMode: 30, }, headerColumnsSticky: 14, headerColumnsNormal: 10, - firstCellWithoutVerticalScroll: 15, - firstCellWithVerticalScroll: 12, - noScrollAtAll: { - hoverPortalCellOnFirstScrollableColumn: 17, - hoverPortalCellOnNormalColumn: 17, - hoverPortalCellOnLabelIdentifierColumn: 17, - firstScrollableHeaderCell: 12, + withGroupsCell0_0: { + cell0_0HoveredWithoutScroll: 15, + cell0_0Normal: 13, }, - scrolledBothVerticallyAndHorizontally: { - hoverPortalCellOnNormalColumn: 2, - hoverPortalCellOnFirstScrollableColumn: 2, - hoverPortalCellOnLabelIdentifierColumn: 2, - firstScrollableHeaderCell: 12, + withoutGroupsCell0_0: { + cell0_0HoveredWithoutScroll: 15, + cell0_0Normal: 12, }, - scrolledHorizontallyOnly: { - hoverPortalCellOnLabelIdentifierColumn: 17, - hoverPortalCellOnNormalColumn: 11, - hoverPortalCellOnFirstScrollableColumn: 11, - firstScrollableHeaderCell: 10, + groupSection: { + stickyCell: 12, + normalCell: 10, }, - scrolledVerticallyOnly: { - hoverPortalCellOnNormalColumn: 9, - hoverPortalCellOnFirstScrollableColumn: 13, - hoverPortalCellOnLabelIdentifierColumn: 13, - firstScrollableHeaderCell: 14, + withGroups: { + noScrollAtAll: { + hoverPortalCellOnFirstScrollableColumn: 17, + hoverPortalCellOnNormalColumn: 17, + hoverPortalCellOnLabelIdentifierColumn: 17, + firstScrollableHeaderCell: 12, + }, + scrolledBothVerticallyAndHorizontally: { + hoverPortalCellOnNormalColumn: 2, + hoverPortalCellOnFirstScrollableColumn: 11, + hoverPortalCellOnLabelIdentifierColumn: 15, + firstScrollableHeaderCell: 12, + }, + scrolledHorizontallyOnly: { + hoverPortalCellOnLabelIdentifierColumn: 15, + hoverPortalCellOnNormalColumn: 11, + hoverPortalCellOnFirstScrollableColumn: 11, + firstScrollableHeaderCell: 10, + }, + scrolledVerticallyOnly: { + hoverPortalCellOnNormalColumn: 9, + hoverPortalCellOnFirstScrollableColumn: 15, + hoverPortalCellOnLabelIdentifierColumn: 15, + firstScrollableHeaderCell: 14, + }, + }, + withoutGroups: { + noScrollAtAll: { + hoverPortalCellOnFirstScrollableColumn: 17, + hoverPortalCellOnNormalColumn: 17, + hoverPortalCellOnLabelIdentifierColumn: 17, + firstScrollableHeaderCell: 12, + }, + scrolledBothVerticallyAndHorizontally: { + hoverPortalCellOnNormalColumn: 2, + hoverPortalCellOnFirstScrollableColumn: 2, + hoverPortalCellOnLabelIdentifierColumn: 2, + firstScrollableHeaderCell: 12, + }, + scrolledHorizontallyOnly: { + hoverPortalCellOnLabelIdentifierColumn: 17, + hoverPortalCellOnNormalColumn: 11, + hoverPortalCellOnFirstScrollableColumn: 11, + firstScrollableHeaderCell: 10, + }, + scrolledVerticallyOnly: { + hoverPortalCellOnNormalColumn: 9, + hoverPortalCellOnFirstScrollableColumn: 13, + hoverPortalCellOnLabelIdentifierColumn: 13, + firstScrollableHeaderCell: 14, + }, }, columnGrip: 30, footer: { - default: 18, - stickyColumn: 20, + tableWithGroups: { + default: 4, + stickyColumn: 5, + }, + tableWithoutGroups: { + default: 18, + stickyColumn: 20, + }, }, }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFirstRowFirstColumn.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFirstRowFirstColumn.tsx index 1d45c0f6fb..dcf84de571 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFirstRowFirstColumn.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFirstRowFirstColumn.tsx @@ -1,8 +1,11 @@ +import { hasRecordGroupsComponentSelector } from '@/object-record/record-group/states/selectors/hasRecordGroupsComponentSelector'; import { TABLE_Z_INDEX } from '@/object-record/record-table/constants/TableZIndex'; import { StyledCell } from '@/object-record/record-table/record-table-cell/components/RecordTableCellStyleWrapper'; import { isRecordTableScrolledVerticallyComponentState } from '@/object-record/record-table/states/isRecordTableScrolledVerticallyComponentState'; +import { recordTableHoverPositionComponentState } from '@/object-record/record-table/states/recordTableHoverPositionComponentState'; import { getRecordTableColumnFieldWidthClassName } from '@/object-record/record-table/utils/getRecordTableColumnFieldWidthClassName'; import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState'; +import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; import styled from '@emotion/styled'; import { type DraggableProvidedDragHandleProps } from '@hello-pangea/dnd'; import { cx } from '@linaria/core'; @@ -30,13 +33,32 @@ export const RecordTableCellFirstRowFirstColumn = ({ } & (Partial | null)) => { const { theme } = useContext(ThemeContext); + const hoverPosition = useRecoilComponentValue( + recordTableHoverPositionComponentState, + ); + + const isHoveredPortalOnThisCell = + hoverPosition?.column === 0 && hoverPosition.row === 0; + const [isRecordTableScrolledVertically] = useRecoilComponentState( isRecordTableScrolledVerticallyComponentState, ); - const zIndex = isRecordTableScrolledVertically - ? TABLE_Z_INDEX.firstCellWithVerticalScroll - : TABLE_Z_INDEX.firstCellWithoutVerticalScroll; + const hasRecordGroups = useRecoilComponentValue( + hasRecordGroupsComponentSelector, + ); + + const zIndexWithoutGroups = + !isRecordTableScrolledVertically && isHoveredPortalOnThisCell + ? TABLE_Z_INDEX.withoutGroupsCell0_0.cell0_0HoveredWithoutScroll + : TABLE_Z_INDEX.withoutGroupsCell0_0.cell0_0Normal; + + const zIndexWithGroups = + !isRecordTableScrolledVertically && isHoveredPortalOnThisCell + ? TABLE_Z_INDEX.withGroupsCell0_0.cell0_0HoveredWithoutScroll + : TABLE_Z_INDEX.withGroupsCell0_0.cell0_0Normal; + + const zIndex = hasRecordGroups ? zIndexWithGroups : zIndexWithoutGroups; const tdBackgroundColor = isSelected ? theme.accent.quaternary 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 9e8f43d3f0..fda534369c 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 @@ -2,6 +2,7 @@ import { RecordTableCellPortalWrapper } from '@/object-record/record-table/recor import { recordTableHoverPositionComponentState } from '@/object-record/record-table/states/recordTableHoverPositionComponentState'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; +import { hasRecordGroupsComponentSelector } from '@/object-record/record-group/states/selectors/hasRecordGroupsComponentSelector'; import { TABLE_Z_INDEX } from '@/object-record/record-table/constants/TableZIndex'; import { RecordTableCellHoveredPortalContent } from '@/object-record/record-table/record-table-cell/components/RecordTableCellHoveredPortalContent'; import { RecordTableCellPortalRootContainer } from '@/object-record/record-table/record-table-cell/components/RecordTableCellPortalRootContainer'; @@ -21,6 +22,10 @@ export const RecordTableCellHoveredPortal = () => { isRecordTableScrolledHorizontallyComponentState, ); + const hasRecordGroups = useRecoilComponentValue( + hasRecordGroupsComponentSelector, + ); + if (!hoverPosition) { return null; } @@ -28,45 +33,99 @@ export const RecordTableCellHoveredPortal = () => { const isOnFirstScrollableColumn = hoverPosition.column === 1; const isOnLabelIdentifierStickyColumn = hoverPosition.column === 0; - const zIndexForFirstScrollableColumn = + const zIndexForHoveredPortalOnFirstScrollableColumnWithoutGroups = isRecordTableScrolledHorizontally && isRecordTableScrolledVertically - ? TABLE_Z_INDEX.scrolledBothVerticallyAndHorizontally + ? TABLE_Z_INDEX.withoutGroups.scrolledBothVerticallyAndHorizontally .hoverPortalCellOnFirstScrollableColumn : isRecordTableScrolledHorizontally - ? TABLE_Z_INDEX.scrolledHorizontallyOnly + ? TABLE_Z_INDEX.withoutGroups.scrolledHorizontallyOnly .hoverPortalCellOnFirstScrollableColumn : isRecordTableScrolledVertically - ? TABLE_Z_INDEX.scrolledVerticallyOnly + ? TABLE_Z_INDEX.withoutGroups.scrolledVerticallyOnly .hoverPortalCellOnFirstScrollableColumn - : TABLE_Z_INDEX.noScrollAtAll.hoverPortalCellOnFirstScrollableColumn; + : TABLE_Z_INDEX.withoutGroups.noScrollAtAll + .hoverPortalCellOnFirstScrollableColumn; - const zIndexForLabelIdentifierStickyColumn = + const zIndexForHoveredPortalOnLabelIdentifierStickyColumnWithoutGroups = isRecordTableScrolledHorizontally && isRecordTableScrolledVertically - ? TABLE_Z_INDEX.scrolledBothVerticallyAndHorizontally + ? TABLE_Z_INDEX.withoutGroups.scrolledBothVerticallyAndHorizontally .hoverPortalCellOnLabelIdentifierColumn : isRecordTableScrolledHorizontally - ? TABLE_Z_INDEX.scrolledHorizontallyOnly + ? TABLE_Z_INDEX.withoutGroups.scrolledHorizontallyOnly .hoverPortalCellOnLabelIdentifierColumn : isRecordTableScrolledVertically - ? TABLE_Z_INDEX.scrolledVerticallyOnly + ? TABLE_Z_INDEX.withoutGroups.scrolledVerticallyOnly .hoverPortalCellOnLabelIdentifierColumn - : TABLE_Z_INDEX.noScrollAtAll.hoverPortalCellOnLabelIdentifierColumn; + : TABLE_Z_INDEX.withoutGroups.noScrollAtAll + .hoverPortalCellOnLabelIdentifierColumn; - const zIndexForNormalColumn = + const zIndexForHoveredPortalOnNormalColumnWithoutGroups = isRecordTableScrolledHorizontally && isRecordTableScrolledVertically - ? TABLE_Z_INDEX.scrolledBothVerticallyAndHorizontally + ? TABLE_Z_INDEX.withoutGroups.scrolledBothVerticallyAndHorizontally .hoverPortalCellOnNormalColumn : isRecordTableScrolledHorizontally - ? TABLE_Z_INDEX.scrolledHorizontallyOnly.hoverPortalCellOnNormalColumn + ? TABLE_Z_INDEX.withoutGroups.scrolledHorizontallyOnly + .hoverPortalCellOnNormalColumn : isRecordTableScrolledVertically - ? TABLE_Z_INDEX.scrolledVerticallyOnly.hoverPortalCellOnNormalColumn - : TABLE_Z_INDEX.noScrollAtAll.hoverPortalCellOnNormalColumn; + ? TABLE_Z_INDEX.withoutGroups.scrolledVerticallyOnly + .hoverPortalCellOnNormalColumn + : TABLE_Z_INDEX.withoutGroups.noScrollAtAll + .hoverPortalCellOnNormalColumn; - const zIndex = isOnFirstScrollableColumn - ? zIndexForFirstScrollableColumn + const zIndexForHoveredPortalWithoutGroups = isOnFirstScrollableColumn + ? zIndexForHoveredPortalOnFirstScrollableColumnWithoutGroups : isOnLabelIdentifierStickyColumn - ? zIndexForLabelIdentifierStickyColumn - : zIndexForNormalColumn; + ? zIndexForHoveredPortalOnLabelIdentifierStickyColumnWithoutGroups + : zIndexForHoveredPortalOnNormalColumnWithoutGroups; + + const zIndexForHoveredPortalOnFirstScrollableColumnWithGroups = + isRecordTableScrolledHorizontally && isRecordTableScrolledVertically + ? TABLE_Z_INDEX.withGroups.scrolledBothVerticallyAndHorizontally + .hoverPortalCellOnFirstScrollableColumn + : isRecordTableScrolledHorizontally + ? TABLE_Z_INDEX.withGroups.scrolledHorizontallyOnly + .hoverPortalCellOnFirstScrollableColumn + : isRecordTableScrolledVertically + ? TABLE_Z_INDEX.withGroups.scrolledVerticallyOnly + .hoverPortalCellOnFirstScrollableColumn + : TABLE_Z_INDEX.withGroups.noScrollAtAll + .hoverPortalCellOnFirstScrollableColumn; + + const zIndexForHoveredPortalOnLabelIdentifierStickyColumnWithGroups = + isRecordTableScrolledHorizontally && isRecordTableScrolledVertically + ? TABLE_Z_INDEX.withGroups.scrolledBothVerticallyAndHorizontally + .hoverPortalCellOnLabelIdentifierColumn + : isRecordTableScrolledHorizontally + ? TABLE_Z_INDEX.withGroups.scrolledHorizontallyOnly + .hoverPortalCellOnLabelIdentifierColumn + : isRecordTableScrolledVertically + ? TABLE_Z_INDEX.withGroups.scrolledVerticallyOnly + .hoverPortalCellOnLabelIdentifierColumn + : TABLE_Z_INDEX.withGroups.noScrollAtAll + .hoverPortalCellOnLabelIdentifierColumn; + + const zIndexForHoveredPortalOnNormalColumnWithGroups = + isRecordTableScrolledHorizontally && isRecordTableScrolledVertically + ? TABLE_Z_INDEX.withGroups.scrolledBothVerticallyAndHorizontally + .hoverPortalCellOnNormalColumn + : isRecordTableScrolledHorizontally + ? TABLE_Z_INDEX.withGroups.scrolledHorizontallyOnly + .hoverPortalCellOnNormalColumn + : isRecordTableScrolledVertically + ? TABLE_Z_INDEX.withGroups.scrolledVerticallyOnly + .hoverPortalCellOnNormalColumn + : TABLE_Z_INDEX.withGroups.noScrollAtAll + .hoverPortalCellOnNormalColumn; + + const zIndexForHoveredPortalWithGroups = isOnFirstScrollableColumn + ? zIndexForHoveredPortalOnFirstScrollableColumnWithGroups + : isOnLabelIdentifierStickyColumn + ? zIndexForHoveredPortalOnLabelIdentifierStickyColumnWithGroups + : zIndexForHoveredPortalOnNormalColumnWithGroups; + + const zIndex = hasRecordGroups + ? zIndexForHoveredPortalWithGroups + : zIndexForHoveredPortalWithoutGroups; return ( 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 737dee31b7..d366c36f95 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 @@ -1,17 +1,54 @@ import styled from '@emotion/styled'; +import { RECORD_TABLE_COLUMN_ADD_COLUMN_BUTTON_WIDTH } from '@/object-record/record-table/constants/RecordTableColumnAddColumnButtonWidth'; +import { RECORD_TABLE_COLUMN_CHECKBOX_WIDTH } from '@/object-record/record-table/constants/RecordTableColumnCheckboxWidth'; +import { RECORD_TABLE_COLUMN_DRAG_AND_DROP_WIDTH } from '@/object-record/record-table/constants/RecordTableColumnDragAndDropWidth'; +import { RECORD_TABLE_COLUMN_LAST_EMPTY_COLUMN_WIDTH_CLASS_NAME } from '@/object-record/record-table/constants/RecordTableColumnLastEmptyColumnWidthClassName'; import { TABLE_Z_INDEX } from '@/object-record/record-table/constants/TableZIndex'; import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; import { RecordTableAggregateFooterCell } from '@/object-record/record-table/record-table-footer/components/RecordTableAggregateFooterCell'; import { RecordTableColumnAggregateFooterCellContext } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateFooterCellContext'; +import { isDefined } from 'twenty-shared/utils'; -const StyledPlaceholderFirstCell = styled.div` +const StyledPlaceholderDragAndDropFooterCell = styled.div<{ + isTableWithGroups: boolean; +}>` background-color: ${({ theme }) => theme.background.primary}; - width: 48px; + width: ${RECORD_TABLE_COLUMN_DRAG_AND_DROP_WIDTH + + RECORD_TABLE_COLUMN_CHECKBOX_WIDTH}px; position: sticky; left: 0px; bottom: 0; - z-index: ${TABLE_Z_INDEX.footer.stickyColumn}; + + z-index: ${({ isTableWithGroups }) => + isTableWithGroups + ? TABLE_Z_INDEX.footer.tableWithGroups.stickyColumn + : TABLE_Z_INDEX.footer.tableWithoutGroups.stickyColumn}; +`; + +const StyledPlaceholderAddButtonPlaceholderFooterCell = styled.div<{ + isTableWithGroups: boolean; +}>` + background-color: ${({ theme }) => theme.background.primary}; + width: ${RECORD_TABLE_COLUMN_ADD_COLUMN_BUTTON_WIDTH}px; + position: sticky; + bottom: 0; + z-index: ${({ isTableWithGroups }) => + isTableWithGroups + ? TABLE_Z_INDEX.footer.tableWithGroups.default + : TABLE_Z_INDEX.footer.tableWithoutGroups.default}; +`; + +const StyledPlaceholderLastColumnEmptyFooterCell = styled.div<{ + isTableWithGroups: boolean; +}>` + background-color: ${({ theme }) => theme.background.primary}; + position: sticky; + bottom: 0; + z-index: ${({ isTableWithGroups }) => + isTableWithGroups + ? TABLE_Z_INDEX.footer.tableWithGroups.default + : TABLE_Z_INDEX.footer.tableWithoutGroups.default}; `; export const RecordTableAggregateFooter = ({ @@ -21,9 +58,13 @@ export const RecordTableAggregateFooter = ({ }) => { const { visibleRecordFields } = useRecordTableContextOrThrow(); + const isTableWithGroups = isDefined(currentRecordGroupId); + return ( <> - + {visibleRecordFields.map((recordField, index) => { return ( ); })} - {/* TODO: fix span for divs styling here colSpan={visibleRecordFields.length - 1}*/} -
-
-
+ + ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-footer/components/RecordTableAggregateFooterCell.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-footer/components/RecordTableAggregateFooterCell.tsx index 127124664f..bd8df8b869 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-footer/components/RecordTableAggregateFooterCell.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-footer/components/RecordTableAggregateFooterCell.tsx @@ -1,6 +1,7 @@ import styled from '@emotion/styled'; import { useContext } from 'react'; +import { RECORD_TABLE_ROW_HEIGHT } from '@/object-record/record-table/constants/RecordTableRowHeight'; import { TABLE_Z_INDEX } from '@/object-record/record-table/constants/TableZIndex'; import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; import { RecordTableColumnAggregateFooterCellContext } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateFooterCellContext'; @@ -9,7 +10,8 @@ import { findByProperty, isDefined } from 'twenty-shared/utils'; const StyledColumnFooterCell = styled.div<{ columnWidth: number; - isFirstCell?: boolean; + isFirstCell: boolean; + isTableWithGroups: boolean; }>` background-color: ${({ theme }) => theme.background.primary}; color: ${({ theme }) => theme.font.color.tertiary}; @@ -31,12 +33,7 @@ const StyledColumnFooterCell = styled.div<{ }; `; }}; - height: 32px; - - position: sticky; - left: 48px; - bottom: 0; - z-index: ${TABLE_Z_INDEX.footer.stickyColumn}; + height: ${RECORD_TABLE_ROW_HEIGHT}px; user-select: none; overflow: auto; @@ -45,6 +42,14 @@ const StyledColumnFooterCell = styled.div<{ *::-webkit-scrollbar { display: none; } + + position: sticky; + bottom: 0; + + ${({ isFirstCell, isTableWithGroups }) => + isFirstCell + ? `left: 48px; z-index: ${isTableWithGroups ? TABLE_Z_INDEX.footer.tableWithGroups.stickyColumn : TABLE_Z_INDEX.footer.tableWithoutGroups.stickyColumn};` + : `z-index: ${isTableWithGroups ? TABLE_Z_INDEX.footer.tableWithGroups.default : TABLE_Z_INDEX.footer.tableWithoutGroups.default};`} `; const StyledColumnFootContainer = styled.div` @@ -70,6 +75,8 @@ export const RecordTableAggregateFooterCell = ({ findByProperty('fieldMetadataItemId', fieldMetadataId), ); + const isTableWithGroups = isDefined(currentRecordGroupId); + if (!isDefined(recordField)) { return null; } @@ -77,10 +84,9 @@ export const RecordTableAggregateFooterCell = ({ return ( theme.background.transparent.secondary}; + background: ${({ theme }) => theme.background.secondary}; } `; const StyledPlusIconContainer = styled.div` align-items: center; display: flex; - height: 32px; + height: ${RECORD_TABLE_ROW_HEIGHT}px; width: 100%; justify-content: center; `; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCellContainer.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCellContainer.tsx index 59b3f3a520..ddce89dab7 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCellContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCellContainer.tsx @@ -1,3 +1,4 @@ +import { RECORD_TABLE_ROW_HEIGHT } from '@/object-record/record-table/constants/RecordTableRowHeight'; import styled from '@emotion/styled'; const StyledHeaderCell = styled.div<{ @@ -10,8 +11,8 @@ const StyledHeaderCell = styled.div<{ position: relative; - height: 32px; - max-height: 32px; + height: ${RECORD_TABLE_ROW_HEIGHT}px; + max-height: ${RECORD_TABLE_ROW_HEIGHT}px; background-color: ${({ theme }) => theme.background.primary}; border-right: 1px solid ${({ theme }) => theme.border.color.light}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderFirstScrollableCell.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderFirstScrollableCell.tsx index 1f458e3555..507d614648 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderFirstScrollableCell.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderFirstScrollableCell.tsx @@ -7,6 +7,7 @@ import { RecordTableHeaderResizeHandler } from '@/object-record/record-table/rec import { RecordTableHeaderCellContainer } from '@/object-record/record-table/record-table-header/components/RecordTableHeaderCellContainer'; +import { hasRecordGroupsComponentSelector } from '@/object-record/record-group/states/selectors/hasRecordGroupsComponentSelector'; import { isRecordTableRowActiveComponentFamilyState } from '@/object-record/record-table/states/isRecordTableRowActiveComponentFamilyState'; import { isRecordTableRowFocusedComponentFamilyState } from '@/object-record/record-table/states/isRecordTableRowFocusedComponentFamilyState'; import { isRecordTableScrolledHorizontallyComponentState } from '@/object-record/record-table/states/isRecordTableScrolledHorizontallyComponentState'; @@ -50,15 +51,35 @@ export const RecordTableHeaderFirstScrollableCell = () => { isRecordTableScrolledHorizontallyComponentState, ); - const zIndex = + const hasRecordGroups = useRecoilComponentValue( + hasRecordGroupsComponentSelector, + ); + + const zIndexWithGroups = isRecordTableScrolledHorizontally && isRecordTableScrolledVertically - ? TABLE_Z_INDEX.scrolledBothVerticallyAndHorizontally + ? TABLE_Z_INDEX.withGroups.scrolledBothVerticallyAndHorizontally .firstScrollableHeaderCell : isRecordTableScrolledHorizontally - ? TABLE_Z_INDEX.scrolledHorizontallyOnly.firstScrollableHeaderCell + ? TABLE_Z_INDEX.withGroups.scrolledHorizontallyOnly + .firstScrollableHeaderCell : isRecordTableScrolledVertically - ? TABLE_Z_INDEX.scrolledVerticallyOnly.firstScrollableHeaderCell - : TABLE_Z_INDEX.noScrollAtAll.firstScrollableHeaderCell; + ? TABLE_Z_INDEX.withGroups.scrolledVerticallyOnly + .firstScrollableHeaderCell + : TABLE_Z_INDEX.withGroups.noScrollAtAll.firstScrollableHeaderCell; + + const zIndexWithoutGroups = + isRecordTableScrolledHorizontally && isRecordTableScrolledVertically + ? TABLE_Z_INDEX.withoutGroups.scrolledBothVerticallyAndHorizontally + .firstScrollableHeaderCell + : isRecordTableScrolledHorizontally + ? TABLE_Z_INDEX.withoutGroups.scrolledHorizontallyOnly + .firstScrollableHeaderCell + : isRecordTableScrolledVertically + ? TABLE_Z_INDEX.withoutGroups.scrolledVerticallyOnly + .firstScrollableHeaderCell + : TABLE_Z_INDEX.withoutGroups.noScrollAtAll.firstScrollableHeaderCell; + + const zIndex = hasRecordGroups ? zIndexWithGroups : zIndexWithoutGroups; if (!recordField) { return <>; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableActionRow.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableActionRow.tsx index 895544132e..f2f7bfb8d0 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableActionRow.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableActionRow.tsx @@ -1,7 +1,12 @@ import styled from '@emotion/styled'; import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; +import { RECORD_TABLE_COLUMN_CHECKBOX_WIDTH } from '@/object-record/record-table/constants/RecordTableColumnCheckboxWidth'; +import { RECORD_TABLE_ROW_HEIGHT } from '@/object-record/record-table/constants/RecordTableRowHeight'; import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; +import { RecordTableAddButtonPlaceholderCell } from '@/object-record/record-table/record-table-row/components/RecordTableAddButtonPlaceholderCell'; +import { RecordTableDragAndDropPlaceholderCell } from '@/object-record/record-table/record-table-row/components/RecordTableDragAndDropPlaceholderCell'; +import { RecordTableLastDynamicFillingCell } from '@/object-record/record-table/record-table-row/components/RecordTableLastDynamicFillingCell'; import { useTheme } from '@emotion/react'; import { filterOutByProperty, @@ -10,37 +15,22 @@ import { } from 'twenty-shared/utils'; import { type IconComponent } from 'twenty-ui/display'; -const StyledDragDropPlaceholderCell = styled.div` - min-width: 16px; - width: 16px; - - position: sticky; +const StyledDragDropPlaceholderCell = styled( + RecordTableDragAndDropPlaceholderCell, +)` left: 0; -`; - -const StyledPlusButtonPlaceholderCell = styled.div` - height: 32px; - min-width: 32px; - width: 32px; - &:hover { - background-color: ${({ theme }) => theme.background.transparent.light}; - } + position: sticky; `; const StyledFieldPlaceholderCell = styled.div<{ widthOfFields: number }>` - height: 32px; + height: ${RECORD_TABLE_ROW_HEIGHT}px; min-width: ${({ widthOfFields }) => widthOfFields}px; width: ${({ widthOfFields }) => widthOfFields}px; - - &:hover { - background-color: ${({ theme }) => theme.background.transparent.light}; - } `; const StyledRecordTableDraggableTr = styled.div` cursor: pointer; - transition: background-color ${({ theme }) => theme.animation.duration.fast} - ease-in-out; + border: none; background: ${({ theme }) => theme.background.primary}; @@ -50,19 +40,12 @@ const StyledRecordTableDraggableTr = styled.div` &:hover { div:not(:first-of-type) { - background-color: ${({ theme }) => theme.background.transparent.light}; + background-color: ${({ theme }) => theme.background.secondary}; } } - div { + div:not(:first-of-type) { border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; - background-color: ${({ theme }) => theme.background.primary}; - transition: background-color ${({ theme }) => theme.animation.duration.fast} - ease-in-out; - - &:first-of-type { - border-bottom: 1px solid ${({ theme }) => theme.background.primary}; - } } width: 100%; @@ -74,21 +57,21 @@ const StyledIconContainer = styled.div` border-right: none; color: ${({ theme }) => theme.font.color.secondary}; display: flex; - height: 32px; + height: ${RECORD_TABLE_ROW_HEIGHT}px; justify-content: center; - width: 32px; + width: ${RECORD_TABLE_COLUMN_CHECKBOX_WIDTH}px; position: sticky; left: 16px; `; -const StyledRecordTableTdTextContainer = styled.div<{ width: number }>` +const StyledActionTextContainer = styled.div<{ width: number }>` align-items: center; - background-color: transparent; + border-right: none; display: flex; - height: 32px; + height: ${RECORD_TABLE_ROW_HEIGHT}px; justify-content: start; left: 48px; @@ -147,18 +130,19 @@ export const RecordTableActionRow = ({ color={theme.font.color.tertiary} /> - {text} - + - + + ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableAddButtonPlaceholderCell.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableAddButtonPlaceholderCell.tsx new file mode 100644 index 0000000000..a00a7cd532 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableAddButtonPlaceholderCell.tsx @@ -0,0 +1,17 @@ +import { RECORD_TABLE_COLUMN_ADD_COLUMN_BUTTON_WIDTH } from '@/object-record/record-table/constants/RecordTableColumnAddColumnButtonWidth'; +import { RECORD_TABLE_ROW_HEIGHT } from '@/object-record/record-table/constants/RecordTableRowHeight'; +import styled from '@emotion/styled'; +import { cx } from '@linaria/core'; + +const StyledPlaceholderAddButtonCell = styled.div` + height: ${RECORD_TABLE_ROW_HEIGHT}px; + width: ${RECORD_TABLE_COLUMN_ADD_COLUMN_BUTTON_WIDTH}px; +`; + +export const RecordTableAddButtonPlaceholderCell = ({ + className, +}: { + className?: string; +}) => { + return ; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableDragAndDropPlaceholderCell.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableDragAndDropPlaceholderCell.tsx new file mode 100644 index 0000000000..e53831a546 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableDragAndDropPlaceholderCell.tsx @@ -0,0 +1,25 @@ +import { RECORD_TABLE_COLUMN_DRAG_AND_DROP_WIDTH } from '@/object-record/record-table/constants/RecordTableColumnDragAndDropWidth'; +import { RECORD_TABLE_ROW_HEIGHT } from '@/object-record/record-table/constants/RecordTableRowHeight'; +import styled from '@emotion/styled'; +import { cx } from '@linaria/core'; + +const StyledPlaceholderDragAndDropCell = styled.div` + height: ${RECORD_TABLE_ROW_HEIGHT}px; + width: ${RECORD_TABLE_COLUMN_DRAG_AND_DROP_WIDTH}px; + min-width: ${RECORD_TABLE_COLUMN_DRAG_AND_DROP_WIDTH}px; + + background-color: ${({ theme }) => theme.background.primary}; + + border-bottom: 1px solid ${({ theme }) => theme.background.primary}; + + position: sticky; + left: 0; +`; + +export const RecordTableDragAndDropPlaceholderCell = ({ + className, +}: { + className?: string; +}) => { + return ; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableLastDynamicFillingCell.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableLastDynamicFillingCell.tsx new file mode 100644 index 0000000000..d2d65c8fc2 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableLastDynamicFillingCell.tsx @@ -0,0 +1,23 @@ +import { RECORD_TABLE_COLUMN_LAST_EMPTY_COLUMN_WIDTH_CLASS_NAME } from '@/object-record/record-table/constants/RecordTableColumnLastEmptyColumnWidthClassName'; +import { RECORD_TABLE_ROW_HEIGHT } from '@/object-record/record-table/constants/RecordTableRowHeight'; +import styled from '@emotion/styled'; +import { cx } from '@linaria/core'; + +const StyledPlaceholderLastDynamicFillingCell = styled.div` + height: ${RECORD_TABLE_ROW_HEIGHT}px; +`; + +export const RecordTableLastDynamicFillingCell = ({ + className, +}: { + className?: string; +}) => { + return ( + + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-section/components/RecordTableRecordGroupSection.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-section/components/RecordTableRecordGroupSection.tsx index ebd96865ab..746530d9ba 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-section/components/RecordTableRecordGroupSection.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-section/components/RecordTableRecordGroupSection.tsx @@ -8,7 +8,12 @@ import { useCurrentRecordGroupId } from '@/object-record/record-group/hooks/useC import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState'; import { RecordGroupDefinitionType } from '@/object-record/record-group/types/RecordGroupDefinition'; import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; +import { RECORD_TABLE_ROW_HEIGHT } from '@/object-record/record-table/constants/RecordTableRowHeight'; +import { TABLE_Z_INDEX } from '@/object-record/record-table/constants/TableZIndex'; import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; +import { RecordTableAddButtonPlaceholderCell } from '@/object-record/record-table/record-table-row/components/RecordTableAddButtonPlaceholderCell'; +import { RecordTableDragAndDropPlaceholderCell } from '@/object-record/record-table/record-table-row/components/RecordTableDragAndDropPlaceholderCell'; +import { RecordTableLastDynamicFillingCell } from '@/object-record/record-table/record-table-row/components/RecordTableLastDynamicFillingCell'; import { RecordTableRecordGroupStickyEffect } from '@/object-record/record-table/record-table-section/components/RecordTableRecordGroupStickyEffect'; import { useAggregateRecordsForRecordTableSection } from '@/object-record/record-table/record-table-section/hooks/useAggregateRecordsForRecordTableSection'; import { isRecordGroupTableSectionToggledComponentState } from '@/object-record/record-table/record-table-section/states/isRecordGroupTableSectionToggledComponentState'; @@ -25,21 +30,17 @@ import { Tag } from 'twenty-ui/components'; import { IconChevronDown } from 'twenty-ui/display'; import { AnimatedLightIconButton } from 'twenty-ui/input'; -const StyledDragDropHeaderPlaceholder = styled.div` - min-width: 16px; - width: 16px; - position: sticky; - left: 0; -`; - const StyledTrContainer = styled.div` cursor: pointer; display: flex; flex-direction: row; + + div:not(:first-of-type) { + border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; + } `; const StyledChevronContainer = styled.div` - border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; border-right: none; color: ${({ theme }) => theme.font.color.secondary}; display: flex; @@ -50,16 +51,19 @@ const StyledChevronContainer = styled.div` position: sticky; left: 16px; + + z-index: ${TABLE_Z_INDEX.groupSection.stickyCell}; `; const StyledAnimatedLightIconButton = styled(AnimatedLightIconButton)` display: block; margin: auto; + + z-index: ${TABLE_Z_INDEX.groupSection.stickyCell}; `; const StyledRecordGroupSection = styled.div<{ width: number }>` align-items: center; - border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; border-right: none; display: flex; flex-direction: row; @@ -70,24 +74,26 @@ const StyledRecordGroupSection = styled.div<{ width: number }>` position: sticky; left: 48px; + + z-index: ${TABLE_Z_INDEX.groupSection.stickyCell}; `; const StyledTag = styled(Tag)` flex-shrink: 0; `; -const StyledPlusButtonPlaceholderCell = styled.div` - border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; - height: 32px; - min-width: 32px; - width: 32px; -`; - const StyledFieldPlaceholderCell = styled.div<{ widthOfFields: number }>` - border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; - height: 32px; + height: ${RECORD_TABLE_ROW_HEIGHT}px; min-width: ${({ widthOfFields }) => widthOfFields}px; width: ${({ widthOfFields }) => widthOfFields}px; + + z-index: ${TABLE_Z_INDEX.groupSection.normalCell}; +`; + +const StyledRecordTableDragAndDropPlaceholderCell = styled( + RecordTableDragAndDropPlaceholderCell, +)` + z-index: ${TABLE_Z_INDEX.groupSection.stickyCell}; `; export const RecordTableRecordGroupSection = () => { @@ -153,7 +159,7 @@ export const RecordTableRecordGroupSection = () => { return ( - + { - + + ); };