From 8c0ec336ea34ab50aeca78eb3ccba7d6a9230b5b Mon Sep 17 00:00:00 2001 From: Jeet Desai <52026385+jeet1desai@users.noreply.github.com> Date: Mon, 4 Mar 2024 21:11:42 +0530 Subject: [PATCH] Fixed index column stickiness mobile (#4206) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * #4155 fixed first column stickiness on mobile * fixed eslint error * resolved checkbox background * refactor: remove RecordTableFirstColumnScrollEffect * fix: resolved comment in PR * #4123 CurrencyFieldInput design is ready * Revert "#4123 CurrencyFieldInput design is ready" This reverts commit 70c4db8ee8ba57dbf163bae1aef1ccb63ec83797. * fix: resolved label identifier issue --------- Co-authored-by: Thaïs Guigon --- .../record-table/components/CheckboxCell.tsx | 1 + .../record-table/components/ColumnHead.tsx | 19 +++++- .../record-table/components/RecordTable.tsx | 61 +++++++++++-------- .../RecordTableFirstColumnScrollObserver.tsx | 20 ------ .../components/RecordTableHeaderCell.tsx | 37 ++++++----- .../components/SelectAllCheckbox.tsx | 1 + .../contexts/RecordTableContext.ts | 1 - 7 files changed, 76 insertions(+), 64 deletions(-) delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/components/RecordTableFirstColumnScrollObserver.tsx diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/CheckboxCell.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/CheckboxCell.tsx index 74af8f6ab..2aff77e1b 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/CheckboxCell.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/CheckboxCell.tsx @@ -16,6 +16,7 @@ const StyledContainer = styled.div` height: 32px; justify-content: center; + background-color: ${({ theme }) => theme.background.primary}; `; export const CheckboxCell = () => { diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/ColumnHead.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/ColumnHead.tsx index f9678b411..5f3207bfa 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/ColumnHead.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/ColumnHead.tsx @@ -1,8 +1,11 @@ -import { useTheme } from '@emotion/react'; +import { css, useTheme } from '@emotion/react'; import styled from '@emotion/styled'; +import { useRecoilValue } from 'recoil'; import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { useIcons } from '@/ui/display/icon/hooks/useIcons'; +import { MOBILE_VIEWPORT } from '@/ui/theme/constants/MobileViewport'; +import { scrollLeftState } from '@/ui/utilities/scroll/states/scrollLeftState'; import { ColumnDefinition } from '../types/ColumnDefinition'; @@ -10,7 +13,7 @@ type ColumnHeadProps = { column: ColumnDefinition; }; -const StyledTitle = styled.div` +const StyledTitle = styled.div<{ hideTitle?: boolean }>` align-items: center; display: flex; flex-direction: row; @@ -19,6 +22,14 @@ const StyledTitle = styled.div` height: ${({ theme }) => theme.spacing(8)}; padding-left: ${({ theme }) => theme.spacing(2)}; padding-right: ${({ theme }) => theme.spacing(2)}; + + ${({ hideTitle }) => + hideTitle && + css` + @media (max-width: ${MOBILE_VIEWPORT}px) { + display: none; + } + `} `; const StyledIcon = styled.div` @@ -42,8 +53,10 @@ export const ColumnHead = ({ column }: ColumnHeadProps) => { const { getIcon } = useIcons(); const Icon = getIcon(column.iconName); + const scrollLeft = useRecoilValue(scrollLeftState); + return ( - + 0}> diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx index 07638f0fa..80dbedafd 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx @@ -1,17 +1,19 @@ -import { useRef } from 'react'; +import { css } from '@emotion/react'; import styled from '@emotion/styled'; +import { useRecoilValue } from 'recoil'; import { useObjectMetadataItemOnly } from '@/object-metadata/hooks/useObjectMetadataItemOnly'; import { RecordTableBody } from '@/object-record/record-table/components/RecordTableBody'; import { RecordTableBodyEffect } from '@/object-record/record-table/components/RecordTableBodyEffect'; -import { RecordTableFirstColumnScrollEffect } from '@/object-record/record-table/components/RecordTableFirstColumnScrollObserver'; import { RecordTableHeader } from '@/object-record/record-table/components/RecordTableHeader'; import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext'; import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; import { RecordTableScope } from '@/object-record/record-table/scopes/RecordTableScope'; +import { MOBILE_VIEWPORT } from '@/ui/theme/constants/MobileViewport'; import { RGBA } from '@/ui/theme/constants/Rgba'; +import { scrollLeftState } from '@/ui/utilities/scroll/states/scrollLeftState'; -const StyledTable = styled.table` +const StyledTable = styled.table<{ freezeFirstColumns?: boolean }>` border-radius: ${({ theme }) => theme.border.radius.sm}; border-spacing: 0; margin-right: ${({ theme }) => theme.table.horizontalCellMargin}; @@ -67,29 +69,37 @@ const StyledTable = styled.table` tbody td:nth-of-type(1) { left: 0; } + + // Label identifier column thead th:nth-of-type(2), tbody td:nth-of-type(2) { left: calc(${({ theme }) => theme.table.checkboxColumnWidth} - 2px); - } - tbody td:nth-of-type(2)::after, - thead th:nth-of-type(2)::after { - content: ''; - height: calc(100% + 1px); - position: absolute; - top: 0; - width: 4px; - right: -4px; - } + ${({ freezeFirstColumns }) => + freezeFirstColumns && + css` + @media (max-width: ${MOBILE_VIEWPORT}px) { + width: 35px; + max-width: 35px; + } + `} - &.freeze-first-columns-shadow thead th:nth-of-type(2)::after, - &.freeze-first-columns-shadow tbody td:nth-of-type(2)::after { - box-shadow: ${({ theme }) => - `4px 0px 4px -4px ${ - theme.name === 'dark' - ? RGBA(theme.grayScale.gray50, 0.8) - : RGBA(theme.grayScale.gray100, 0.25) - } inset`}; + &::after { + content: ''; + height: calc(100% + 1px); + position: absolute; + top: 0; + width: 4px; + right: -4px; + + ${({ freezeFirstColumns, theme }) => + freezeFirstColumns && + css` + box-shadow: 4px 0px 4px -4px ${theme.name === 'dark' + ? RGBA(theme.grayScale.gray50, 0.8) + : RGBA(theme.grayScale.gray100, 0.25)} inset; + `} + } } thead th:nth-of-type(3), @@ -111,8 +121,8 @@ export const RecordTable = ({ onColumnsChange, createRecord, }: RecordTableProps) => { - const recordTableRef = useRef(null); const { scopeId } = useRecordTableStates(recordTableId); + const scrollLeft = useRecoilValue(scrollLeftState); const { objectMetadataItem } = useObjectMetadataItemOnly({ objectNameSingular, @@ -127,11 +137,12 @@ export const RecordTable = ({ - - + 0} + className="entity-table-cell" + > diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableFirstColumnScrollObserver.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableFirstColumnScrollObserver.tsx deleted file mode 100644 index bd6a02946..000000000 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableFirstColumnScrollObserver.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { useContext, useEffect } from 'react'; -import { useRecoilValue } from 'recoil'; - -import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext'; -import { scrollLeftState } from '@/ui/utilities/scroll/states/scrollLeftState'; - -export const RecordTableFirstColumnScrollEffect = () => { - const { recordTableRef } = useContext(RecordTableContext); - - const scrollLeft = useRecoilValue(scrollLeftState); - - useEffect(() => { - recordTableRef.current?.classList.toggle( - 'freeze-first-columns-shadow', - scrollLeft > 0, - ); - }, [scrollLeft, recordTableRef]); - - return <>; -}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableHeaderCell.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableHeaderCell.tsx index a238792bd..2c0907f53 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableHeaderCell.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableHeaderCell.tsx @@ -11,6 +11,8 @@ import { IconPlus } from '@/ui/display/icon'; import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; import { useTrackPointer } from '@/ui/utilities/pointer-event/hooks/useTrackPointer'; import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; +import { scrollLeftState } from '@/ui/utilities/scroll/states/scrollLeftState'; import { mapArrayToObject } from '~/utils/array/mapArrayToObject'; import { ColumnHeadWithDropdown } from './ColumnHeadWithDropdown'; @@ -70,9 +72,7 @@ const StyledColumnHeadContainer = styled.div` `; const StyledHeaderIcon = styled.div` - margin-bottom: ${({ theme }) => theme.spacing(1)}; - margin-right: ${({ theme }) => theme.spacing(1)}; - margin-top: ${({ theme }) => theme.spacing(1)}; + margin: ${({ theme }) => theme.spacing(1, 1, 1, 1.5)}; `; export const RecordTableHeaderCell = ({ @@ -164,6 +164,12 @@ export const RecordTableHeaderCell = ({ onMouseUp: handleResizeHandlerEnd, }); + const isMobile = useIsMobile(); + const scrollLeft = useRecoilValue(scrollLeftState); + + const disableColumnResize = + column.isLabelIdentifier && isMobile && scrollLeft > 0; + return ( setIconVisibility(true)} + onMouseLeave={() => setIconVisibility(false)} > - setIconVisibility(true)} - onMouseLeave={() => setIconVisibility(false)} - > + {column.isLabelIdentifier ? ( ) : ( )} - {iconVisibility && !!column.isLabelIdentifier && ( + {(useIsMobile() || iconVisibility) && !!column.isLabelIdentifier && ( )} - { - setResizedFieldKey(column.fieldMetadataId); - }} - /> + {!disableColumnResize && ( + { + setResizedFieldKey(column.fieldMetadataId); + }} + /> + )} ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/SelectAllCheckbox.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/SelectAllCheckbox.tsx index 7d65db391..9f9a46a70 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/SelectAllCheckbox.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/SelectAllCheckbox.tsx @@ -13,6 +13,7 @@ const StyledContainer = styled.div` height: 32px; justify-content: center; + background-color: ${({ theme }) => theme.background.primary}; `; export const SelectAllCheckbox = () => { diff --git a/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableContext.ts b/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableContext.ts index 87ad5adb8..80e2ad9a3 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableContext.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableContext.ts @@ -4,7 +4,6 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; type RecordTableContextProps = { objectMetadataItem: ObjectMetadataItem; - recordTableRef: React.RefObject; }; export const RecordTableContext = createContext(