diff --git a/packages/twenty-front/src/modules/object-record/components/RecordChip.tsx b/packages/twenty-front/src/modules/object-record/components/RecordChip.tsx index f5230116e..9d07eab1f 100644 --- a/packages/twenty-front/src/modules/object-record/components/RecordChip.tsx +++ b/packages/twenty-front/src/modules/object-record/components/RecordChip.tsx @@ -22,6 +22,7 @@ export type RecordChipProps = { maxWidth?: number; to?: string | undefined; size?: ChipSize; + isLabelHidden?: boolean; }; export const RecordChip = ({ @@ -33,6 +34,7 @@ export const RecordChip = ({ to, size, forceDisableClick = false, + isLabelHidden = false, }: RecordChipProps) => { const { recordChipData } = useRecordChipData({ objectNameSingular, @@ -74,6 +76,7 @@ export const RecordChip = ({ maxWidth={maxWidth} placeholderColorSeed={record.id} name={recordChipData.name} + isLabelHidden={isLabelHidden} avatarType={recordChipData.avatarType} avatarUrl={recordChipData.avatarUrl ?? ''} className={className} diff --git a/packages/twenty-front/src/modules/object-record/record-field/components/FieldContextProvider.tsx b/packages/twenty-front/src/modules/object-record/record-field/components/FieldContextProvider.tsx index 874d70a96..6d6a5f0f5 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/components/FieldContextProvider.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/components/FieldContextProvider.tsx @@ -14,6 +14,7 @@ export const FieldContextProvider = ({ fieldMetadataName, fieldPosition, isLabelIdentifier = false, + isLabelHidden, objectNameSingular, objectRecordId, customUseUpdateOneObjectHook, @@ -24,6 +25,7 @@ export const FieldContextProvider = ({ fieldMetadataName: string; fieldPosition: number; isLabelIdentifier?: boolean; + isLabelHidden?: boolean; objectNameSingular: string; objectRecordId: string; customUseUpdateOneObjectHook?: RecordUpdateHook; @@ -63,6 +65,7 @@ export const FieldContextProvider = ({ value={{ recordId: objectRecordId, isLabelIdentifier, + isLabelHidden, fieldDefinition: formatFieldMetadataItemAsColumnDefinition({ field: fieldMetadataItem, showLabel: true, diff --git a/packages/twenty-front/src/modules/object-record/record-field/contexts/FieldContext.ts b/packages/twenty-front/src/modules/object-record/record-field/contexts/FieldContext.ts index a6ec5e4b9..ab07755d1 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/contexts/FieldContext.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/contexts/FieldContext.ts @@ -34,6 +34,7 @@ export type GenericFieldContextType = { isDisplayModeFixHeight?: boolean; onOpenEditMode?: () => void; onCloseEditMode?: () => void; + isLabelHidden?: boolean; }; export const FieldContext = createContext( diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/ChipFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/ChipFieldDisplay.tsx index 55e9307b5..6db5b345a 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/ChipFieldDisplay.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/ChipFieldDisplay.tsx @@ -4,8 +4,12 @@ import { ChipSize } from 'twenty-ui'; import { isDefined } from 'twenty-shared/utils'; export const ChipFieldDisplay = () => { - const { recordValue, objectNameSingular, labelIdentifierLink } = - useChipFieldDisplay(); + const { + recordValue, + objectNameSingular, + labelIdentifierLink, + isLabelHidden, + } = useChipFieldDisplay(); if (!isDefined(recordValue)) { return null; @@ -17,6 +21,7 @@ export const ChipFieldDisplay = () => { record={recordValue} size={ChipSize.Small} to={labelIdentifierLink} + isLabelHidden={isLabelHidden} /> ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useChipFieldDisplay.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useChipFieldDisplay.ts index 9e1551679..0d4ce17ba 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useChipFieldDisplay.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useChipFieldDisplay.ts @@ -12,8 +12,13 @@ import { FieldContext } from '../../contexts/FieldContext'; import { isDefined } from 'twenty-shared/utils'; export const useChipFieldDisplay = () => { - const { recordId, fieldDefinition, isLabelIdentifier, labelIdentifierLink } = - useContext(FieldContext); + const { + recordId, + fieldDefinition, + isLabelIdentifier, + labelIdentifierLink, + isLabelHidden, + } = useContext(FieldContext); const { chipGeneratorPerObjectPerField } = useContext( PreComputedChipGeneratorsContext, @@ -42,5 +47,6 @@ export const useChipFieldDisplay = () => { recordValue, isLabelIdentifier, labelIdentifierLink, + isLabelHidden, }; }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBody.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBody.tsx index 26b1fa747..8022cce69 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBody.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBody.tsx @@ -1,5 +1,4 @@ import styled from '@emotion/styled'; -import { MOBILE_VIEWPORT } from 'twenty-ui'; const StyledTbody = styled.tbody` &.first-columns-sticky { @@ -22,18 +21,6 @@ const StyledTbody = styled.tbody` z-index: 5; transition: 0.3s ease; - @media (max-width: ${MOBILE_VIEWPORT}px) { - & [data-testid='editable-cell-display-mode'] { - [data-testid='tooltip'] { - display: none; - } - - [data-testid='chip'] { - gap: 0; - } - } - } - &:not(.disable-shadow)::after { content: ''; position: absolute; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContext.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContext.tsx new file mode 100644 index 000000000..9d691e58e --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContext.tsx @@ -0,0 +1,95 @@ +import { ReactNode, useContext } from 'react'; +import { useIsMobile } from 'twenty-ui'; +import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField'; +import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; +import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; +import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation'; +import { isFieldSelect } from '@/object-record/record-field/types/guards/isFieldSelect'; +import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; +import { MultipleRecordPickerHotkeyScope } from '@/object-record/record-picker/multiple-record-picker/types/MultipleRecordPickerHotkeyScope'; +import { SingleRecordPickerHotkeyScope } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerHotkeyScope'; +import { RecordUpdateContext } from '@/object-record/record-table/contexts/EntityUpdateMutationHookContext'; +import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; +import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; +import { TableHotkeyScope } from '@/object-record/record-table/types/TableHotkeyScope'; +import { SelectFieldHotkeyScope } from '@/object-record/select/types/SelectFieldHotkeyScope'; +import { RelationDefinitionType } from '~/generated-metadata/graphql'; +import { isRecordTableScrolledLeftComponentState } from '../../states/isRecordTableScrolledLeftComponentState'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext'; +import { useRecordTableRowContextOrThrow } from '@/object-record/record-table/contexts/RecordTableRowContext'; + +export const RecordTableCellFieldContext = ({ + children, +}: { + children: ReactNode; +}) => { + const { objectMetadataItem } = useRecordTableContextOrThrow(); + const { indexIdentifierUrl } = useRecordIndexContextOrThrow(); + const { columnDefinition } = useContext(RecordTableCellContext); + const { recordId } = useRecordTableRowContextOrThrow(); + const updateRecord = useContext(RecordUpdateContext); + const isMobile = useIsMobile(); + + const isRecordTableScrolledLeft = useRecoilComponentValueV2( + isRecordTableScrolledLeftComponentState, + ); + + const isLabelHidden = + isMobile && + columnDefinition?.isLabelIdentifier && + !isRecordTableScrolledLeft; + + const computedHotkeyScope = ( + columnDefinition: ColumnDefinition, + ) => { + if (isFieldRelation(columnDefinition)) { + if ( + columnDefinition.metadata.relationType === + RelationDefinitionType.MANY_TO_ONE + ) { + return SingleRecordPickerHotkeyScope.SingleRecordPicker; + } + + if ( + columnDefinition.metadata.relationType === + RelationDefinitionType.ONE_TO_MANY + ) { + return MultipleRecordPickerHotkeyScope.MultipleRecordPicker; + } + + return SingleRecordPickerHotkeyScope.SingleRecordPicker; + } + + if (isFieldSelect(columnDefinition)) { + return SelectFieldHotkeyScope.SelectField; + } + + return TableHotkeyScope.CellEditMode; + }; + + const customHotkeyScope = computedHotkeyScope(columnDefinition); + + return ( + [updateRecord, {}], + hotkeyScope: customHotkeyScope, + labelIdentifierLink: indexIdentifierUrl(recordId), + isLabelIdentifier: isLabelIdentifierField({ + fieldMetadataItem: { + id: columnDefinition.fieldMetadataId, + name: columnDefinition.metadata.fieldName, + }, + objectMetadataItem, + }), + displayedMaxRows: 1, + isLabelHidden, + }} + > + {children} + + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextWrapper.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextWrapper.tsx index c53ac4b51..387a973fe 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextWrapper.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextWrapper.tsx @@ -1,104 +1,32 @@ import { ReactNode, useContext } from 'react'; - -import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField'; -import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; import { RecordFieldComponentInstanceContext } from '@/object-record/record-field/states/contexts/RecordFieldComponentInstanceContext'; -import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; -import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation'; -import { isFieldSelect } from '@/object-record/record-field/types/guards/isFieldSelect'; -import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; -import { MultipleRecordPickerHotkeyScope } from '@/object-record/record-picker/multiple-record-picker/types/MultipleRecordPickerHotkeyScope'; -import { SingleRecordPickerHotkeyScope } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerHotkeyScope'; -import { RecordUpdateContext } from '@/object-record/record-table/contexts/EntityUpdateMutationHookContext'; import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext'; -import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; import { useRecordTableRowContextOrThrow } from '@/object-record/record-table/contexts/RecordTableRowContext'; -import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; -import { TableHotkeyScope } from '@/object-record/record-table/types/TableHotkeyScope'; -import { SelectFieldHotkeyScope } from '@/object-record/select/types/SelectFieldHotkeyScope'; import { getRecordFieldInputId } from '@/object-record/utils/getRecordFieldInputId'; -import { RelationDefinitionType } from '~/generated-metadata/graphql'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; +import { RecordTableCellFieldContext } from './RecordTableCellFieldContext'; export const RecordTableCellFieldContextWrapper = ({ children, }: { children: ReactNode; }) => { - const { objectMetadataItem } = useRecordTableContextOrThrow(); - - const { indexIdentifierUrl } = useRecordIndexContextOrThrow(); - const { columnDefinition } = useContext(RecordTableCellContext); - const { recordId } = useRecordTableRowContextOrThrow(); - const updateRecord = useContext(RecordUpdateContext); - if (isUndefinedOrNull(columnDefinition)) { return null; } - // TODO: deprecate this and use useOpenFieldInput hooks to set the hotkey scope - const computedHotkeyScope = ( - columnDefinition: ColumnDefinition, - ) => { - if (isFieldRelation(columnDefinition)) { - if ( - columnDefinition.metadata.relationType === - RelationDefinitionType.MANY_TO_ONE - ) { - return SingleRecordPickerHotkeyScope.SingleRecordPicker; - } - - if ( - columnDefinition.metadata.relationType === - RelationDefinitionType.ONE_TO_MANY - ) { - return MultipleRecordPickerHotkeyScope.MultipleRecordPicker; - } - - return SingleRecordPickerHotkeyScope.SingleRecordPicker; - } - - if (isFieldSelect(columnDefinition)) { - return SelectFieldHotkeyScope.SelectField; - } - - return TableHotkeyScope.CellEditMode; - }; - - const customHotkeyScope = computedHotkeyScope(columnDefinition); + const instanceId = getRecordFieldInputId( + recordId, + columnDefinition.metadata.fieldName, + 'record-table-cell', + ); return ( - [updateRecord, {}], - hotkeyScope: customHotkeyScope, - labelIdentifierLink: indexIdentifierUrl(recordId), - isLabelIdentifier: isLabelIdentifierField({ - fieldMetadataItem: { - id: columnDefinition.fieldMetadataId, - name: columnDefinition.metadata.fieldName, - }, - objectMetadataItem, - }), - displayedMaxRows: 1, - }} - > - - {children} - - + + {children} + ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx index cf452046f..bcabe483c 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx @@ -1,6 +1,6 @@ import { ReactElement, useContext, useEffect, useRef } from 'react'; import { useRecoilValue } from 'recoil'; -import { IconArrowUpRight } from 'twenty-ui'; +import { IconArrowUpRight, useIsMobile } from 'twenty-ui'; import { useGetButtonIcon } from '@/object-record/record-field/hooks/useGetButtonIcon'; import { useIsFieldEmpty } from '@/object-record/record-field/hooks/useIsFieldEmpty'; @@ -80,8 +80,12 @@ export const RecordTableCellSoftFocusMode = ({ ? IconArrowUpRight // IconLayoutSidebarRightExpand - Disabling sidepanel access for now : customButtonIcon; + const isMobile = useIsMobile(); const showButton = - isDefined(buttonIcon) && !editModeContentOnly && !isFieldReadOnly; + isDefined(buttonIcon) && + !editModeContentOnly && + !isFieldReadOnly && + !(isMobile && isFirstColumn); const dontShowContent = isEmpty && isFieldReadOnly; diff --git a/packages/twenty-ui/src/display/avatar-chip/components/LinkAvatarChip.tsx b/packages/twenty-ui/src/display/avatar-chip/components/LinkAvatarChip.tsx index 2a7edc484..07f7c4225 100644 --- a/packages/twenty-ui/src/display/avatar-chip/components/LinkAvatarChip.tsx +++ b/packages/twenty-ui/src/display/avatar-chip/components/LinkAvatarChip.tsx @@ -8,6 +8,7 @@ export type LinkAvatarChipProps = Omit & { to: string; onClick?: LinkChipProps['onClick']; variant?: AvatarChipVariant; + isLabelHidden?: boolean; }; export const LinkAvatarChip = ({ @@ -24,11 +25,13 @@ export const LinkAvatarChip = ({ placeholderColorSeed, size, variant, + isLabelHidden, }: LinkAvatarChipProps) => ( missleading variant === AvatarChipVariant.Regular diff --git a/packages/twenty-ui/src/display/chip/components/Chip.tsx b/packages/twenty-ui/src/display/chip/components/Chip.tsx index 29d0516df..4f471479e 100644 --- a/packages/twenty-ui/src/display/chip/components/Chip.tsx +++ b/packages/twenty-ui/src/display/chip/components/Chip.tsx @@ -26,6 +26,7 @@ export type ChipProps = { disabled?: boolean; clickable?: boolean; label: string; + isLabelHidden?: boolean; maxWidth?: number; variant?: ChipVariant; accent?: ChipAccent; @@ -124,6 +125,7 @@ const StyledContainer = withTheme(styled.div< export const Chip = ({ size = ChipSize.Small, label, + isLabelHidden = false, disabled = false, clickable = true, variant = ChipVariant.Regular, @@ -145,7 +147,9 @@ export const Chip = ({ maxWidth={maxWidth} > {leftComponent?.()} - + {!isLabelHidden && ( + + )} {rightComponent?.()} ); diff --git a/packages/twenty-ui/src/display/chip/components/LinkChip.tsx b/packages/twenty-ui/src/display/chip/components/LinkChip.tsx index 897c1adb1..51ab587a9 100644 --- a/packages/twenty-ui/src/display/chip/components/LinkChip.tsx +++ b/packages/twenty-ui/src/display/chip/components/LinkChip.tsx @@ -27,6 +27,7 @@ export const LinkChip = ({ to, size = ChipSize.Small, label, + isLabelHidden = false, variant = ChipVariant.Regular, leftComponent = null, rightComponent = null, @@ -40,6 +41,7 @@ export const LinkChip = ({