Navbar customization v2 (#18026)

Adds color support for navigation menu items.

---------

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Co-authored-by: Devessier <baptiste@devessier.fr>
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Abdul Rahman
2026-02-28 16:18:28 +05:30
committed by GitHub
parent 63f17eec2c
commit 9fe2a07c55
94 changed files with 1204 additions and 474 deletions
@@ -3,6 +3,7 @@ import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainCo
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
import { RecordIndexPageHeaderIcon } from '@/object-record/record-index/components/RecordIndexPageHeaderIcon';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { PageHeaderToggleCommandMenuButton } from '@/ui/layout/page-header/components/PageHeaderToggleCommandMenuButton';
import { PageHeader } from '@/ui/layout/page/components/PageHeader';
@@ -10,7 +11,6 @@ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/use
import styled from '@emotion/styled';
import { t } from '@lingui/core/macro';
import { isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
const StyledTitleWithSelectedRecords = styled.div`
display: flex;
@@ -41,9 +41,6 @@ export const RecordIndexPageHeader = () => {
const objectMetadataItem =
findObjectMetadataItemByNamePlural(objectNamePlural);
const { getIcon } = useIcons();
const Icon = getIcon(objectMetadataItem?.icon);
const label = objectMetadataItem?.labelPlural ?? objectNamePlural;
const pageHeaderTitle =
@@ -65,7 +62,12 @@ export const RecordIndexPageHeader = () => {
);
return (
<PageHeader title={pageHeaderTitle} Icon={Icon}>
<PageHeader
title={pageHeaderTitle}
Icon={() => (
<RecordIndexPageHeaderIcon objectMetadataItem={objectMetadataItem} />
)}
>
{isDefined(contextStoreCurrentViewId) && (
<>
<RecordIndexActionMenu />
@@ -0,0 +1,59 @@
import { isNonEmptyString } from '@sniptt/guards';
import { NavigationMenuItemStyleIcon } from '@/navigation-menu-item/components/NavigationMenuItemStyleIcon';
import { usePrefetchedNavigationMenuItemsData } from '@/navigation-menu-item/hooks/usePrefetchedNavigationMenuItemsData';
import { getStandardObjectIconColor } from '@/navigation-menu-item/utils/getStandardObjectIconColor';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useAtomFamilySelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilySelectorValue';
import { coreIndexViewIdFromObjectMetadataItemFamilySelector } from '@/views/states/selectors/coreIndexViewIdFromObjectMetadataItemFamilySelector';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useTheme } from '@emotion/react';
import { isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
import { FeatureFlagKey } from '~/generated-metadata/graphql';
export const RecordIndexPageHeaderIcon = ({
objectMetadataItem,
}: {
objectMetadataItem?: ObjectMetadataItem;
}) => {
const theme = useTheme();
const isNavigationMenuItemEditingEnabled = useIsFeatureEnabled(
FeatureFlagKey.IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED,
);
const { workspaceNavigationMenuItems } =
usePrefetchedNavigationMenuItemsData();
const coreIndexViewId = useAtomFamilySelectorValue(
coreIndexViewIdFromObjectMetadataItemFamilySelector,
{ objectMetadataItemId: objectMetadataItem?.id ?? '' },
);
const { getIcon } = useIcons();
const ObjectIcon = getIcon(objectMetadataItem?.icon);
if (!ObjectIcon) {
return null;
}
if (!isNavigationMenuItemEditingEnabled) {
return <ObjectIcon size={theme.icon.size.md} />;
}
const navItem = isDefined(coreIndexViewId)
? workspaceNavigationMenuItems.find(
(item) => item.viewId === coreIndexViewId,
)
: undefined;
const navigationMenuItemColor = isNonEmptyString(navItem?.color)
? navItem.color
: undefined;
const iconColor =
navigationMenuItemColor ??
getStandardObjectIconColor(objectMetadataItem?.nameSingular ?? '');
return (
<NavigationMenuItemStyleIcon
Icon={ObjectIcon}
color={iconColor ?? undefined}
/>
);
};