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
@@ -0,0 +1,93 @@
import { CommandMenuItemDropdown } from '@/command-menu/components/CommandMenuItemDropdown';
import { useUpdateNavigationMenuItemInDraft } from '@/navigation-menu-item/hooks/useUpdateNavigationMenuItemInDraft';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
import { isNonEmptyString } from '@sniptt/guards';
import { useState } from 'react';
import { capitalize } from 'twenty-shared/utils';
import { IconColorSwatch } from 'twenty-ui/display';
import {
DEFAULT_COLOR_LABELS,
MenuItemSelectColor,
} from 'twenty-ui/navigation';
import { MAIN_COLOR_NAMES, type ThemeColor } from 'twenty-ui/theme';
const NAVIGATION_MENU_ITEM_COLOR_DROPDOWN_ID = 'navigation-menu-item-color';
const StyledMenuStyleText = styled.span`
color: ${({ theme }) => theme.font.color.light};
font-size: 13px;
`;
type CommandMenuEditColorOptionProps = {
navigationMenuItemId: string;
color: ThemeColor;
};
export const CommandMenuEditColorOption = ({
navigationMenuItemId,
color,
}: CommandMenuEditColorOptionProps) => {
const { t } = useLingui();
const { updateNavigationMenuItemInDraft } =
useUpdateNavigationMenuItemInDraft();
const { closeDropdown } = useCloseDropdown();
const [searchValue, setSearchValue] = useState('');
const themeColor = color ?? 'gray';
const colorLabel = DEFAULT_COLOR_LABELS[themeColor] ?? capitalize(themeColor);
const query = searchValue.trim().toLowerCase();
const filteredColorNames = isNonEmptyString(query)
? MAIN_COLOR_NAMES.filter(
(colorName) =>
colorName.toLowerCase().includes(query) ||
(DEFAULT_COLOR_LABELS[colorName] ?? '').toLowerCase().includes(query),
)
: MAIN_COLOR_NAMES;
const handleSelectColor = (selectedColor: ThemeColor) => {
updateNavigationMenuItemInDraft(navigationMenuItemId, {
color: selectedColor,
});
closeDropdown(NAVIGATION_MENU_ITEM_COLOR_DROPDOWN_ID);
};
return (
<CommandMenuItemDropdown
id="edit-navigation-menu-item-color"
label={t`Color`}
Icon={IconColorSwatch}
dropdownId={NAVIGATION_MENU_ITEM_COLOR_DROPDOWN_ID}
dropdownPlacement="bottom-start"
RightComponent={<StyledMenuStyleText>{colorLabel}</StyledMenuStyleText>}
dropdownComponents={
<DropdownContent>
<DropdownMenuSearchInput
placeholder={t`Search colors...`}
value={searchValue}
onChange={(event) => setSearchValue(event.target.value)}
/>
<DropdownMenuSeparator />
<DropdownMenuItemsContainer hasMaxHeight>
{filteredColorNames.map((colorName) => (
<MenuItemSelectColor
key={colorName}
onClick={() => handleSelectColor(colorName)}
color={colorName}
selected={colorName === themeColor}
colorLabels={DEFAULT_COLOR_LABELS}
/>
))}
</DropdownMenuItemsContainer>
</DropdownContent>
}
/>
);
};
@@ -1,12 +1,15 @@
import { useState } from 'react';
import { useLingui } from '@lingui/react/macro';
import { IconFolderPlus } from 'twenty-ui/display';
import { useState } from 'react';
import { useIcons } from 'twenty-ui/display';
import { CommandGroup } from '@/command-menu/components/CommandGroup';
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
import { CommandMenuList } from '@/command-menu/components/CommandMenuList';
import { CommandMenuSubViewWithSearch } from '@/command-menu/components/CommandMenuSubViewWithSearch';
import { useFolderPickerSelectionData } from '@/command-menu/pages/navigation-menu-item/hooks/useFolderPickerSelectionData';
import { NavigationMenuItemStyleIcon } from '@/navigation-menu-item/components/NavigationMenuItemStyleIcon';
import { FOLDER_ICON_DEFAULT } from '@/navigation-menu-item/constants/FolderIconDefault';
import { DEFAULT_NAVIGATION_MENU_ITEM_COLOR_FOLDER } from '@/navigation-menu-item/constants/NavigationMenuItemDefaultColorFolder';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { filterBySearchQuery } from '~/utils/filterBySearchQuery';
@@ -18,6 +21,7 @@ export const CommandMenuEditFolderPickerSubView = ({
onBack,
}: CommandMenuEditFolderPickerSubViewProps) => {
const { t } = useLingui();
const { getIcon } = useIcons();
const [searchValue, setSearchValue] = useState('');
const { foldersToShow, includeNoFolderOption, handleSelectFolder } =
useFolderPickerSelectionData({ onCloseSubView: onBack });
@@ -64,20 +68,30 @@ export const CommandMenuEditFolderPickerSubView = ({
/>
</SelectableListItem>
)}
{filteredFolders.map((folder) => (
<SelectableListItem
key={folder.id}
itemId={folder.id}
onEnter={() => handleSelectFolder(folder.id)}
>
<CommandMenuItem
Icon={IconFolderPlus}
label={folder.name}
id={folder.id}
onClick={() => handleSelectFolder(folder.id)}
/>
</SelectableListItem>
))}
{filteredFolders.map((folder) => {
const FolderIcon = getIcon(folder.icon ?? FOLDER_ICON_DEFAULT);
const folderColor =
folder.color ?? DEFAULT_NAVIGATION_MENU_ITEM_COLOR_FOLDER;
return (
<SelectableListItem
key={folder.id}
itemId={folder.id}
onEnter={() => handleSelectFolder(folder.id)}
>
<CommandMenuItem
LeftComponent={
<NavigationMenuItemStyleIcon
Icon={FolderIcon}
color={folderColor}
/>
}
label={folder.name}
id={folder.id}
onClick={() => handleSelectFolder(folder.id)}
/>
</SelectableListItem>
);
})}
</CommandGroup>
</CommandMenuList>
</CommandMenuSubViewWithSearch>
@@ -5,13 +5,15 @@ import { getAbsoluteUrl } from 'twenty-shared/utils';
import { CommandGroup } from '@/command-menu/components/CommandGroup';
import { CommandMenuList } from '@/command-menu/components/CommandMenuList';
import { CommandMenuEditColorOption } from '@/command-menu/pages/navigation-menu-item/components/CommandMenuEditColorOption';
import {
type OrganizeActionsProps,
CommandMenuEditOrganizeActions,
} from '@/command-menu/pages/navigation-menu-item/components/CommandMenuEditOrganizeActions';
import { getOrganizeActionsSelectableItemIds } from '@/command-menu/pages/navigation-menu-item/utils/getOrganizeActionsSelectableItemIds';
import { CommandMenuEditOwnerSection } from '@/command-menu/pages/navigation-menu-item/components/CommandMenuEditOwnerSection';
import { getOrganizeActionsSelectableItemIds } from '@/command-menu/pages/navigation-menu-item/utils/getOrganizeActionsSelectableItemIds';
import { type ProcessedNavigationMenuItem } from '@/navigation-menu-item/types/processed-navigation-menu-item';
import { parseThemeColor } from '@/navigation-menu-item/utils/parseThemeColor';
import { TextInput } from '@/ui/input/components/TextInput';
type CommandMenuEditLinkItemViewProps = OrganizeActionsProps & {
@@ -40,6 +42,10 @@ export const CommandMenuEditLinkItemView = ({
return (
<CommandMenuList commandGroups={[]} selectableItemIds={selectableItemIds}>
<CommandGroup heading={t`Customize`}>
<CommandMenuEditColorOption
navigationMenuItemId={selectedItem.id}
color={parseThemeColor(selectedItem.color)}
/>
<TextInput
fullWidth
placeholder="www.google.com"
@@ -1,12 +1,18 @@
import { CommandGroup } from '@/command-menu/components/CommandGroup';
import { CommandMenuList } from '@/command-menu/components/CommandMenuList';
import { CommandMenuEditColorOption } from '@/command-menu/pages/navigation-menu-item/components/CommandMenuEditColorOption';
import {
type OrganizeActionsProps,
CommandMenuEditOrganizeActions,
} from '@/command-menu/pages/navigation-menu-item/components/CommandMenuEditOrganizeActions';
import { getOrganizeActionsSelectableItemIds } from '@/command-menu/pages/navigation-menu-item/utils/getOrganizeActionsSelectableItemIds';
import { CommandMenuList } from '@/command-menu/components/CommandMenuList';
import { useSelectedNavigationMenuItemEditItem } from '@/navigation-menu-item/hooks/useSelectedNavigationMenuItemEditItem';
import { parseThemeColor } from '@/navigation-menu-item/utils/parseThemeColor';
import { useLingui } from '@lingui/react/macro';
type CommandMenuEditObjectViewBaseProps = OrganizeActionsProps & {
onOpenFolderPicker: () => void;
showColorOption?: boolean;
};
export const CommandMenuEditObjectViewBase = ({
@@ -18,11 +24,22 @@ export const CommandMenuEditObjectViewBase = ({
onRemove,
onAddBefore,
onAddAfter,
showColorOption = false,
}: CommandMenuEditObjectViewBaseProps) => {
const { t } = useLingui();
const { selectedItem } = useSelectedNavigationMenuItemEditItem();
const selectableItemIds = getOrganizeActionsSelectableItemIds(true);
return (
<CommandMenuList commandGroups={[]} selectableItemIds={selectableItemIds}>
{showColorOption && selectedItem && (
<CommandGroup heading={t`Customize`}>
<CommandMenuEditColorOption
navigationMenuItemId={selectedItem.id}
color={parseThemeColor(selectedItem.color)}
/>
</CommandGroup>
)}
<CommandMenuEditOrganizeActions
canMoveUp={canMoveUp}
canMoveDown={canMoveDown}
@@ -1,4 +1,7 @@
import { CommandGroup } from '@/command-menu/components/CommandGroup';
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
import { CommandMenuList } from '@/command-menu/components/CommandMenuList';
import { CommandMenuEditColorOption } from '@/command-menu/pages/navigation-menu-item/components/CommandMenuEditColorOption';
import { CommandMenuEditFolderPickerSubView } from '@/command-menu/pages/navigation-menu-item/components/CommandMenuEditFolderPickerSubView';
import { CommandMenuEditLinkItemView } from '@/command-menu/pages/navigation-menu-item/components/CommandMenuEditLinkItemView';
import { CommandMenuEditObjectViewBase } from '@/command-menu/pages/navigation-menu-item/components/CommandMenuEditObjectViewBase';
@@ -7,16 +10,24 @@ import { CommandMenuEditOwnerSection } from '@/command-menu/pages/navigation-men
import { useNavigationMenuItemEditOrganizeActions } from '@/command-menu/pages/navigation-menu-item/hooks/useNavigationMenuItemEditOrganizeActions';
import { getOrganizeActionsSelectableItemIds } from '@/command-menu/pages/navigation-menu-item/utils/getOrganizeActionsSelectableItemIds';
import { NavigationMenuItemType } from '@/navigation-menu-item/constants/NavigationMenuItemType';
import { useNavigationMenuItemsDraftState } from '@/navigation-menu-item/hooks/useNavigationMenuItemsDraftState';
import { useOpenAddItemToFolderPage } from '@/navigation-menu-item/hooks/useOpenAddItemToFolderPage';
import { useSelectedNavigationMenuItemEditItem } from '@/navigation-menu-item/hooks/useSelectedNavigationMenuItemEditItem';
import { useSelectedNavigationMenuItemEditItemLabel } from '@/navigation-menu-item/hooks/useSelectedNavigationMenuItemEditItemLabel';
import { useSelectedNavigationMenuItemEditItemObjectMetadata } from '@/navigation-menu-item/hooks/useSelectedNavigationMenuItemEditItemObjectMetadata';
import { useUpdateLinkInDraft } from '@/navigation-menu-item/hooks/useUpdateLinkInDraft';
import { selectedNavigationMenuItemInEditModeState } from '@/navigation-menu-item/states/selectedNavigationMenuItemInEditModeState';
import { parseThemeColor } from '@/navigation-menu-item/utils/parseThemeColor';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { ViewKey } from '@/views/types/ViewKey';
import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
import { useState } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { IconPlus } from 'twenty-ui/display';
const ADD_ITEM_TO_FOLDER_ACTION_ID = 'add-item-to-folder';
const StyledCommandMenuPlaceholder = styled.p`
color: ${({ theme }) => theme.font.color.tertiary};
@@ -40,7 +51,7 @@ export const CommandMenuNavigationMenuItemEditPage = () => {
const selectedItemType = selectedItem?.itemType ?? null;
const [isFolderPickerOpen, setIsFolderPickerOpen] = useState(false);
const setFolderPicker = () => setIsFolderPickerOpen(true);
const openFolderPicker = () => setIsFolderPickerOpen(true);
const {
canMoveUp,
@@ -53,6 +64,25 @@ export const CommandMenuNavigationMenuItemEditPage = () => {
} = useNavigationMenuItemEditOrganizeActions();
const { updateLinkInDraft } = useUpdateLinkInDraft();
const { openAddItemToFolderPage } = useOpenAddItemToFolderPage();
const { workspaceNavigationMenuItems } = useNavigationMenuItemsDraftState();
const handleAddItemToFolder = () => {
if (
!selectedItem ||
selectedItem.itemType !== NavigationMenuItemType.FOLDER
) {
return;
}
const folderItemCount = workspaceNavigationMenuItems.filter(
(item) => (item.folderId ?? null) === selectedItem.id,
).length;
openAddItemToFolderPage({
targetFolderId: selectedItem.id,
targetIndex: folderItemCount,
resetNavigationStack: false,
});
};
if (!selectedNavigationMenuItemInEditMode || !selectedItemLabel) {
return (
@@ -77,7 +107,7 @@ export const CommandMenuNavigationMenuItemEditPage = () => {
if (!selectedItemObjectMetadata) return null;
return (
<CommandMenuEditObjectViewBase
onOpenFolderPicker={setFolderPicker}
onOpenFolderPicker={openFolderPicker}
canMoveUp={canMoveUp}
canMoveDown={canMoveDown}
onMoveUp={onMoveUp}
@@ -85,6 +115,11 @@ export const CommandMenuNavigationMenuItemEditPage = () => {
onRemove={onRemove}
onAddBefore={onAddBefore}
onAddAfter={onAddAfter}
showColorOption={
selectedItem &&
'viewKey' in selectedItem &&
selectedItem.viewKey === ViewKey.Index
}
/>
);
case NavigationMenuItemType.LINK:
@@ -97,7 +132,7 @@ export const CommandMenuNavigationMenuItemEditPage = () => {
key={selectedItem.id}
selectedItem={selectedItem}
onUpdateLink={(linkId, link) => updateLinkInDraft(linkId, { link })}
onOpenFolderPicker={setFolderPicker}
onOpenFolderPicker={openFolderPicker}
canMoveUp={canMoveUp}
canMoveDown={canMoveDown}
onMoveUp={onMoveUp}
@@ -113,8 +148,31 @@ export const CommandMenuNavigationMenuItemEditPage = () => {
return (
<CommandMenuList
commandGroups={[]}
selectableItemIds={getOrganizeActionsSelectableItemIds(false)}
selectableItemIds={[
ADD_ITEM_TO_FOLDER_ACTION_ID,
...getOrganizeActionsSelectableItemIds(false),
]}
>
{selectedItem && (
<CommandGroup heading={t`Customize`}>
<SelectableListItem
itemId={ADD_ITEM_TO_FOLDER_ACTION_ID}
onEnter={handleAddItemToFolder}
>
<CommandMenuItem
Icon={IconPlus}
label={t`Add item to folder`}
id={ADD_ITEM_TO_FOLDER_ACTION_ID}
onClick={handleAddItemToFolder}
hasSubMenu
/>
</SelectableListItem>
<CommandMenuEditColorOption
navigationMenuItemId={selectedItem.id}
color={parseThemeColor(selectedItem.color)}
/>
</CommandGroup>
)}
<CommandMenuEditOrganizeActions
canMoveUp={canMoveUp}
canMoveDown={canMoveDown}
@@ -133,6 +191,14 @@ export const CommandMenuNavigationMenuItemEditPage = () => {
commandGroups={[]}
selectableItemIds={getOrganizeActionsSelectableItemIds(true)}
>
{selectedItem && (
<CommandGroup heading={t`Customize`}>
<CommandMenuEditColorOption
navigationMenuItemId={selectedItem.id}
color={parseThemeColor(selectedItem.color)}
/>
</CommandGroup>
)}
<CommandMenuEditOrganizeActions
canMoveUp={canMoveUp}
canMoveDown={canMoveDown}
@@ -142,7 +208,7 @@ export const CommandMenuNavigationMenuItemEditPage = () => {
onAddBefore={onAddBefore}
onAddAfter={onAddAfter}
showMoveToFolder
onMoveToFolder={setFolderPicker}
onMoveToFolder={openFolderPicker}
/>
</CommandMenuList>
);
@@ -1,10 +1,11 @@
import { useTheme } from '@emotion/react';
import { useLingui } from '@lingui/react/macro';
import {
IconAddressBook,
IconCube,
Avatar,
IconBuildingSkyscraper,
IconFolder,
IconLink,
IconList,
IconTable,
} from 'twenty-ui/display';
import { CommandGroup } from '@/command-menu/components/CommandGroup';
@@ -15,8 +16,9 @@ import { CommandMenuItemWithAddToNavigationDrag } from '@/command-menu/component
import { CommandMenuList } from '@/command-menu/components/CommandMenuList';
import { useAddFolderToNavigationMenu } from '@/command-menu/pages/navigation-menu-item/hooks/useAddFolderToNavigationMenu';
import { useAddLinkToNavigationMenu } from '@/command-menu/pages/navigation-menu-item/hooks/useAddLinkToNavigationMenu';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { NavigationMenuItemStyleIcon } from '@/navigation-menu-item/components/NavigationMenuItemStyleIcon';
import { NavigationMenuItemType } from '@/navigation-menu-item/constants/NavigationMenuItemType';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
type CommandMenuNewSidebarItemMainMenuProps = {
onSelectObject: () => void;
@@ -30,6 +32,7 @@ export const CommandMenuNewSidebarItemMainMenu = ({
onSelectRecord,
}: CommandMenuNewSidebarItemMainMenuProps) => {
const { t } = useLingui();
const theme = useTheme();
const { handleAddFolder } = useAddFolderToNavigationMenu();
const { handleAddLink } = useAddLinkToNavigationMenu();
@@ -46,7 +49,12 @@ export const CommandMenuNewSidebarItemMainMenu = ({
<CommandMenuAddToNavDraggablePlaceholder index={0}>
<SelectableListItem itemId="object" onEnter={onSelectObject}>
<CommandMenuItem
Icon={IconCube}
Icon={() => (
<NavigationMenuItemStyleIcon
Icon={IconBuildingSkyscraper}
color="blue"
/>
)}
label={t`Object`}
id="object"
hasSubMenu={true}
@@ -57,7 +65,12 @@ export const CommandMenuNewSidebarItemMainMenu = ({
<CommandMenuAddToNavDraggablePlaceholder index={1}>
<SelectableListItem itemId="view" onEnter={onSelectView}>
<CommandMenuItem
Icon={IconList}
Icon={() => (
<NavigationMenuItemStyleIcon
Icon={IconTable}
color="gray"
/>
)}
label={t`View`}
id="view"
hasSubMenu={true}
@@ -68,7 +81,13 @@ export const CommandMenuNewSidebarItemMainMenu = ({
<CommandMenuAddToNavDraggablePlaceholder index={2}>
<SelectableListItem itemId="record" onEnter={onSelectRecord}>
<CommandMenuItem
Icon={IconAddressBook}
Icon={() => (
<Avatar
placeholder="L"
type="rounded"
backgroundColor={theme.color.green4}
/>
)}
label={t`Record`}
id="record"
hasSubMenu={true}
@@ -6,6 +6,7 @@ import { CommandMenuObjectPickerSubView } from '@/command-menu/pages/navigation-
import { CommandMenuSystemObjectPickerSubView } from '@/command-menu/pages/navigation-menu-item/components/CommandMenuSystemObjectPickerSubView';
import { getAvailableObjectMetadataForNewSidebarItem } from '@/command-menu/pages/navigation-menu-item/utils/getAvailableObjectMetadataForNewSidebarItem';
import { useAddObjectToNavigationMenuDraft } from '@/navigation-menu-item/hooks/useAddObjectToNavigationMenuDraft';
import { getStandardObjectIconColor } from '@/navigation-menu-item/utils/getStandardObjectIconColor';
import { useDraftNavigationMenuItems } from '@/navigation-menu-item/hooks/useDraftNavigationMenuItems';
import { useNavigationMenuObjectMetadataFromDraft } from '@/navigation-menu-item/hooks/useNavigationMenuObjectMetadataFromDraft';
import { addMenuItemInsertionContextState } from '@/navigation-menu-item/states/addMenuItemInsertionContextState';
@@ -40,8 +41,11 @@ export const CommandMenuNewSidebarItemObjectFlow = ({
const setAddMenuItemInsertionContext = useSetAtomState(
addMenuItemInsertionContextState,
);
const { views, objectMetadataIdsWithIndexView } =
useNavigationMenuObjectMetadataFromDraft(currentDraft);
const {
views,
objectMetadataIdsWithIndexView,
objectMetadataIdsInWorkspace,
} = useNavigationMenuObjectMetadataFromDraft(currentDraft);
const objectMetadataIdsWithDisplayableViews = new Set(
views
@@ -61,12 +65,16 @@ export const CommandMenuNewSidebarItemObjectFlow = ({
objectMetadataItem: ObjectMetadataItem,
defaultViewId: string,
) => {
if (objectMetadataIdsInWorkspace.has(objectMetadataItem.id)) {
return;
}
addObjectToDraft(
objectMetadataItem.id,
defaultViewId,
currentDraft,
addMenuItemInsertionContext?.targetFolderId,
addMenuItemInsertionContext?.targetIndex,
getStandardObjectIconColor(objectMetadataItem.nameSingular),
);
setAddMenuItemInsertionContext(null);
closeCommandMenu();
@@ -1,4 +1,3 @@
import { useTheme } from '@emotion/react';
import { useLingui } from '@lingui/react/macro';
import { IconSettings, useIcons } from 'twenty-ui/display';
@@ -7,8 +6,8 @@ import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
import { CommandMenuList } from '@/command-menu/components/CommandMenuList';
import { CommandMenuSubViewWithSearch } from '@/command-menu/components/CommandMenuSubViewWithSearch';
import { useFilteredPickerItems } from '@/command-menu/hooks/useFilteredPickerItems';
import { IconWithBackground } from '@/navigation-menu-item/components/IconWithBackground';
import { getNavigationMenuItemIconColors } from '@/navigation-menu-item/utils/getNavigationMenuItemIconColors';
import { NavigationMenuItemStyleIcon } from '@/navigation-menu-item/components/NavigationMenuItemStyleIcon';
import { getStandardObjectIconColor } from '@/navigation-menu-item/utils/getStandardObjectIconColor';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
@@ -32,9 +31,7 @@ export const CommandMenuNewSidebarItemViewObjectPickerSubView = ({
showSystemObjectsOption = true,
}: CommandMenuNewSidebarItemViewObjectPickerSubViewProps) => {
const { t } = useLingui();
const theme = useTheme();
const { getIcon } = useIcons();
const iconColors = getNavigationMenuItemIconColors(theme);
const { filteredItems, selectableItemIds, isEmpty, hasSearchQuery } =
useFilteredPickerItems({
items: objects,
@@ -68,12 +65,12 @@ export const CommandMenuNewSidebarItemViewObjectPickerSubView = ({
onEnter={() => onSelectObject(objectMetadataItem)}
>
<CommandMenuItem
Icon={({ size, stroke }) => (
<IconWithBackground
Icon={() => (
<NavigationMenuItemStyleIcon
Icon={getIcon(objectMetadataItem.icon)}
backgroundColor={iconColors.object}
size={size}
stroke={stroke}
color={getStandardObjectIconColor(
objectMetadataItem.nameSingular,
)}
/>
)}
label={objectMetadataItem.labelPlural}
@@ -86,7 +83,7 @@ export const CommandMenuNewSidebarItemViewObjectPickerSubView = ({
{showSystemObjectsOption && (
<SelectableListItem itemId="system" onEnter={onOpenSystemPicker}>
<CommandMenuItem
Icon={IconSettings}
Icon={() => <NavigationMenuItemStyleIcon Icon={IconSettings} />}
label={t`System objects`}
id="system"
hasSubMenu={true}
@@ -1,7 +1,3 @@
import { useLingui } from '@lingui/react/macro';
import { useState } from 'react';
import { useIcons } from 'twenty-ui/display';
import { CommandGroup } from '@/command-menu/components/CommandGroup';
import { CommandMenuAddToNavDroppable } from '@/command-menu/components/CommandMenuAddToNavDroppable';
import { CommandMenuItemWithAddToNavigationDrag } from '@/command-menu/components/CommandMenuItemWithAddToNavigationDrag';
@@ -9,18 +5,23 @@ import { CommandMenuList } from '@/command-menu/components/CommandMenuList';
import { CommandMenuSubViewWithSearch } from '@/command-menu/components/CommandMenuSubViewWithSearch';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { useFilteredPickerItems } from '@/command-menu/hooks/useFilteredPickerItems';
import { useDraftNavigationMenuItems } from '@/navigation-menu-item/hooks/useDraftNavigationMenuItems';
import { ObjectIconWithViewOverlay } from '@/navigation-menu-item/components/ObjectIconWithViewOverlay';
import { NavigationMenuItemType } from '@/navigation-menu-item/constants/NavigationMenuItemType';
import { useAddViewToNavigationMenuDraft } from '@/navigation-menu-item/hooks/useAddViewToNavigationMenuDraft';
import { useDraftNavigationMenuItems } from '@/navigation-menu-item/hooks/useDraftNavigationMenuItems';
import { useNavigationMenuObjectMetadataFromDraft } from '@/navigation-menu-item/hooks/useNavigationMenuObjectMetadataFromDraft';
import { addMenuItemInsertionContextState } from '@/navigation-menu-item/states/addMenuItemInsertionContextState';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
import { getStandardObjectIconColor } from '@/navigation-menu-item/utils/getStandardObjectIconColor';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
import { type View } from '@/views/types/View';
import { ViewKey } from '@/views/types/ViewKey';
import { useLingui } from '@lingui/react/macro';
import { useState } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
type CommandMenuNewSidebarItemViewPickerSubViewProps = {
selectedObjectMetadataIdForView: string;
@@ -80,6 +81,9 @@ export const CommandMenuNewSidebarItemViewPickerSubView = ({
currentDraft,
addMenuItemInsertionContext?.targetFolderId ?? null,
addMenuItemInsertionContext?.targetIndex,
isDefined(selectedObjectMetadataItem)
? getStandardObjectIconColor(selectedObjectMetadataItem.nameSingular)
: undefined,
);
setAddMenuItemInsertionContext(null);
closeCommandMenu();
@@ -118,6 +122,9 @@ export const CommandMenuNewSidebarItemViewPickerSubView = ({
selectedObjectMetadataItem.icon,
)}
ViewIcon={getIcon(view.icon)}
objectColor={getStandardObjectIconColor(
selectedObjectMetadataItem.nameSingular,
)}
/>
) : undefined
}
@@ -1,4 +1,3 @@
import { useTheme } from '@emotion/react';
import { useLingui } from '@lingui/react/macro';
import { useIcons } from 'twenty-ui/display';
@@ -6,9 +5,9 @@ import { CommandGroup } from '@/command-menu/components/CommandGroup';
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
import { CommandMenuList } from '@/command-menu/components/CommandMenuList';
import { CommandMenuSubViewWithSearch } from '@/command-menu/components/CommandMenuSubViewWithSearch';
import { IconWithBackground } from '@/navigation-menu-item/components/IconWithBackground';
import { getNavigationMenuItemIconColors } from '@/navigation-menu-item/utils/getNavigationMenuItemIconColors';
import { useFilteredPickerItems } from '@/command-menu/hooks/useFilteredPickerItems';
import { NavigationMenuItemStyleIcon } from '@/navigation-menu-item/components/NavigationMenuItemStyleIcon';
import { getStandardObjectIconColor } from '@/navigation-menu-item/utils/getStandardObjectIconColor';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
@@ -28,9 +27,7 @@ export const CommandMenuNewSidebarItemViewSystemSubView = ({
onSelectObject,
}: CommandMenuNewSidebarItemViewSystemSubViewProps) => {
const { t } = useLingui();
const theme = useTheme();
const { getIcon } = useIcons();
const iconColors = getNavigationMenuItemIconColors(theme);
const {
filteredItems: filteredSystemObjectMetadataItems,
selectableItemIds,
@@ -67,12 +64,12 @@ export const CommandMenuNewSidebarItemViewSystemSubView = ({
onEnter={() => onSelectObject(objectMetadataItem)}
>
<CommandMenuItem
Icon={({ size, stroke }) => (
<IconWithBackground
Icon={() => (
<NavigationMenuItemStyleIcon
Icon={getIcon(objectMetadataItem.icon)}
backgroundColor={iconColors.object}
size={size}
stroke={stroke}
color={getStandardObjectIconColor(
objectMetadataItem.nameSingular,
)}
/>
)}
label={objectMetadataItem.labelPlural}
@@ -1,12 +1,14 @@
import { useTheme } from '@emotion/react';
import { useLingui } from '@lingui/react/macro';
import { isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
import { CommandMenuItemWithAddToNavigationDrag } from '@/command-menu/components/CommandMenuItemWithAddToNavigationDrag';
import { IconWithBackground } from '@/navigation-menu-item/components/IconWithBackground';
import { NavigationMenuItemStyleIcon } from '@/navigation-menu-item/components/NavigationMenuItemStyleIcon';
import { NavigationMenuItemType } from '@/navigation-menu-item/constants/NavigationMenuItemType';
import { getNavigationMenuItemIconColors } from '@/navigation-menu-item/utils/getNavigationMenuItemIconColors';
import { useDraftNavigationMenuItems } from '@/navigation-menu-item/hooks/useDraftNavigationMenuItems';
import { useNavigationMenuObjectMetadataFromDraft } from '@/navigation-menu-item/hooks/useNavigationMenuObjectMetadataFromDraft';
import { getStandardObjectIconColor } from '@/navigation-menu-item/utils/getStandardObjectIconColor';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { useAtomFamilySelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilySelectorValue';
@@ -28,28 +30,38 @@ export const CommandMenuObjectMenuItem = ({
variant,
dragIndex,
}: CommandMenuObjectMenuItemProps) => {
const theme = useTheme();
const { t } = useLingui();
const { getIcon } = useIcons();
const iconColors = getNavigationMenuItemIconColors(theme);
const { currentDraft } = useDraftNavigationMenuItems();
const { objectMetadataIdsInWorkspace } =
useNavigationMenuObjectMetadataFromDraft(currentDraft);
const isAlreadyInNavbar = objectMetadataIdsInWorkspace.has(
objectMetadataItem.id,
);
const defaultViewId = useAtomFamilySelectorValue(
coreIndexViewIdFromObjectMetadataItemFamilySelector,
{ objectMetadataItemId: objectMetadataItem.id },
);
const Icon = getIcon(objectMetadataItem.icon);
const isDisabled = !isDefined(defaultViewId);
const iconColor = getStandardObjectIconColor(objectMetadataItem.nameSingular);
const isDisabled = isAlreadyInNavbar || !isDefined(defaultViewId);
const handleClick = () => {
if (!defaultViewId) {
if (isDisabled || !defaultViewId) {
return;
}
onSelect(objectMetadataItem, defaultViewId);
};
const styledIcon = () => (
<NavigationMenuItemStyleIcon Icon={Icon} color={iconColor} />
);
return (
<SelectableListItem itemId={objectMetadataItem.id} onEnter={handleClick}>
{variant === 'add' && !isDisabled ? (
<CommandMenuItemWithAddToNavigationDrag
icon={Icon}
icon={styledIcon}
label={objectMetadataItem.labelPlural}
id={objectMetadataItem.id}
onClick={handleClick}
@@ -63,18 +75,12 @@ export const CommandMenuObjectMenuItem = ({
/>
) : (
<CommandMenuItem
Icon={({ size, stroke }) => (
<IconWithBackground
Icon={Icon}
backgroundColor={iconColors.object}
size={size}
stroke={stroke}
/>
)}
Icon={styledIcon}
label={objectMetadataItem.labelPlural}
id={objectMetadataItem.id}
onClick={handleClick}
disabled={isDisabled}
description={isAlreadyInNavbar ? t`Already in navbar` : undefined}
/>
)}
</SelectableListItem>
@@ -1,11 +1,10 @@
import { useTheme } from '@emotion/react';
import { isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
import { CommandMenuObjectMenuItem } from '@/command-menu/pages/navigation-menu-item/components/CommandMenuObjectMenuItem';
import { IconWithBackground } from '@/navigation-menu-item/components/IconWithBackground';
import { getNavigationMenuItemIconColors } from '@/navigation-menu-item/utils/getNavigationMenuItemIconColors';
import { NavigationMenuItemStyleIcon } from '@/navigation-menu-item/components/NavigationMenuItemStyleIcon';
import { getStandardObjectIconColor } from '@/navigation-menu-item/utils/getStandardObjectIconColor';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
@@ -29,9 +28,7 @@ export const CommandMenuObjectPickerItem = ({
objectMenuItemVariant = 'edit',
dragIndex,
}: CommandMenuObjectPickerItemProps) => {
const theme = useTheme();
const { getIcon } = useIcons();
const iconColors = getNavigationMenuItemIconColors(theme);
if (isViewItem && isDefined(onSelectObjectForViewEdit)) {
return (
@@ -40,12 +37,12 @@ export const CommandMenuObjectPickerItem = ({
onEnter={() => onSelectObjectForViewEdit(objectMetadataItem)}
>
<CommandMenuItem
Icon={({ size, stroke }) => (
<IconWithBackground
Icon={() => (
<NavigationMenuItemStyleIcon
Icon={getIcon(objectMetadataItem.icon)}
backgroundColor={iconColors.object}
size={size}
stroke={stroke}
color={getStandardObjectIconColor(
objectMetadataItem.nameSingular,
)}
/>
)}
label={objectMetadataItem.labelPlural}
@@ -9,6 +9,7 @@ import { CommandMenuList } from '@/command-menu/components/CommandMenuList';
import { CommandMenuSubViewWithSearch } from '@/command-menu/components/CommandMenuSubViewWithSearch';
import { useFilteredPickerItems } from '@/command-menu/hooks/useFilteredPickerItems';
import { CommandMenuObjectPickerItem } from '@/command-menu/pages/navigation-menu-item/components/CommandMenuObjectPickerItem';
import { NavigationMenuItemStyleIcon } from '@/navigation-menu-item/components/NavigationMenuItemStyleIcon';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
@@ -72,10 +73,10 @@ export const CommandMenuObjectPickerSubView = ({
<CommandMenuAddToNavDraggablePlaceholder index={filteredItems.length}>
<SelectableListItem itemId="system" onEnter={onOpenSystemPicker}>
<CommandMenuItem
Icon={IconSettings}
Icon={() => <NavigationMenuItemStyleIcon Icon={IconSettings} />}
label={t`System objects`}
id="system"
hasSubMenu={true}
hasSubMenu
onClick={onOpenSystemPicker}
/>
</SelectableListItem>
@@ -83,10 +84,10 @@ export const CommandMenuObjectPickerSubView = ({
) : (
<SelectableListItem itemId="system" onEnter={onOpenSystemPicker}>
<CommandMenuItem
Icon={IconSettings}
Icon={() => <NavigationMenuItemStyleIcon Icon={IconSettings} />}
label={t`System objects`}
id="system"
hasSubMenu={true}
hasSubMenu
onClick={onOpenSystemPicker}
/>
</SelectableListItem>
@@ -12,7 +12,7 @@ import { NavigationMenuItemType } from '@/navigation-menu-item/constants/Navigat
type FolderOption = {
id: string;
name: string;
folderId?: string;
folderId?: string | null;
};
const getDescendantFolderIds = (
@@ -1,6 +1,6 @@
import { useLingui } from '@lingui/react/macro';
import { isDefined } from 'twenty-shared/utils';
import { IconPlus } from 'twenty-ui/display';
import { IconColumnInsertRight } from 'twenty-ui/display';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { useNavigateCommandMenu } from '@/command-menu/hooks/useNavigateCommandMenu';
@@ -119,7 +119,7 @@ export const useNavigationMenuItemEditOrganizeActions =
navigateCommandMenu({
page: CommandMenuPages.NavigationMenuAddItem,
pageTitle: t`New sidebar item`,
pageIcon: IconPlus,
pageIcon: IconColumnInsertRight,
resetNavigationStack: true,
});
};