fix(ui): layout-shift-on-tasks (#15775)
Fixes #12090 ### Summary Fixes a UI layout shift issue in table rows in Tasks page, where bottom borders appeared inconsistently across rows. The problem occurred because `shouldDisplayBorderBottom` conditionally applied the bottom border, which caused slight height differences between rows and visual "jumping" when rendering focused styling. ### Changes Made - Ensured consistent `border-bottom` rendering - Removed conditional rendering prop to always display bottom border ### Steps to Reproduce (Before Fix) 1. Navigate to - /objects/tasks?viewId=xxxx 2. Interact with row elements 3. Notice a slight layout shift when first row is active/focused ### Before https://github.com/user-attachments/assets/ab95db5d-0922-4460-a086-a03f58375824 ### After https://github.com/user-attachments/assets/a6b4d50c-b6f0-456b-90d4-fc3f0cde42bc --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
+6
-52
@@ -8,8 +8,6 @@ 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 { recordIndexRecordIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRecordIdsByGroupComponentFamilyState';
|
||||
import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector';
|
||||
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 { TABLE_Z_INDEX } from '@/object-record/record-table/constants/TableZIndex';
|
||||
@@ -22,10 +20,7 @@ import { RECORD_TABLE_COLUMN_MIN_WIDTH } from '@/object-record/record-table/cons
|
||||
import { RECORD_TABLE_LABEL_IDENTIFIER_COLUMN_WIDTH_ON_MOBILE } from '@/object-record/record-table/constants/RecordTableLabelIdentifierColumnWidthOnMobile';
|
||||
import { useAggregateRecordsForRecordTableSection } from '@/object-record/record-table/record-table-section/hooks/useAggregateRecordsForRecordTableSection';
|
||||
import { isRecordGroupTableSectionToggledComponentState } from '@/object-record/record-table/record-table-section/states/isRecordGroupTableSectionToggledComponentState';
|
||||
import { isRecordTableRowActiveComponentFamilyState } from '@/object-record/record-table/states/isRecordTableRowActiveComponentFamilyState';
|
||||
import { isRecordTableRowFocusedComponentFamilyState } from '@/object-record/record-table/states/isRecordTableRowFocusedComponentFamilyState';
|
||||
import { useRecoilComponentFamilyState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyState';
|
||||
import { useRecoilComponentFamilyValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import {
|
||||
@@ -39,16 +34,13 @@ import { IconChevronDown } from 'twenty-ui/display';
|
||||
import { AnimatedLightIconButton } from 'twenty-ui/input';
|
||||
import { useIsMobile } from 'twenty-ui/utilities';
|
||||
|
||||
const StyledTrContainer = styled.div<{ shouldDisplayBorderBottom: boolean }>`
|
||||
const StyledTrContainer = styled.div`
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
div:not(:first-of-type) {
|
||||
border-bottom: ${({ theme, shouldDisplayBorderBottom }) =>
|
||||
shouldDisplayBorderBottom
|
||||
? `1px solid ${theme.border.color.light}`
|
||||
: 'none'};
|
||||
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -103,19 +95,14 @@ const StyledFieldPlaceholderCell = styled.div<{ widthOfFields: number }>`
|
||||
z-index: ${TABLE_Z_INDEX.groupSection.normalCell};
|
||||
`;
|
||||
|
||||
const StyledRecordTableDragAndDropPlaceholderCell = styled.div<{
|
||||
shouldDisplayBorderBottom: boolean;
|
||||
}>`
|
||||
const StyledRecordTableDragAndDropPlaceholderCell = 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: ${({ theme, shouldDisplayBorderBottom }) =>
|
||||
shouldDisplayBorderBottom
|
||||
? `1px solid ${theme.background.primary}`
|
||||
: 'none'};
|
||||
border-bottom: 1px solid ${({ theme }) => theme.background.primary};
|
||||
|
||||
position: sticky;
|
||||
left: 0;
|
||||
@@ -181,46 +168,13 @@ export const RecordTableRecordGroupSection = () => {
|
||||
sumOfWidthOfVisibleRecordFieldsAfterLabelIdentifierField +
|
||||
sumOfBorderWidthForFields;
|
||||
|
||||
const allRecordIds = useRecoilComponentValue(
|
||||
recordIndexAllRecordIdsComponentSelector,
|
||||
);
|
||||
|
||||
const recordIdsOfThisGroup = useRecoilComponentFamilyValue(
|
||||
recordIndexRecordIdsByGroupComponentFamilyState,
|
||||
recordGroup?.id ?? '',
|
||||
);
|
||||
|
||||
const indexOfFirstRowOfThisGroup = allRecordIds.findIndex(
|
||||
(value) => value === recordIdsOfThisGroup[0],
|
||||
);
|
||||
|
||||
const isFirstRowActive = useRecoilComponentFamilyValue(
|
||||
isRecordTableRowActiveComponentFamilyState,
|
||||
indexOfFirstRowOfThisGroup,
|
||||
);
|
||||
|
||||
const isFirstRowFocused = useRecoilComponentFamilyValue(
|
||||
isRecordTableRowFocusedComponentFamilyState,
|
||||
indexOfFirstRowOfThisGroup,
|
||||
);
|
||||
|
||||
const isFirstRowActiveOrFocused = isFirstRowActive || isFirstRowFocused;
|
||||
|
||||
const shouldDisplayBorderBottom =
|
||||
!isFirstRowActiveOrFocused || !isRecordGroupTableSectionToggled;
|
||||
|
||||
if (!isDefined(recordGroup)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledTrContainer
|
||||
onClick={handleDropdownToggle}
|
||||
shouldDisplayBorderBottom={shouldDisplayBorderBottom}
|
||||
>
|
||||
<StyledRecordTableDragAndDropPlaceholderCell
|
||||
shouldDisplayBorderBottom={shouldDisplayBorderBottom}
|
||||
/>
|
||||
<StyledTrContainer onClick={handleDropdownToggle}>
|
||||
<StyledRecordTableDragAndDropPlaceholderCell />
|
||||
<StyledChevronContainer>
|
||||
<StyledAnimatedLightIconButton
|
||||
Icon={IconChevronDown}
|
||||
|
||||
Reference in New Issue
Block a user