Fix add more tab bottom separator (#18529)

Adding a full height prop

Before 
<img width="409" height="139" alt="Capture d’écran 2026-03-10 à 14 06
13"
src="https://github.com/user-attachments/assets/6f9bb8d1-8834-44b9-a0cf-1253dffc9ea0"
/>

After
<img width="409" height="139" alt="Capture d’écran 2026-03-10 à 14 06
33"
src="https://github.com/user-attachments/assets/1d3551fe-0b4b-4bbf-88e4-fd466c9bb704"
/>
This commit is contained in:
Thomas Trompette
2026-03-10 18:08:51 +01:00
committed by GitHub
parent 40a8d18d38
commit 6e628bb751
6 changed files with 33 additions and 87 deletions
@@ -18,6 +18,7 @@ import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
import { TabListHiddenMeasurements } from '@/ui/layout/tab-list/components/TabListHiddenMeasurements';
import { TAB_LIST_GAP } from '@/ui/layout/tab-list/constants/TabListGap';
import { TAB_LIST_HEIGHT } from '@/ui/layout/tab-list/constants/TabListHeight';
import { useTabListMeasurements } from '@/ui/layout/tab-list/hooks/useTabListMeasurements';
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
import { TabListComponentInstanceContext } from '@/ui/layout/tab-list/states/contexts/TabListComponentInstanceContext';
@@ -30,7 +31,7 @@ import { useAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useAtomC
import { useNavigatePageLayoutSidePanel } from '@/side-panel/pages/page-layout/hooks/useNavigatePageLayoutSidePanel';
import { PAGE_LAYOUT_TAB_LIST_DROPPABLE_IDS } from '@/page-layout/components/PageLayoutTabListDroppableIds';
import { PageLayoutTabListReorderableOverflowDropdown } from '@/page-layout/components/PageLayoutTabListReorderableOverflowDropdown';
import { PageLayoutTabListStaticOverflowDropdown } from '@/page-layout/components/PageLayoutTabListStaticOverflowDropdown';
import { TabListDropdown } from '@/ui/layout/tab-list/components/TabListDropdown';
import { PageLayoutTabListVisibleTabs } from '@/page-layout/components/PageLayoutTabListVisibleTabs';
import { STANDARD_PAGE_LAYOUT_TAB_TITLE_TRANSLATIONS } from '@/page-layout/constants/StandardPageLayoutTabTitleTranslations';
import { useIsCurrentObjectCustom } from '@/page-layout/hooks/useIsCurrentObjectCustom';
@@ -52,7 +53,7 @@ import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledContainer = styled.div`
box-sizing: border-box;
display: flex;
height: ${themeCssVariables.spacing[10]};
height: ${TAB_LIST_HEIGHT};
position: relative;
user-select: none;
width: 100%;
@@ -76,7 +77,7 @@ const StyledDropdownContainer = styled.div`
const StyledAddButton = styled.div`
align-items: center;
display: flex;
height: ${themeCssVariables.spacing[10]};
height: ${TAB_LIST_HEIGHT};
margin-left: ${TAB_LIST_GAP}px;
`;
@@ -413,14 +414,16 @@ export const PageLayoutTabList = ({
/>
{shouldRenderStaticDropdown && (
<StyledDropdownContainer>
<PageLayoutTabListStaticOverflowDropdown
<TabListDropdown
dropdownId={dropdownId}
hiddenTabs={hiddenTabs}
hiddenTabsCount={hiddenTabsCount}
isActiveTabHidden={isActiveTabHidden}
overflow={{
hiddenTabsCount,
isActiveTabHidden,
}}
activeTabId={activeTabId || ''}
loading={loading}
onSelect={handleSelectTabFromDropdown}
onTabSelect={handleSelectTabFromDropdown}
onClose={closeOverflowDropdown}
/>
</StyledDropdownContainer>
@@ -1,71 +0,0 @@
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { TabAvatar } from '@/ui/layout/tab-list/components/TabAvatar';
import { TabMoreButton } from '@/ui/layout/tab-list/components/TabMoreButton';
import { type SingleTabProps } from '@/ui/layout/tab-list/types/SingleTabProps';
import { MenuItemSelectAvatar } from 'twenty-ui/navigation';
type PageLayoutTabListStaticOverflowDropdownProps = {
dropdownId: string;
hiddenTabs: SingleTabProps[];
hiddenTabsCount: number;
isActiveTabHidden: boolean;
activeTabId: string | null;
loading?: boolean;
onSelect: (tabId: string) => void;
onClose: () => void;
};
export const PageLayoutTabListStaticOverflowDropdown = ({
dropdownId,
hiddenTabs,
hiddenTabsCount,
isActiveTabHidden,
activeTabId,
loading,
onSelect,
onClose,
}: PageLayoutTabListStaticOverflowDropdownProps) => {
return (
<Dropdown
dropdownId={dropdownId}
dropdownPlacement="bottom-end"
dropdownOffset={{ x: 0, y: 8 }}
onClickOutside={onClose}
clickableComponent={
<TabMoreButton
hiddenTabsCount={hiddenTabsCount}
active={isActiveTabHidden}
/>
}
dropdownComponents={
<DropdownContent>
<DropdownMenuItemsContainer>
{hiddenTabs.map((tab) => {
const disabled = tab.disabled ?? loading;
return (
<MenuItemSelectAvatar
key={tab.id}
text={tab.title}
avatar={<TabAvatar tab={tab} />}
selected={tab.id === activeTabId}
onClick={
disabled
? undefined
: () => {
onSelect(tab.id);
onClose();
}
}
disabled={disabled}
/>
);
})}
</DropdownMenuItemsContainer>
</DropdownContent>
}
/>
);
};
@@ -15,7 +15,6 @@ import { type DropdownOffset } from '@/ui/layout/dropdown/types/DropdownOffset';
import { type GlobalHotkeysConfig } from '@/ui/utilities/hotkey/types/GlobalHotkeysConfig';
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
import { useSetAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentState';
import { styled } from '@linaria/react';
import {
type Placement,
autoUpdate,
@@ -24,6 +23,7 @@ import {
size,
useFloating,
} from '@floating-ui/react';
import { styled } from '@linaria/react';
import { type MouseEvent, type ReactNode, useCallback } from 'react';
import { flushSync } from 'react-dom';
import { type Keys } from 'react-hotkeys-hook';
@@ -1,5 +1,6 @@
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { TAB_LIST_GAP } from '@/ui/layout/tab-list/constants/TabListGap';
import { TAB_LIST_HEIGHT } from '@/ui/layout/tab-list/constants/TabListHeight';
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
import { TabListComponentInstanceContext } from '@/ui/layout/tab-list/states/contexts/TabListComponentInstanceContext';
import { type TabListProps } from '@/ui/layout/tab-list/types/TabListProps';
@@ -18,7 +19,7 @@ import { TabListFromUrlOptionalEffect } from './TabListFromUrlOptionalEffect';
const StyledContainer = styled.div`
box-sizing: border-box;
display: flex;
height: ${themeCssVariables.spacing[10]};
height: ${TAB_LIST_HEIGHT};
position: relative;
user-select: none;
width: 100%;
@@ -1,7 +1,15 @@
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { IconChevronDown } from 'twenty-ui/display';
import { TabButton } from 'twenty-ui/input';
import { TAB_LIST_HEIGHT } from '@/ui/layout/tab-list/constants/TabListHeight';
const StyledTabMoreButtonContainer = styled.div`
display: flex;
height: ${TAB_LIST_HEIGHT};
`;
export const TabMoreButton = ({
hiddenTabsCount,
active,
@@ -12,12 +20,14 @@ export const TabMoreButton = ({
className?: string;
}) => {
return (
<TabButton
id="tab-more-button"
active={active}
title={`+${hiddenTabsCount} ${t`More`}`}
RightIcon={IconChevronDown}
className={className}
/>
<StyledTabMoreButtonContainer>
<TabButton
id="tab-more-button"
active={active}
title={`+${hiddenTabsCount} ${t`More`}`}
RightIcon={IconChevronDown}
className={className}
/>
</StyledTabMoreButtonContainer>
);
};
@@ -0,0 +1,3 @@
import { themeCssVariables } from 'twenty-ui/theme-constants';
export const TAB_LIST_HEIGHT = themeCssVariables.spacing[10];