Fixed index column stickiness mobile (#4206)

* #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 70c4db8ee8.

* fix: resolved label identifier issue

---------

Co-authored-by: Thaïs Guigon <guigon.thais@gmail.com>
This commit is contained in:
Jeet Desai 2024-03-04 21:11:42 +05:30 committed by GitHub
parent 6512a781ee
commit 8c0ec336ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 76 additions and 64 deletions

View File

@ -16,6 +16,7 @@ const StyledContainer = styled.div`
height: 32px;
justify-content: center;
background-color: ${({ theme }) => theme.background.primary};
`;
export const CheckboxCell = () => {

View File

@ -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<FieldMetadata>;
};
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 (
<StyledTitle>
<StyledTitle hideTitle={!!column.isLabelIdentifier && scrollLeft > 0}>
<StyledIcon>
<Icon size={theme.icon.size.md} />
</StyledIcon>

View File

@ -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<HTMLTableElement>(null);
const { scopeId } = useRecordTableStates(recordTableId);
const scrollLeft = useRecoilValue(scrollLeftState);
const { objectMetadataItem } = useObjectMetadataItemOnly({
objectNameSingular,
@ -127,11 +137,12 @@ export const RecordTable = ({
<RecordTableContext.Provider
value={{
objectMetadataItem,
recordTableRef,
}}
>
<RecordTableFirstColumnScrollEffect />
<StyledTable ref={recordTableRef} className="entity-table-cell">
<StyledTable
freezeFirstColumns={scrollLeft > 0}
className="entity-table-cell"
>
<RecordTableHeader createRecord={createRecord} />
<RecordTableBodyEffect objectNameSingular={objectNameSingular} />
<RecordTableBody objectNameSingular={objectNameSingular} />

View File

@ -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 <></>;
};

View File

@ -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 (
<StyledColumnHeaderCell
key={column.fieldMetadataId}
@ -174,17 +180,16 @@ export const RecordTableHeaderCell = ({
24,
COLUMN_MIN_WIDTH,
)}
onMouseEnter={() => setIconVisibility(true)}
onMouseLeave={() => setIconVisibility(false)}
>
<StyledColumnHeadContainer
onMouseEnter={() => setIconVisibility(true)}
onMouseLeave={() => setIconVisibility(false)}
>
<StyledColumnHeadContainer>
{column.isLabelIdentifier ? (
<ColumnHead column={column} />
) : (
<ColumnHeadWithDropdown column={column} />
)}
{iconVisibility && !!column.isLabelIdentifier && (
{(useIsMobile() || iconVisibility) && !!column.isLabelIdentifier && (
<StyledHeaderIcon>
<LightIconButton
Icon={IconPlus}
@ -195,13 +200,15 @@ export const RecordTableHeaderCell = ({
</StyledHeaderIcon>
)}
</StyledColumnHeadContainer>
<StyledResizeHandler
className="cursor-col-resize"
role="separator"
onPointerDown={() => {
setResizedFieldKey(column.fieldMetadataId);
}}
/>
{!disableColumnResize && (
<StyledResizeHandler
className="cursor-col-resize"
role="separator"
onPointerDown={() => {
setResizedFieldKey(column.fieldMetadataId);
}}
/>
)}
</StyledColumnHeaderCell>
);
};

View File

@ -13,6 +13,7 @@ const StyledContainer = styled.div`
height: 32px;
justify-content: center;
background-color: ${({ theme }) => theme.background.primary};
`;
export const SelectAllCheckbox = () => {

View File

@ -4,7 +4,6 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
type RecordTableContextProps = {
objectMetadataItem: ObjectMetadataItem;
recordTableRef: React.RefObject<HTMLDivElement>;
};
export const RecordTableContext = createContext<RecordTableContextProps>(