Add back first column shrink on mobile (#16244)
This PR fixes https://github.com/twentyhq/twenty/issues/14829 I created two states because one was needed for the table and the other for the ChipFieldDisplay, which can appear anywhere. The states tell if the first column and the ChipFieldDisplay should be shrinked. I also removed the usage of `useRecordTableLastColumnWidthToFill` to avoid unnecessary re-renders of the whole table on scroll. ## Before https://github.com/user-attachments/assets/8b6886b3-8976-41c2-9937-5d7ea396ec56 ## After https://github.com/user-attachments/assets/dc3b5ff9-59c4-4954-a973-57f6edc2508e
This commit is contained in:
+6
-4
@@ -1,8 +1,9 @@
|
||||
import { RecordChip } from '@/object-record/components/RecordChip';
|
||||
import { useChipFieldDisplay } from '@/object-record/record-field/ui/meta-types/hooks/useChipFieldDisplay';
|
||||
import { shouldCompactRecordIndexLabelIdentifierComponentState } from '@/object-record/record-index/states/shouldCompactRecordIndexLabelIdentifierComponentState';
|
||||
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';
|
||||
|
||||
export const ChipFieldDisplay = () => {
|
||||
const {
|
||||
@@ -15,10 +16,11 @@ export const ChipFieldDisplay = () => {
|
||||
onRecordChipClick,
|
||||
} = useChipFieldDisplay();
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
const shouldCompactRecordIndexLabelIdentifier = useRecoilComponentValue(
|
||||
shouldCompactRecordIndexLabelIdentifierComponentState,
|
||||
);
|
||||
|
||||
// TODO: reimplement scrolled horizontally here.
|
||||
const isLabelIdentifierCompact = isMobile;
|
||||
const isLabelIdentifierCompact = shouldCompactRecordIndexLabelIdentifier;
|
||||
|
||||
if (!isDefined(recordValue)) {
|
||||
return null;
|
||||
|
||||
+2
@@ -8,6 +8,7 @@ import { useRecordIndexFieldMetadataDerivedStates } from '@/object-record/record
|
||||
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
|
||||
import { ComponentDecorator } from 'twenty-ui/testing';
|
||||
import { ChipGeneratorsDecorator } from '~/testing/decorators/ChipGeneratorsDecorator';
|
||||
import { ContextStoreDecorator } from '~/testing/decorators/ContextStoreDecorator';
|
||||
import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorator';
|
||||
import { getFieldDecorator } from '~/testing/decorators/getFieldDecorator';
|
||||
import { getProfilingStory } from '~/testing/profiling/utils/getProfilingStory';
|
||||
@@ -16,6 +17,7 @@ import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockO
|
||||
const meta: Meta = {
|
||||
title: 'UI/Data/Field/Display/ChipFieldDisplay',
|
||||
decorators: [
|
||||
ContextStoreDecorator,
|
||||
(Story) => {
|
||||
const instanceId = 'child-field-display-scope';
|
||||
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
|
||||
export const shouldCompactRecordIndexLabelIdentifierComponentState =
|
||||
createComponentState<boolean>({
|
||||
key: 'shouldCompactRecordIndexLabelIdentifierComponentState',
|
||||
componentInstanceContext: ContextStoreComponentInstanceContext,
|
||||
defaultValue: false,
|
||||
});
|
||||
+66
-4
@@ -1,11 +1,21 @@
|
||||
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_VARIABLE_NAME } from '@/object-record/record-table/constants/RecordTableColumnLastEmptyColumnWidthVariableName';
|
||||
import { RECORD_TABLE_COLUMN_MIN_WIDTH } from '@/object-record/record-table/constants/RecordTableColumnMinWidth';
|
||||
import { RECORD_TABLE_COLUMN_WITH_GROUP_LAST_EMPTY_COLUMN_WIDTH_VARIABLE_NAME } from '@/object-record/record-table/constants/RecordTableColumnWithGroupLastEmptyColumnWidthVariableName';
|
||||
import { RECORD_TABLE_LABEL_IDENTIFIER_COLUMN_WIDTH_ON_MOBILE } from '@/object-record/record-table/constants/RecordTableLabelIdentifierColumnWidthOnMobile';
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { useRecordTableLastColumnWidthToFill } from '@/object-record/record-table/hooks/useRecordTableLastColumnWidthToFill';
|
||||
import { recordTableWidthComponentState } from '@/object-record/record-table/states/recordTableWidthComponentState';
|
||||
import { resizedFieldMetadataIdComponentState } from '@/object-record/record-table/states/resizedFieldMetadataIdComponentState';
|
||||
import { shouldCompactRecordTableFirstColumnComponentState } from '@/object-record/record-table/states/shouldCompactRecordTableFirstColumnComponentState';
|
||||
import { computeLastRecordTableColumnWidth } from '@/object-record/record-table/utils/computeLastRecordTableColumnWidth';
|
||||
import { computeVisibleRecordFieldsWidthOnTable } from '@/object-record/record-table/utils/computeVisibleRecordFieldsWidthOnTable';
|
||||
import { getRecordTableColumnFieldWidthCSSVariableName } from '@/object-record/record-table/utils/getRecordTableColumnFieldWidthCSSVariableName';
|
||||
import { updateRecordTableCSSVariable } from '@/object-record/record-table/utils/updateRecordTableCSSVariable';
|
||||
import { RECORD_TABLE_VIRTUALIZATION_BODY_PLACEHOLDER_WIDTH_CSS_VARIABLE_NAME } from '@/object-record/record-table/virtualization/components/RecordTableVirtualizedBodyPlaceholder';
|
||||
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@@ -15,15 +25,47 @@ export const RecordTableColumnWidthEffect = () => {
|
||||
resizedFieldMetadataIdComponentState,
|
||||
);
|
||||
|
||||
const { lastColumnWidth } = useRecordTableLastColumnWidthToFill();
|
||||
|
||||
const { visibleRecordFields } = useRecordTableContextOrThrow();
|
||||
|
||||
const shouldCompactRecordTableFirstColumn = useRecoilComponentValue(
|
||||
shouldCompactRecordTableFirstColumnComponentState,
|
||||
);
|
||||
|
||||
const recordTableWidth = useRecoilComponentValue(
|
||||
recordTableWidthComponentState,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDefined(resizedFieldMetadataItemId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { lastColumnWidth } = computeLastRecordTableColumnWidth({
|
||||
recordFields: visibleRecordFields,
|
||||
shouldCompactFirstColumn: shouldCompactRecordTableFirstColumn,
|
||||
tableWidth: recordTableWidth,
|
||||
});
|
||||
|
||||
const { visibleRecordFieldsWidth } = computeVisibleRecordFieldsWidthOnTable(
|
||||
{
|
||||
shouldCompactFirstColumn: shouldCompactRecordTableFirstColumn,
|
||||
visibleRecordFields,
|
||||
},
|
||||
);
|
||||
|
||||
const totalTableBodyWidth =
|
||||
visibleRecordFieldsWidth +
|
||||
RECORD_TABLE_COLUMN_DRAG_AND_DROP_WIDTH +
|
||||
RECORD_TABLE_COLUMN_CHECKBOX_WIDTH +
|
||||
RECORD_TABLE_COLUMN_ADD_COLUMN_BUTTON_WIDTH +
|
||||
lastColumnWidth +
|
||||
visibleRecordFields.length;
|
||||
|
||||
updateRecordTableCSSVariable(
|
||||
RECORD_TABLE_VIRTUALIZATION_BODY_PLACEHOLDER_WIDTH_CSS_VARIABLE_NAME,
|
||||
`${totalTableBodyWidth}px`,
|
||||
);
|
||||
|
||||
updateRecordTableCSSVariable(
|
||||
RECORD_TABLE_COLUMN_LAST_EMPTY_COLUMN_WIDTH_VARIABLE_NAME,
|
||||
`${lastColumnWidth}px`,
|
||||
@@ -40,7 +82,27 @@ export const RecordTableColumnWidthEffect = () => {
|
||||
`${recordField.size}px`,
|
||||
);
|
||||
}
|
||||
}, [lastColumnWidth, resizedFieldMetadataItemId, visibleRecordFields]);
|
||||
|
||||
if (shouldCompactRecordTableFirstColumn) {
|
||||
updateRecordTableCSSVariable(
|
||||
getRecordTableColumnFieldWidthCSSVariableName(0),
|
||||
`${RECORD_TABLE_LABEL_IDENTIFIER_COLUMN_WIDTH_ON_MOBILE}px`,
|
||||
);
|
||||
} else {
|
||||
const firstColumnWidth =
|
||||
visibleRecordFields[0]?.size ?? RECORD_TABLE_COLUMN_MIN_WIDTH;
|
||||
|
||||
updateRecordTableCSSVariable(
|
||||
getRecordTableColumnFieldWidthCSSVariableName(0),
|
||||
`${firstColumnWidth}px`,
|
||||
);
|
||||
}
|
||||
}, [
|
||||
resizedFieldMetadataItemId,
|
||||
visibleRecordFields,
|
||||
recordTableWidth,
|
||||
shouldCompactRecordTableFirstColumn,
|
||||
]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
-4
@@ -4,7 +4,6 @@ import { RecordTableStyleWrapper } from '@/object-record/record-table/components
|
||||
import { RecordTableWidthEffect } from '@/object-record/record-table/components/RecordTableWidthEffect';
|
||||
import { RECORD_TABLE_HTML_ID } from '@/object-record/record-table/constants/RecordTableHtmlId';
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { useRecordTableLastColumnWidthToFill } from '@/object-record/record-table/hooks/useRecordTableLastColumnWidthToFill';
|
||||
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';
|
||||
@@ -72,8 +71,6 @@ export const RecordTableContent = ({
|
||||
|
||||
const { visibleRecordFields } = useRecordTableContextOrThrow();
|
||||
|
||||
const { lastColumnWidth } = useRecordTableLastColumnWidthToFill();
|
||||
|
||||
const setRecordTableHoverPosition = useSetRecoilComponentState(
|
||||
recordTableHoverPositionComponentState,
|
||||
);
|
||||
@@ -103,7 +100,6 @@ export const RecordTableContent = ({
|
||||
ref={tableBodyRef}
|
||||
isDragging={isDragging}
|
||||
visibleRecordFields={visibleRecordFields}
|
||||
lastColumnWidth={lastColumnWidth}
|
||||
id={RECORD_TABLE_HTML_ID}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
hasRecordGroups={hasRecordGroups}
|
||||
|
||||
+5
-7
@@ -8,17 +8,16 @@ import { RECORD_TABLE_COLUMN_DRAG_AND_DROP_WIDTH } from '@/object-record/record-
|
||||
import { RECORD_TABLE_HTML_ID } from '@/object-record/record-table/constants/RecordTableHtmlId';
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { RecordTableEmptyState } from '@/object-record/record-table/empty-state/components/RecordTableEmptyState';
|
||||
import { useRecordTableLastColumnWidthToFill } from '@/object-record/record-table/hooks/useRecordTableLastColumnWidthToFill';
|
||||
import { RecordTableHeader } from '@/object-record/record-table/record-table-header/components/RecordTableHeader';
|
||||
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 { shouldCompactRecordTableFirstColumnComponentState } from '@/object-record/record-table/states/shouldCompactRecordTableFirstColumnComponentState';
|
||||
import { computeVisibleRecordFieldsWidthOnTable } from '@/object-record/record-table/utils/computeVisibleRecordFieldsWidthOnTable';
|
||||
import { RecordTableVirtualizedDataChangedEffect } from '@/object-record/record-table/virtualization/components/RecordTableVirtualizedDataChangedEffect';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import styled from '@emotion/styled';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { useIsMobile } from 'twenty-ui/utilities';
|
||||
|
||||
const StyledEmptyStateContainer = styled.div<{ width: number }>`
|
||||
height: 100%;
|
||||
@@ -47,7 +46,9 @@ export const RecordTableEmpty = ({ tableBodyRef }: RecordTableEmptyProps) => {
|
||||
|
||||
const isResizing = isDefined(resizedFieldMetadataId);
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
const shouldCompactRecordTableFirstColumn = useRecoilComponentValue(
|
||||
shouldCompactRecordTableFirstColumnComponentState,
|
||||
);
|
||||
|
||||
const resizeOffsetToAddOnlyIfItMakesTableContainerGrow = isResizing
|
||||
? resizeFieldOffset > 0
|
||||
@@ -58,12 +59,10 @@ export const RecordTableEmpty = ({ tableBodyRef }: RecordTableEmptyProps) => {
|
||||
const totalColumnsBorderWidth = visibleRecordFields.length;
|
||||
|
||||
const { visibleRecordFieldsWidth } = computeVisibleRecordFieldsWidthOnTable({
|
||||
isMobile,
|
||||
shouldCompactFirstColumn: shouldCompactRecordTableFirstColumn,
|
||||
visibleRecordFields,
|
||||
});
|
||||
|
||||
const { lastColumnWidth } = useRecordTableLastColumnWidthToFill();
|
||||
|
||||
const emptyTableContainerComputedWidth =
|
||||
visibleRecordFieldsWidth +
|
||||
RECORD_TABLE_COLUMN_CHECKBOX_WIDTH +
|
||||
@@ -86,7 +85,6 @@ export const RecordTableEmpty = ({ tableBodyRef }: RecordTableEmptyProps) => {
|
||||
<RecordTableStyleWrapper
|
||||
ref={tableBodyRef}
|
||||
visibleRecordFields={visibleRecordFields}
|
||||
lastColumnWidth={lastColumnWidth}
|
||||
id={RECORD_TABLE_HTML_ID}
|
||||
hasRecordGroups={hasRecordGroups}
|
||||
>
|
||||
|
||||
+26
-1
@@ -1,23 +1,35 @@
|
||||
import { shouldCompactRecordIndexLabelIdentifierComponentState } from '@/object-record/record-index/states/shouldCompactRecordIndexLabelIdentifierComponentState';
|
||||
import { RECORD_TABLE_HORIZONTAL_SCROLL_SHADOW_VISIBILITY_CSS_VARIABLE_NAME } from '@/object-record/record-table/constants/RecordTableHorizontalScrollShadowVisibilityCssVariableName';
|
||||
import { RECORD_TABLE_VERTICAL_SCROLL_SHADOW_VISIBILITY_CSS_VARIABLE_NAME } from '@/object-record/record-table/constants/RecordTableVerticalScrollShadowVisibilityCssVariableName';
|
||||
import { isRecordTableScrolledHorizontallyComponentState } from '@/object-record/record-table/states/isRecordTableScrolledHorizontallyComponentState';
|
||||
import { isRecordTableScrolledVerticallyComponentState } from '@/object-record/record-table/states/isRecordTableScrolledVerticallyComponentState';
|
||||
import { shouldCompactRecordTableFirstColumnComponentState } from '@/object-record/record-table/states/shouldCompactRecordTableFirstColumnComponentState';
|
||||
import { updateRecordTableCSSVariable } from '@/object-record/record-table/utils/updateRecordTableCSSVariable';
|
||||
|
||||
import { useScrollWrapperHTMLElement } from '@/ui/utilities/scroll/hooks/useScrollWrapperHTMLElement';
|
||||
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
|
||||
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { useIsMobile } from 'twenty-ui/utilities';
|
||||
|
||||
export const RecordTableScrollAndZIndexEffect = () => {
|
||||
const { scrollWrapperHTMLElement } = useScrollWrapperHTMLElement();
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
const [
|
||||
isRecordTableScrolledHorizontally,
|
||||
setIsRecordTableScrolledHorizontally,
|
||||
] = useRecoilComponentState(isRecordTableScrolledHorizontallyComponentState);
|
||||
|
||||
const setShouldCompactRecordTableFirstColumn = useSetRecoilComponentState(
|
||||
shouldCompactRecordTableFirstColumnComponentState,
|
||||
);
|
||||
|
||||
const setShouldCompactRecordIndexLabelIdentifier = useSetRecoilComponentState(
|
||||
shouldCompactRecordIndexLabelIdentifierComponentState,
|
||||
);
|
||||
|
||||
const [isRecordTableScrolledVertically, setIsRecordTableScrolledVertically] =
|
||||
useRecoilComponentState(isRecordTableScrolledVerticallyComponentState);
|
||||
|
||||
@@ -57,6 +69,16 @@ export const RecordTableScrollAndZIndexEffect = () => {
|
||||
RECORD_TABLE_HORIZONTAL_SCROLL_SHADOW_VISIBILITY_CSS_VARIABLE_NAME,
|
||||
newVisibilityOfShadows,
|
||||
);
|
||||
|
||||
if (isMobile) {
|
||||
if (newIsScrolledHorizontally) {
|
||||
setShouldCompactRecordTableFirstColumn(true);
|
||||
setShouldCompactRecordIndexLabelIdentifier(true);
|
||||
} else {
|
||||
setShouldCompactRecordTableFirstColumn(false);
|
||||
setShouldCompactRecordIndexLabelIdentifier(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -71,6 +93,9 @@ export const RecordTableScrollAndZIndexEffect = () => {
|
||||
isRecordTableScrolledHorizontally,
|
||||
setIsRecordTableScrolledVertically,
|
||||
setIsRecordTableScrolledHorizontally,
|
||||
isMobile,
|
||||
setShouldCompactRecordTableFirstColumn,
|
||||
setShouldCompactRecordIndexLabelIdentifier,
|
||||
]);
|
||||
|
||||
return <></>;
|
||||
|
||||
+5
-29
@@ -10,7 +10,6 @@ import { RECORD_TABLE_COLUMN_LAST_EMPTY_COLUMN_WIDTH_VARIABLE_NAME } from '@/obj
|
||||
import { RECORD_TABLE_COLUMN_WITH_GROUP_LAST_EMPTY_COLUMN_WIDTH_CLASS_NAME } from '@/object-record/record-table/constants/RecordTableColumnWithGroupLastEmptyColumnWidthClassName';
|
||||
import { RECORD_TABLE_COLUMN_WITH_GROUP_LAST_EMPTY_COLUMN_WIDTH_VARIABLE_NAME } from '@/object-record/record-table/constants/RecordTableColumnWithGroupLastEmptyColumnWidthVariableName';
|
||||
import { RECORD_TABLE_HORIZONTAL_SCROLL_SHADOW_VISIBILITY_CSS_VARIABLE_NAME } from '@/object-record/record-table/constants/RecordTableHorizontalScrollShadowVisibilityCssVariableName';
|
||||
import { RECORD_TABLE_LABEL_IDENTIFIER_COLUMN_WIDTH_ON_MOBILE } from '@/object-record/record-table/constants/RecordTableLabelIdentifierColumnWidthOnMobile';
|
||||
import { RECORD_TABLE_VERTICAL_SCROLL_SHADOW_VISIBILITY_CSS_VARIABLE_NAME } from '@/object-record/record-table/constants/RecordTableVerticalScrollShadowVisibilityCssVariableName';
|
||||
|
||||
import { TABLE_Z_INDEX } from '@/object-record/record-table/constants/TableZIndex';
|
||||
@@ -18,7 +17,6 @@ import { getRecordTableColumnFieldWidthClassName } from '@/object-record/record-
|
||||
import { getRecordTableColumnFieldWidthCSSVariableName } from '@/object-record/record-table/utils/getRecordTableColumnFieldWidthCSSVariableName';
|
||||
import { css, type Theme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
|
||||
|
||||
export const VerticalScrollBoxShadowCSS = ({ theme }: { theme: Theme }) => css`
|
||||
&::before {
|
||||
@@ -64,7 +62,6 @@ export const HorizontalScrollBoxShadowCSS = ({
|
||||
const StyledTable = styled.div<{
|
||||
isDragging?: boolean;
|
||||
visibleRecordFields: RecordField[];
|
||||
lastColumnWidth: number;
|
||||
hasRecordGroups: boolean;
|
||||
}>`
|
||||
& > * {
|
||||
@@ -128,12 +125,6 @@ const StyledTable = styled.div<{
|
||||
: TABLE_Z_INDEX.headerColumns.withoutGroups.headerColumnsSticky};
|
||||
|
||||
${HorizontalScrollBoxShadowCSS}
|
||||
|
||||
@media (max-width: ${MOBILE_VIEWPORT}px) {
|
||||
width: ${RECORD_TABLE_LABEL_IDENTIFIER_COLUMN_WIDTH_ON_MOBILE}px;
|
||||
max-width: ${RECORD_TABLE_LABEL_IDENTIFIER_COLUMN_WIDTH_ON_MOBILE}px;
|
||||
min-width: ${RECORD_TABLE_LABEL_IDENTIFIER_COLUMN_WIDTH_ON_MOBILE}px;
|
||||
}
|
||||
}
|
||||
|
||||
div.table-cell:nth-of-type(1) {
|
||||
@@ -192,7 +183,7 @@ const StyledTable = styled.div<{
|
||||
max-width: ${RECORD_TABLE_COLUMN_ADD_COLUMN_BUTTON_WIDTH}px;
|
||||
}
|
||||
|
||||
${({ visibleRecordFields, lastColumnWidth }) => {
|
||||
${({ visibleRecordFields }) => {
|
||||
let returnedCSS = '';
|
||||
|
||||
for (let i = 0; i < visibleRecordFields.length; i++) {
|
||||
@@ -200,28 +191,13 @@ const StyledTable = styled.div<{
|
||||
}
|
||||
|
||||
for (let i = 0; i < visibleRecordFields.length; i++) {
|
||||
returnedCSS += `div.${getRecordTableColumnFieldWidthClassName(i)} {
|
||||
width: var(${getRecordTableColumnFieldWidthCSSVariableName(i)});
|
||||
min-width: var(${getRecordTableColumnFieldWidthCSSVariableName(i)});
|
||||
max-width: var(${getRecordTableColumnFieldWidthCSSVariableName(i)});
|
||||
returnedCSS += `div.${getRecordTableColumnFieldWidthClassName(i)} {
|
||||
width: var(${getRecordTableColumnFieldWidthCSSVariableName(i)});
|
||||
min-width: var(${getRecordTableColumnFieldWidthCSSVariableName(i)});
|
||||
max-width: var(${getRecordTableColumnFieldWidthCSSVariableName(i)});
|
||||
} \n`;
|
||||
|
||||
const isLabelIdentifierColumn = i === 0;
|
||||
|
||||
if (isLabelIdentifierColumn) {
|
||||
returnedCSS += `div.${getRecordTableColumnFieldWidthClassName(i)} {
|
||||
@media (max-width: ${MOBILE_VIEWPORT}px) {
|
||||
width: ${RECORD_TABLE_LABEL_IDENTIFIER_COLUMN_WIDTH_ON_MOBILE}px;
|
||||
max-width: ${RECORD_TABLE_LABEL_IDENTIFIER_COLUMN_WIDTH_ON_MOBILE}px;
|
||||
min-width: ${RECORD_TABLE_LABEL_IDENTIFIER_COLUMN_WIDTH_ON_MOBILE}px;
|
||||
}
|
||||
} \n`;
|
||||
}
|
||||
}
|
||||
|
||||
returnedCSS += `${RECORD_TABLE_COLUMN_LAST_EMPTY_COLUMN_WIDTH_VARIABLE_NAME}: ${lastColumnWidth}px;`;
|
||||
returnedCSS += `${RECORD_TABLE_COLUMN_WITH_GROUP_LAST_EMPTY_COLUMN_WIDTH_VARIABLE_NAME}: ${lastColumnWidth}px;`;
|
||||
|
||||
return returnedCSS;
|
||||
}};
|
||||
|
||||
|
||||
+5
-3
@@ -1,8 +1,8 @@
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { recordTableWidthComponentState } from '@/object-record/record-table/states/recordTableWidthComponentState';
|
||||
import { shouldCompactRecordTableFirstColumnComponentState } from '@/object-record/record-table/states/shouldCompactRecordTableFirstColumnComponentState';
|
||||
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();
|
||||
@@ -11,12 +11,14 @@ export const useRecordTableLastColumnWidthToFill = () => {
|
||||
recordTableWidthComponentState,
|
||||
);
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
const shouldCompactRecordTableFirstColumn = useRecoilComponentValue(
|
||||
shouldCompactRecordTableFirstColumnComponentState,
|
||||
);
|
||||
|
||||
const { lastColumnWidth } = computeLastRecordTableColumnWidth({
|
||||
recordFields: visibleRecordFields,
|
||||
tableWidth: recordTableWidth,
|
||||
isMobile,
|
||||
shouldCompactFirstColumn: shouldCompactRecordTableFirstColumn,
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
+9
-2
@@ -4,6 +4,8 @@ import styled from '@emotion/styled';
|
||||
import { fieldMetadataItemByIdSelector } from '@/object-metadata/states/fieldMetadataItemByIdSelector';
|
||||
import { isFieldMetadataItemLabelIdentifierSelector } from '@/object-metadata/states/isFieldMetadataItemLabelIdentifierSelector';
|
||||
import { type RecordField } from '@/object-record/record-field/types/RecordField';
|
||||
import { shouldCompactRecordTableFirstColumnComponentState } from '@/object-record/record-table/states/shouldCompactRecordTableFirstColumnComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
|
||||
@@ -69,10 +71,15 @@ export const RecordTableColumnHead = ({
|
||||
}),
|
||||
);
|
||||
|
||||
// TODO: fix previous behavior with isRecordTableScrolledHorizontally
|
||||
const shouldCompactRecordTableFirstColumn = useRecoilComponentValue(
|
||||
shouldCompactRecordTableFirstColumnComponentState,
|
||||
);
|
||||
|
||||
const shouldHideTitle =
|
||||
shouldCompactRecordTableFirstColumn && isLabelIdentifier;
|
||||
|
||||
return (
|
||||
<StyledTitle hideTitle={isLabelIdentifier}>
|
||||
<StyledTitle hideTitle={shouldHideTitle}>
|
||||
<StyledIcon>
|
||||
<Icon size={theme.icon.size.md} />
|
||||
</StyledIcon>
|
||||
|
||||
+20
-4
@@ -5,10 +5,12 @@ import { RECORD_TABLE_COLUMN_MIN_WIDTH } from '@/object-record/record-table/cons
|
||||
import { RECORD_TABLE_COLUMN_WITH_GROUP_LAST_EMPTY_COLUMN_WIDTH_VARIABLE_NAME } from '@/object-record/record-table/constants/RecordTableColumnWithGroupLastEmptyColumnWidthVariableName';
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { useResetTableRowSelection } from '@/object-record/record-table/hooks/internal/useResetTableRowSelection';
|
||||
import { useRecordTableLastColumnWidthToFill } from '@/object-record/record-table/hooks/useRecordTableLastColumnWidthToFill';
|
||||
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 { shouldCompactRecordTableFirstColumnComponentState } from '@/object-record/record-table/states/shouldCompactRecordTableFirstColumnComponentState';
|
||||
import { computeLastRecordTableColumnWidth } from '@/object-record/record-table/utils/computeLastRecordTableColumnWidth';
|
||||
import { getRecordTableColumnFieldWidthCSSVariableName } from '@/object-record/record-table/utils/getRecordTableColumnFieldWidthCSSVariableName';
|
||||
import { updateRecordTableCSSVariable } from '@/object-record/record-table/utils/updateRecordTableCSSVariable';
|
||||
import { useDragSelect } from '@/ui/utilities/drag-select/hooks/useDragSelect';
|
||||
@@ -16,6 +18,7 @@ import { useTrackPointer } from '@/ui/utilities/pointer-event/hooks/useTrackPoin
|
||||
import { type PointerEventListener } from '@/ui/utilities/pointer-event/types/PointerEventListener';
|
||||
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
|
||||
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
|
||||
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
|
||||
import { useSaveRecordFields } from '@/views/hooks/useSaveRecordFields';
|
||||
@@ -55,7 +58,13 @@ export const useResizeTableHeader = () => {
|
||||
|
||||
const { updateRecordField } = useUpdateRecordField();
|
||||
|
||||
const { lastColumnWidth } = useRecordTableLastColumnWidthToFill();
|
||||
const recordTableWidth = useRecoilComponentValue(
|
||||
recordTableWidthComponentState,
|
||||
);
|
||||
|
||||
const shouldCompactRecordTableFirstColumn = useRecoilComponentValue(
|
||||
shouldCompactRecordTableFirstColumnComponentState,
|
||||
);
|
||||
|
||||
const handleResizeHandlerStart = useCallback<PointerEventListener>(
|
||||
({ x }) => {
|
||||
@@ -90,6 +99,12 @@ export const useResizeTableHeader = () => {
|
||||
`${newWidth}px`,
|
||||
);
|
||||
|
||||
const { lastColumnWidth } = computeLastRecordTableColumnWidth({
|
||||
recordFields: visibleRecordFields,
|
||||
shouldCompactFirstColumn: shouldCompactRecordTableFirstColumn,
|
||||
tableWidth: recordTableWidth,
|
||||
});
|
||||
|
||||
const newLastColumnWidth = lastColumnWidth - newResizeOffset;
|
||||
|
||||
updateRecordTableCSSVariable(
|
||||
@@ -110,11 +125,12 @@ export const useResizeTableHeader = () => {
|
||||
setResizeFieldOffset(x - initialPointerPositionX);
|
||||
},
|
||||
[
|
||||
setResizeFieldOffset,
|
||||
initialPointerPositionX,
|
||||
recordField,
|
||||
lastColumnWidth,
|
||||
visibleRecordFields,
|
||||
shouldCompactRecordTableFirstColumn,
|
||||
recordTableWidth,
|
||||
setResizeFieldOffset,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
|
||||
export const shouldCompactRecordTableFirstColumnComponentState =
|
||||
createComponentState<boolean>({
|
||||
key: 'shouldCompactRecordTableFirstColumnComponentState',
|
||||
componentInstanceContext: RecordTableComponentInstanceContext,
|
||||
defaultValue: false,
|
||||
});
|
||||
+3
-3
@@ -7,14 +7,14 @@ import { computeVisibleRecordFieldsWidthOnTable } from '@/object-record/record-t
|
||||
export const computeLastRecordTableColumnWidth = ({
|
||||
recordFields,
|
||||
tableWidth,
|
||||
isMobile,
|
||||
shouldCompactFirstColumn,
|
||||
}: {
|
||||
recordFields: Pick<RecordField, 'size'>[];
|
||||
tableWidth: number;
|
||||
isMobile: boolean;
|
||||
shouldCompactFirstColumn: boolean;
|
||||
}) => {
|
||||
const { visibleRecordFieldsWidth } = computeVisibleRecordFieldsWidthOnTable({
|
||||
isMobile,
|
||||
shouldCompactFirstColumn,
|
||||
visibleRecordFields: recordFields,
|
||||
});
|
||||
|
||||
|
||||
+7
-5
@@ -3,10 +3,10 @@ import { RECORD_TABLE_LABEL_IDENTIFIER_COLUMN_WIDTH_ON_MOBILE } from '@/object-r
|
||||
import { sumByProperty } from 'twenty-shared/utils';
|
||||
|
||||
export const computeVisibleRecordFieldsWidthOnTable = ({
|
||||
isMobile,
|
||||
shouldCompactFirstColumn,
|
||||
visibleRecordFields,
|
||||
}: {
|
||||
isMobile: boolean;
|
||||
shouldCompactFirstColumn: boolean;
|
||||
visibleRecordFields: Pick<RecordField, 'size'>[];
|
||||
}) => {
|
||||
const visibleRecordFieldsWithoutFirst = visibleRecordFields.slice(1);
|
||||
@@ -18,12 +18,14 @@ export const computeVisibleRecordFieldsWidthOnTable = ({
|
||||
|
||||
const sumWithAllFields = visibleRecordFields.reduce(sumByProperty('size'), 0);
|
||||
|
||||
const sumForMobile =
|
||||
const sumForCompactedFirstColumn =
|
||||
RECORD_TABLE_LABEL_IDENTIFIER_COLUMN_WIDTH_ON_MOBILE + sumWithoutFirstField;
|
||||
|
||||
const sumForNonMobile = sumWithAllFields;
|
||||
const sumForNoCompactColumn = sumWithAllFields;
|
||||
|
||||
const visibleRecordFieldsWidth = isMobile ? sumForMobile : sumForNonMobile;
|
||||
const visibleRecordFieldsWidth = shouldCompactFirstColumn
|
||||
? sumForCompactedFirstColumn
|
||||
: sumForNoCompactColumn;
|
||||
|
||||
return {
|
||||
visibleRecordFieldsWidth,
|
||||
|
||||
+7
-31
@@ -1,54 +1,30 @@
|
||||
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_ROW_HEIGHT } from '@/object-record/record-table/constants/RecordTableRowHeight';
|
||||
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { useRecordTableLastColumnWidthToFill } from '@/object-record/record-table/hooks/useRecordTableLastColumnWidthToFill';
|
||||
import { computeVisibleRecordFieldsWidthOnTable } from '@/object-record/record-table/utils/computeVisibleRecordFieldsWidthOnTable';
|
||||
import { totalNumberOfRecordsToVirtualizeComponentState } from '@/object-record/record-table/virtualization/states/totalNumberOfRecordsToVirtualizeComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { styled } from '@linaria/react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { useIsMobile } from 'twenty-ui/utilities';
|
||||
|
||||
export const RECORD_TABLE_VIRTUALIZATION_BODY_PLACEHOLDER_WIDTH_CSS_VARIABLE_NAME =
|
||||
'--record-table-virtualization-body-placeholder-width';
|
||||
|
||||
const StyledVirtualizationContainer = styled.div<{
|
||||
width: number;
|
||||
height: number;
|
||||
}>`
|
||||
height: ${({ height }) => height}px;
|
||||
width: ${({ width }) => width}px;
|
||||
width: var(
|
||||
${RECORD_TABLE_VIRTUALIZATION_BODY_PLACEHOLDER_WIDTH_CSS_VARIABLE_NAME}
|
||||
);
|
||||
`;
|
||||
|
||||
export const RecordTableVirtualizedBodyPlaceholder = () => {
|
||||
const { visibleRecordFields } = useRecordTableContextOrThrow();
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
const { visibleRecordFieldsWidth } = computeVisibleRecordFieldsWidthOnTable({
|
||||
isMobile,
|
||||
visibleRecordFields,
|
||||
});
|
||||
|
||||
const totalNumberOfRecordsToVirtualize = useRecoilComponentValue(
|
||||
totalNumberOfRecordsToVirtualizeComponentState,
|
||||
);
|
||||
|
||||
const { lastColumnWidth } = useRecordTableLastColumnWidthToFill();
|
||||
|
||||
const totalWidth =
|
||||
visibleRecordFieldsWidth +
|
||||
RECORD_TABLE_COLUMN_DRAG_AND_DROP_WIDTH +
|
||||
RECORD_TABLE_COLUMN_CHECKBOX_WIDTH +
|
||||
RECORD_TABLE_COLUMN_ADD_COLUMN_BUTTON_WIDTH +
|
||||
lastColumnWidth +
|
||||
visibleRecordFields.length;
|
||||
|
||||
const totalHeight = isDefined(totalNumberOfRecordsToVirtualize)
|
||||
? totalNumberOfRecordsToVirtualize * (RECORD_TABLE_ROW_HEIGHT + 1)
|
||||
: 0;
|
||||
|
||||
return (
|
||||
<StyledVirtualizationContainer width={totalWidth} height={totalHeight} />
|
||||
);
|
||||
return <StyledVirtualizationContainer height={totalHeight} />;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user