diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx index 8e7e13396..2f7898810 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx @@ -23,14 +23,13 @@ import { RecordBoardScrollWrapperContext } from '@/ui/utilities/scroll/contexts/ import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; import styled from '@emotion/styled'; import { ReactNode, useContext, useState } from 'react'; -import { useInView } from 'react-intersection-observer'; +import { InView, useInView } from 'react-intersection-observer'; import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'; import { AnimatedEaseInOut, AvatarChipVariant, Checkbox, CheckboxVariant, - ChipSize, IconEye, IconEyeOff, LightIconButton, @@ -147,10 +146,6 @@ const StyledCompactIconContainer = styled.div` margin-left: ${({ theme }) => theme.spacing(1)}; `; -const StyledRecordInlineCellPlaceholder = styled.div` - height: 24px; -`; - export const RecordBoardCard = ({ isCreating = false, onCreateSuccess, @@ -240,7 +235,7 @@ export const RecordBoardCard = ({ const scrollWrapperRef = useContext(RecordBoardScrollWrapperContext); - const { ref: cardRef, inView } = useInView({ + const { ref: cardRef } = useInView({ root: scrollWrapperRef?.ref.current, rootMargin: '1000px', }); @@ -256,126 +251,123 @@ export const RecordBoardCard = ({ return ( {!isCreating && } - { - if (!isCreating) { - setIsCurrentCardSelected(!isCurrentCardSelected); - } - }} - > - - {isCreating && position !== undefined ? ( - - - handleInputEnter( - labelIdentifierField?.label ?? '', - newLabelValue, - position, - onCreateSuccess, - ) - } - onBlur={() => - handleBlur( - labelIdentifierField?.label ?? '', - newLabelValue, - position, - onCreateSuccess, - ) - } - onChange={(text: string) => setNewLabelValue(text)} - placeholder={labelIdentifierField?.label} - /> - - ) : ( - - )} - - {!isCreating && ( - <> - {isCompactModeActive && ( - - { - e.stopPropagation(); - setIsCardExpanded((prev) => !prev); - }} - /> - - )} - - - - setIsCurrentCardSelected(!isCurrentCardSelected) - } - variant={CheckboxVariant.Secondary} - /> - - - )} - - - + { + if (!isCreating) { + setIsCurrentCardSelected(!isCurrentCardSelected); + } + }} > - - {visibleFieldDefinitionsFiltered.map((fieldDefinition) => ( - - + {isCreating && position !== undefined ? ( + + + handleInputEnter( + labelIdentifierField?.label ?? '', + newLabelValue, + position, + onCreateSuccess, + ) + } + onBlur={() => + handleBlur( + labelIdentifierField?.label ?? '', + newLabelValue, + position, + onCreateSuccess, + ) + } + onChange={(text: string) => setNewLabelValue(text)} + placeholder={labelIdentifierField?.label} + /> + + ) : ( + + )} + + {!isCreating && ( + <> + {isCompactModeActive && ( + + { + e.stopPropagation(); + setIsCardExpanded((prev) => !prev); + }} + /> + + )} + + + + setIsCurrentCardSelected(!isCurrentCardSelected) + } + variant={CheckboxVariant.Secondary} + /> + + + )} + + + + + {visibleFieldDefinitionsFiltered.map((fieldDefinition) => ( + - {inView ? ( + - ) : ( - - )} - - - ))} - - - + + + ))} + + + + ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableRowContext.ts b/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableRowContext.ts index d0ed1aea2..c85e2bda6 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableRowContext.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableRowContext.ts @@ -1,5 +1,5 @@ -import { createContext } from 'react'; import { DraggableProvidedDragHandleProps } from '@hello-pangea/dnd'; +import { createContext } from 'react'; export type RecordTableRowContextProps = { pathToShowPage: string; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellCheckbox.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellCheckbox.tsx index c4c542314..cac73801a 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellCheckbox.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellCheckbox.tsx @@ -9,11 +9,10 @@ import { Checkbox } from 'twenty-ui'; const StyledContainer = styled.div` align-items: center; cursor: pointer; - display: flex; height: 32px; - justify-content: center; + min-width: 24px; `; export const RecordTableCellCheckbox = () => { 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 18bd56df7..65b5dd390 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 @@ -16,6 +16,7 @@ const StyledTd = styled.td<{ left?: number; hasRightBorder?: boolean; hasBottomBorder?: boolean; + width?: number; }>` border-bottom: 1px solid ${({ borderColor, hasBottomBorder }) => @@ -32,13 +33,12 @@ const StyledTd = styled.td<{ background: ${({ backgroundColor }) => backgroundColor}; z-index: ${({ zIndex }) => (isDefined(zIndex) ? zIndex : 'auto')}; - ${({ isDragging }) => isDragging ? ` background-color: transparent; border-color: transparent; - ` + ` : ''} ${({ freezeFirstColumns }) => @@ -60,6 +60,7 @@ export const RecordTableTd = ({ left, hasRightBorder = true, hasBottomBorder = true, + width, ...dragHandleProps }: { className?: string; @@ -72,6 +73,7 @@ export const RecordTableTd = ({ hasRightBorder?: boolean; hasBottomBorder?: boolean; left?: number; + width?: number; } & (Partial | null)) => { const { theme } = useContext(ThemeContext); @@ -94,6 +96,7 @@ export const RecordTableTd = ({ left={left} hasRightBorder={hasRightBorder} hasBottomBorder={hasBottomBorder} + width={width} // eslint-disable-next-line react/jsx-props-no-spreading {...dragHandleProps} > diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCell.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCell.tsx index c1e23e687..069379199 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCell.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCell.tsx @@ -175,6 +175,7 @@ export const RecordTableHeaderCell = ({ resizedFieldKey, resizeFieldOffsetState, tableColumnsByKey, + setResizedFieldKey, tableColumns, handleColumnsChange, ], diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableCellsEmpty.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableCellsEmpty.tsx index 3186f8657..f20f1a5b9 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableCellsEmpty.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableCellsEmpty.tsx @@ -1,9 +1,8 @@ -import { useContext } from 'react'; - import { RecordTableRowContext } from '@/object-record/record-table/contexts/RecordTableRowContext'; import { RecordTableTd } from '@/object-record/record-table/record-table-cell/components/RecordTableTd'; import { visibleTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/visibleTableColumnsComponentSelector'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useContext } from 'react'; export const RecordTableCellsEmpty = () => { const { isSelected } = useContext(RecordTableRowContext); diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableCellsVisible.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableCellsVisible.tsx index 081247b2d..b41e9e44b 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableCellsVisible.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableCellsVisible.tsx @@ -5,10 +5,16 @@ import { RecordTableCell } from '@/object-record/record-table/record-table-cell/ import { RecordTableCellWrapper } from '@/object-record/record-table/record-table-cell/components/RecordTableCellWrapper'; import { RecordTableTd } from '@/object-record/record-table/record-table-cell/components/RecordTableTd'; import { visibleTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/visibleTableColumnsComponentSelector'; +import { tableCellWidthsComponentState } from '@/object-record/record-table/states/tableCellWidthsComponentState'; +import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; export const RecordTableCellsVisible = () => { - const { isDragging, isSelected } = useContext(RecordTableRowContext); + const { isSelected, isDragging } = useContext(RecordTableRowContext); + + const [tableCellWidths] = useRecoilComponentStateV2( + tableCellWidthsComponentState, + ); const visibleTableColumns = useRecoilComponentValueV2( visibleTableColumnsComponentSelector, @@ -19,22 +25,29 @@ export const RecordTableCellsVisible = () => { return ( <> - + - {!isDragging && - tableColumnsAfterFirst.map((column, columnIndex) => ( - ( + + - - - - - ))} + + + + ))} ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableRowWrapper.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableRowWrapper.tsx index 311c1d5df..11d1ae1bb 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableRowWrapper.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableRowWrapper.tsx @@ -1,6 +1,6 @@ import { useTheme } from '@emotion/react'; import { Draggable } from '@hello-pangea/dnd'; -import { ReactNode, useContext, useEffect } from 'react'; +import { ReactNode, useContext, useEffect, useRef } from 'react'; import { useInView } from 'react-intersection-observer'; import { getBasePathToShowPage } from '@/object-metadata/utils/getBasePathToShowPage'; @@ -9,8 +9,10 @@ import { RecordTableContext } from '@/object-record/record-table/contexts/Record import { RecordTableRowContext } from '@/object-record/record-table/contexts/RecordTableRowContext'; import { RecordTableTr } from '@/object-record/record-table/record-table-row/components/RecordTableTr'; import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState'; +import { tableCellWidthsComponentState } from '@/object-record/record-table/states/tableCellWidthsComponentState'; import { RecordTableWithWrappersScrollWrapperContext } from '@/ui/utilities/scroll/contexts/ScrollWrapperContexts'; import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2'; +import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; export const RecordTableRowWrapper = ({ recordId, @@ -23,6 +25,8 @@ export const RecordTableRowWrapper = ({ isPendingRow?: boolean; children: ReactNode; }) => { + const trRef = useRef(null); + const { objectMetadataItem } = useContext(RecordTableContext); const { onIndexRecordsLoaded } = useContext(RecordIndexRootPropsContext); @@ -44,6 +48,24 @@ export const RecordTableRowWrapper = ({ rootMargin: '1000px', }); + const [, setTableCellWidths] = useRecoilComponentStateV2( + tableCellWidthsComponentState, + ); + + useEffect(() => { + if (rowIndex === 0) { + const tdArray = Array.from( + trRef.current?.getElementsByTagName('td') ?? [], + ); + + const tdWidths = tdArray.map((td) => { + return td.getBoundingClientRect().width; + }); + + setTableCellWidths(tdWidths); + } + }, [trRef, rowIndex, setTableCellWidths]); + // TODO: find a better way to emit this event useEffect(() => { if (inView) { @@ -56,6 +78,8 @@ export const RecordTableRowWrapper = ({ {(draggableProvided, draggableSnapshot) => ( { + // @ts-expect-error - TS doesn't know that node.current is assignable + trRef.current = node; elementRef(node); draggableProvided.innerRef(node); }} diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/tableCellWidthsComponentState.ts b/packages/twenty-front/src/modules/object-record/record-table/states/tableCellWidthsComponentState.ts new file mode 100644 index 000000000..54ab3dacf --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/states/tableCellWidthsComponentState.ts @@ -0,0 +1,8 @@ +import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; + +export const tableCellWidthsComponentState = createComponentStateV2({ + key: 'tableCellWidthsComponentState', + defaultValue: [], + componentInstanceContext: RecordTableComponentInstanceContext, +});