diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnHeader.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnHeader.tsx index 1d0a575db6..f7d71abd2d 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnHeader.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnHeader.tsx @@ -1,5 +1,6 @@ import { styled } from '@linaria/react'; -import { useContext, useState } from 'react'; +import { t } from '@lingui/core/macro'; +import { useContext } from 'react'; import { themeCssVariables } from 'twenty-ui/theme-constants'; import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject'; @@ -21,6 +22,7 @@ import { canCreateRecordsForObjectMetadataItem } from '@/object-record/utils/can import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { useDisableDragSelectOnPointerDown } from '@/ui/utilities/drag-select/hooks/useDisableDragSelectOnPointerDown'; import { useToggleDropdown } from '@/ui/layout/dropdown/hooks/useToggleDropdown'; +import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState'; import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateValue'; import { useAtomComponentSelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentSelectorValue'; import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue'; @@ -38,8 +40,31 @@ const StyledHeader = styled.div` `; const StyledHeaderActions = styled.div` + align-items: center; display: flex; - margin-left: auto; + flex-shrink: 0; + // padding + negative margin cancel out in layout and exist only so + // overflow:hidden clips 4px outside each button, leaving room for + // LightIconButton's 3px focus ring + margin: calc(-1 * ${themeCssVariables.spacing[1]}); + max-width: 0; + min-width: 0; + opacity: 0; + overflow: hidden; + padding: ${themeCssVariables.spacing[1]}; + pointer-events: none; + transition: + max-width ease-in-out + calc(${themeCssVariables.animation.duration.fast} * 1s), + opacity ease-in-out calc(${themeCssVariables.animation.duration.fast} * 1s); + + &[data-dropdown-open='true'], + ${StyledHeader}:hover &, + ${StyledHeader}:focus-within & { + max-width: ${themeCssVariables.spacing[14]}; + opacity: 1; + pointer-events: auto; + } `; const StyledHeaderContainer = styled.div` @@ -55,11 +80,6 @@ const StyledLeftContainer = styled.div` overflow: hidden; `; -const StyledRightContainer = styled.div` - align-items: center; - display: flex; -`; - const StyledColumn = styled.div` background-color: ${themeCssVariables.background.primary}; display: flex; @@ -104,8 +124,6 @@ export const RecordBoardColumnHeader = () => { onPointerUp: handlePointerUp, } = useDisableDragSelectOnPointerDown(); - const [isHeaderHovered, setIsHeaderHovered] = useState(false); - const { objectMetadataItem, selectFieldMetadataItem } = useContext(RecordBoardContext); @@ -140,6 +158,11 @@ export const RecordBoardColumnHeader = () => { const dropdownId = `record-board-column-dropdown-${columnDefinition.id}`; + const isDropdownOpen = useAtomComponentStateValue( + isDropdownOpenComponentState, + dropdownId, + ); + const handleCreateNewRecordClick = async () => { await createNewIndexRecord({ position: 'first', @@ -152,8 +175,6 @@ export const RecordBoardColumnHeader = () => { 0 ? 'true' : undefined}> setIsHeaderHovered(true)} - onMouseLeave={() => setIsHeaderHovered(false)} onPointerCancel={handlePointerCancel} onPointerDown={handlePointerDown} onPointerUp={handlePointerUp} @@ -187,28 +208,28 @@ export const RecordBoardColumnHeader = () => { aggregateLabel={recordIndexAggregateDisplayLabel} /> - - {isHeaderHovered && ( - - { - toggleDropdown({ - dropdownComponentInstanceIdFromProps: dropdownId, - }); - }} - /> - {canCreateRecords && !hasAnySoftDeleteFilterOnView && ( - - )} - + + { + toggleDropdown({ + dropdownComponentInstanceIdFromProps: dropdownId, + }); + }} + /> + {canCreateRecords && !hasAnySoftDeleteFilterOnView && ( + )} - +