Fix table column width on mobile (#14623)

This PR fixes some minor issues to have all width computation working
properly and table displaying nicely on mobile.
This commit is contained in:
Lucas Bordeau
2025-09-22 10:18:12 +02:00
committed by GitHub
parent d308f5adf9
commit d6e4bcb533
6 changed files with 82 additions and 22 deletions
@@ -13,9 +13,11 @@ import { RecordTableHeader } from '@/object-record/record-table/record-table-hea
import { recordTableWidthComponentState } from '@/object-record/record-table/states/recordTableWidthComponentState';
import { resizedFieldMetadataIdComponentState } from '@/object-record/record-table/states/resizedFieldMetadataIdComponentState';
import { resizeFieldOffsetComponentState } from '@/object-record/record-table/states/resizeFieldOffsetComponentState';
import { computeVisibleRecordFieldsWidthOnTable } from '@/object-record/record-table/utils/computeVisibleRecordFieldsWidthOnTable';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import styled from '@emotion/styled';
import { isDefined, sumByProperty } from 'twenty-shared/utils';
import { isDefined } from 'twenty-shared/utils';
import { useIsMobile } from 'twenty-ui/utilities';
const StyledEmptyStateContainer = styled.div<{ width: number }>`
height: 100%;
@@ -44,23 +46,25 @@ export const RecordTableEmpty = ({ tableBodyRef }: RecordTableEmptyProps) => {
const isResizing = isDefined(resizedFieldMetadataId);
const isMobile = useIsMobile();
const resizeOffsetToAddOnlyIfItMakesTableContainerGrow = isResizing
? resizeFieldOffset > 0
? resizeFieldOffset
: 0
: 0;
const totalWidthOfRecordFieldColumns = visibleRecordFields.reduce(
sumByProperty('size'),
0,
);
const totalColumnsBorderWidth = visibleRecordFields.length;
const { visibleRecordFieldsWidth } = computeVisibleRecordFieldsWidthOnTable({
isMobile,
visibleRecordFields,
});
const { lastColumnWidth } = useRecordTableLastColumnWidthToFill();
const emptyTableContainerComputedWidth =
totalWidthOfRecordFieldColumns +
visibleRecordFieldsWidth +
RECORD_TABLE_COLUMN_CHECKBOX_WIDTH +
RECORD_TABLE_COLUMN_DRAG_AND_DROP_WIDTH +
RECORD_TABLE_COLUMN_ADD_COLUMN_BUTTON_WIDTH +
@@ -2,6 +2,7 @@ import { useRecordTableContextOrThrow } from '@/object-record/record-table/conte
import { recordTableWidthComponentState } from '@/object-record/record-table/states/recordTableWidthComponentState';
import { computeLastRecordTableColumnWidth } from '@/object-record/record-table/utils/computeLastRecordTableColumnWidth';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useIsMobile } from 'twenty-ui/utilities';
export const useRecordTableLastColumnWidthToFill = () => {
const { visibleRecordFields } = useRecordTableContextOrThrow();
@@ -10,9 +11,12 @@ export const useRecordTableLastColumnWidthToFill = () => {
recordTableWidthComponentState,
);
const isMobile = useIsMobile();
const { lastColumnWidth } = computeLastRecordTableColumnWidth({
recordFields: visibleRecordFields,
tableWidth: recordTableWidth,
isMobile,
});
return {
@@ -3,6 +3,8 @@ 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_COLUMN_DRAG_AND_DROP_WIDTH } from '@/object-record/record-table/constants/RecordTableColumnDragAndDropWidth';
import { RECORD_TABLE_COLUMN_MIN_WIDTH } from '@/object-record/record-table/constants/RecordTableColumnMinWidth';
import { RECORD_TABLE_LABEL_IDENTIFIER_COLUMN_WIDTH_ON_MOBILE } from '@/object-record/record-table/constants/RecordTableLabelIdentifierColumnWidthOnMobile';
import { RECORD_TABLE_ROW_HEIGHT } from '@/object-record/record-table/constants/RecordTableRowHeight';
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
import { RecordTableDragAndDropPlaceholderCell } from '@/object-record/record-table/record-table-cell/components/RecordTableDragAndDropPlaceholderCell';
@@ -15,6 +17,7 @@ import {
sumByProperty,
} from 'twenty-shared/utils';
import { type IconComponent } from 'twenty-ui/display';
import { useIsMobile } from 'twenty-ui/utilities';
const StyledDragDropPlaceholderCell = styled(
RecordTableDragAndDropPlaceholderCell,
@@ -85,8 +88,11 @@ const StyledText = styled.span`
color: ${({ theme }) => theme.font.color.tertiary};
margin-left: ${({ theme }) => theme.spacing(2)};
font-size: ${({ theme }) => theme.font.size.md};
text-align: center;
text-align: left;
vertical-align: middle;
position: absolute;
width: 100px;
`;
type RecordTableActionRowProps = {
@@ -112,10 +118,16 @@ export const RecordTableActionRow = ({
),
);
const isMobile = useIsMobile();
const labelIdentifierRecordField = visibleRecordFields.find(
findByProperty('fieldMetadataItemId', labelIdentifierFieldMetadataItem?.id),
);
const firstColumnWidth = isMobile
? RECORD_TABLE_LABEL_IDENTIFIER_COLUMN_WIDTH_ON_MOBILE
: (labelIdentifierRecordField?.size ?? RECORD_TABLE_COLUMN_MIN_WIDTH);
const sumOfWidthOfVisibleRecordFieldsAfterLabelIdentifierField =
visibleRecordFieldsWithoutLabelIdentifier.reduce(sumByProperty('size'), 0);
@@ -132,9 +144,7 @@ export const RecordTableActionRow = ({
color={theme.font.color.tertiary}
/>
</StyledIconContainer>
<StyledActionTextContainer
width={labelIdentifierRecordField?.size ?? 104}
>
<StyledActionTextContainer width={firstColumnWidth}>
<StyledText>{text}</StyledText>
</StyledActionTextContainer>
<StyledFieldPlaceholderCell
@@ -18,6 +18,8 @@ import { RecordTableAddButtonPlaceholderCell } from '@/object-record/record-tabl
import { RecordTableGroupSectionLastDynamicFillingCell } from '@/object-record/record-table/record-table-row/components/RecordTableGroupSectionLastDynamicFillingCell';
import { RECORD_TABLE_COLUMN_CHECKBOX_WIDTH } from '@/object-record/record-table/constants/RecordTableColumnCheckboxWidth';
import { RECORD_TABLE_COLUMN_MIN_WIDTH } from '@/object-record/record-table/constants/RecordTableColumnMinWidth';
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';
@@ -35,6 +37,7 @@ import {
import { Tag } from 'twenty-ui/components';
import { IconChevronDown } from 'twenty-ui/display';
import { AnimatedLightIconButton } from 'twenty-ui/input';
import { useIsMobile } from 'twenty-ui/utilities';
const StyledTrContainer = styled.div<{ shouldDisplayBorderBottom: boolean }>`
cursor: pointer;
@@ -135,13 +138,16 @@ export const RecordTableRecordGroupSection = () => {
visibleRecordFieldsComponentSelector,
);
const widthOfLabelIdentifierRecordField =
visibleRecordFields.find(
findByProperty(
'fieldMetadataItemId',
labelIdentifierFieldMetadataItem?.id ?? '',
),
)?.size ?? null;
const isMobile = useIsMobile();
const widthOfLabelIdentifierRecordField = isMobile
? RECORD_TABLE_LABEL_IDENTIFIER_COLUMN_WIDTH_ON_MOBILE
: (visibleRecordFields.find(
findByProperty(
'fieldMetadataItemId',
labelIdentifierFieldMetadataItem?.id ?? '',
),
)?.size ?? RECORD_TABLE_COLUMN_MIN_WIDTH);
const [
isRecordGroupTableSectionToggled,
@@ -226,7 +232,7 @@ export const RecordTableRecordGroupSection = () => {
</StyledChevronContainer>
<StyledRecordGroupSection
className="disable-shadow"
width={widthOfLabelIdentifierRecordField ?? 104}
width={widthOfLabelIdentifierRecordField}
>
<StyledTag
variant={
@@ -2,16 +2,21 @@ import { type RecordField } from '@/object-record/record-field/types/RecordField
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 { sumByProperty } from 'twenty-shared/utils';
import { computeVisibleRecordFieldsWidthOnTable } from '@/object-record/record-table/utils/computeVisibleRecordFieldsWidthOnTable';
export const computeLastRecordTableColumnWidth = ({
recordFields,
tableWidth,
isMobile,
}: {
recordFields: Pick<RecordField, 'size'>[];
tableWidth: number;
isMobile: boolean;
}) => {
const totalColumnsWidth = recordFields.reduce(sumByProperty('size'), 0);
const { visibleRecordFieldsWidth } = computeVisibleRecordFieldsWidthOnTable({
isMobile,
visibleRecordFields: recordFields,
});
const widthOfBorders = recordFields.length;
@@ -23,7 +28,7 @@ export const computeLastRecordTableColumnWidth = ({
const remainingWidthToFill = Math.max(
0,
tableWidth - fixedColumnsWidth - totalColumnsWidth,
tableWidth - fixedColumnsWidth - visibleRecordFieldsWidth,
);
const lastColumnWidth = remainingWidthToFill;
@@ -0,0 +1,31 @@
import { type RecordField } from '@/object-record/record-field/types/RecordField';
import { RECORD_TABLE_LABEL_IDENTIFIER_COLUMN_WIDTH_ON_MOBILE } from '@/object-record/record-table/constants/RecordTableLabelIdentifierColumnWidthOnMobile';
import { sumByProperty } from 'twenty-shared/utils';
export const computeVisibleRecordFieldsWidthOnTable = ({
isMobile,
visibleRecordFields,
}: {
isMobile: boolean;
visibleRecordFields: Pick<RecordField, 'size'>[];
}) => {
const visibleRecordFieldsWithoutFirst = visibleRecordFields.slice(1);
const sumWithoutFirstField = visibleRecordFieldsWithoutFirst.reduce(
sumByProperty('size'),
0,
);
const sumWithAllFields = visibleRecordFields.reduce(sumByProperty('size'), 0);
const sumForMobile =
RECORD_TABLE_LABEL_IDENTIFIER_COLUMN_WIDTH_ON_MOBILE + sumWithoutFirstField;
const sumForNonMobile = sumWithAllFields;
const visibleRecordFieldsWidth = isMobile ? sumForMobile : sumForNonMobile;
return {
visibleRecordFieldsWidth,
};
};