From b4e386192da07f4752ed662dce9fed8d5fca2c89 Mon Sep 17 00:00:00 2001 From: Lucas Bordeau Date: Thu, 18 Sep 2025 11:29:33 +0200 Subject: [PATCH] Table small fixes (#14588) This PR brings more UX fixes for table. Fixes in https://github.com/twentyhq/core-team-issues/issues/1490 : - Fix any field filter chip formatting - Empty placeholder should be centered on screenwidth and not scrollable width on table - First cell is automatically active on table but we can't move => We now allow focus position to be null as it is a portal Fixes https://github.com/twentyhq/twenty/issues/14573 --- .../RecordTableEmptyStateDisplay.tsx | 67 ++++++++++++------- .../hooks/internal/useLeaveTableFocus.ts | 7 ++ .../hooks/useRecordTableMoveFocusedCell.ts | 18 +++++ .../RecordTableCellArrowKeysEffect.tsx | 11 +-- .../RecordTableCellEditModePortal.tsx | 8 ++- .../RecordTableCellFirstRowFirstColumn.tsx | 2 +- .../RecordTableCellFocusedPortalContent.tsx | 7 +- .../RecordTableCellHotkeysEffect.tsx | 8 ++- .../components/RecordTableCellPortals.tsx | 10 ++- ...eCurrentlyFocusedRecordTableCellFocusId.ts | 11 +-- .../hooks/useFocusRecordTableCell.ts | 28 +++++--- .../hooks/useUnfocusRecordTableCell.ts | 5 ++ .../recordTableFocusPositionComponentState.ts | 7 +- .../views/components/AnyFieldSearchChip.tsx | 4 +- 14 files changed, 133 insertions(+), 60 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay.tsx index d9d5eb3064..5a544e9af7 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay.tsx @@ -2,7 +2,10 @@ import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPe import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly'; import { hasAnySoftDeleteFilterOnViewComponentSelector } from '@/object-record/record-filter/states/hasAnySoftDeleteFilterOnView'; import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; +import { useScrollWrapperHTMLElement } from '@/ui/utilities/scroll/hooks/useScrollWrapperHTMLElement'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; +import styled from '@emotion/styled'; +import { isDefined } from 'twenty-shared/utils'; import { type IconComponent } from 'twenty-ui/display'; import { Button } from 'twenty-ui/input'; import { @@ -14,6 +17,18 @@ import { type AnimatedPlaceholderType, } from 'twenty-ui/layout'; +const StyledEmptyPlaceholderOuterContainer = styled( + AnimatedPlaceholderEmptyContainer, +)` + align-items: flex-start; +`; + +const StyledEmptyPlaceholderInnerContainer = styled( + AnimatedPlaceholderEmptyContainer, +)<{ width?: number }>` + width: ${({ width }) => (isDefined(width) ? `${width}px` : '100%')}; +`; + type RecordTableEmptyStateDisplayButtonComponentProps = { buttonComponent?: React.ReactNode; }; @@ -50,29 +65,35 @@ export const RecordTableEmptyStateDisplay = ( hasAnySoftDeleteFilterOnViewComponentSelector, ); + const { scrollWrapperHTMLElement } = useScrollWrapperHTMLElement(); + + const scrollWrapperWidth = scrollWrapperHTMLElement?.clientWidth; + return ( - - - - - {props.title} - - - {props.subTitle} - - - {'buttonComponent' in props && props.buttonComponent} - {'buttonTitle' in props && - !isReadOnly && - !hasAnySoftDeleteFilterOnView && ( -