Navbar customization followup (#17848)
Addresses review comments from the [first navbar customization PR](https://github.com/twentyhq/twenty/pull/17728) --------- Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> Co-authored-by: Devessier <baptiste@devessier.fr>
This commit is contained in:
+11
-34
@@ -1,30 +1,21 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { IconFolder, IconLink } from 'twenty-ui/display';
|
||||
import { IconFolder } from 'twenty-ui/display';
|
||||
|
||||
import { CommandMenuPageInfoLayout } from '@/command-menu/components/CommandMenuPageInfoLayout';
|
||||
import { commandMenuPageInfoState } from '@/command-menu/states/commandMenuPageInfoState';
|
||||
import { commandMenuShouldFocusTitleInputComponentState } from '@/command-menu/states/commandMenuShouldFocusTitleInputComponentState';
|
||||
import { NavigationMenuItemType } from '@/navigation-menu-item/constants/NavigationMenuItemType';
|
||||
import { StyledNavigationMenuItemIconContainer } from '@/navigation-menu-item/components/NavigationMenuItemIconContainer';
|
||||
import { useUpdateFolderNameInDraft } from '@/navigation-menu-item/hooks/useUpdateFolderNameInDraft';
|
||||
import { useUpdateLinkInDraft } from '@/navigation-menu-item/hooks/useUpdateLinkInDraft';
|
||||
import { useWorkspaceSectionItems } from '@/navigation-menu-item/hooks/useWorkspaceSectionItems';
|
||||
import { selectedNavigationMenuItemInEditModeState } from '@/navigation-menu-item/states/selectedNavigationMenuItemInEditModeState';
|
||||
import { getNavigationMenuItemIconColors } from '@/navigation-menu-item/utils/getNavigationMenuItemIconColors';
|
||||
import { TitleInput } from '@/ui/input/components/TitleInput';
|
||||
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
|
||||
|
||||
const ICON_CONFIG = {
|
||||
folder: { Icon: IconFolder, colorKey: 'folder' },
|
||||
link: { Icon: IconLink, colorKey: 'link' },
|
||||
} as const;
|
||||
|
||||
export const CommandMenuFolderLinkInfo = ({
|
||||
type,
|
||||
}: {
|
||||
type: 'folder' | 'link';
|
||||
}) => {
|
||||
export const CommandMenuFolderInfo = () => {
|
||||
const theme = useTheme();
|
||||
const { t } = useLingui();
|
||||
const commandMenuPageInfo = useRecoilValue(commandMenuPageInfoState);
|
||||
@@ -38,15 +29,14 @@ export const CommandMenuFolderLinkInfo = ({
|
||||
);
|
||||
const items = useWorkspaceSectionItems();
|
||||
const { updateFolderNameInDraft } = useUpdateFolderNameInDraft();
|
||||
const { updateLinkInDraft } = useUpdateLinkInDraft();
|
||||
|
||||
const defaultLabel = type === 'folder' ? t`New folder` : t`Link label`;
|
||||
const placeholder = type === 'folder' ? t`Folder name` : t`Link label`;
|
||||
const defaultLabel = t`New folder`;
|
||||
const placeholder = t`Folder name`;
|
||||
|
||||
const selectedItem = selectedNavigationMenuItemInEditMode
|
||||
? items.find(
|
||||
(item) =>
|
||||
item.itemType === type &&
|
||||
item.itemType === NavigationMenuItemType.FOLDER &&
|
||||
item.id === selectedNavigationMenuItemInEditMode,
|
||||
)
|
||||
: undefined;
|
||||
@@ -57,11 +47,7 @@ export const CommandMenuFolderLinkInfo = ({
|
||||
const itemName = selectedItem.name ?? defaultLabel;
|
||||
|
||||
const handleChange = (text: string) => {
|
||||
if (type === 'folder') {
|
||||
updateFolderNameInDraft(itemId, text);
|
||||
} else {
|
||||
updateLinkInDraft(itemId, { name: text });
|
||||
}
|
||||
updateFolderNameInDraft(itemId, text);
|
||||
};
|
||||
|
||||
const handleSave = () => {
|
||||
@@ -69,23 +55,17 @@ export const CommandMenuFolderLinkInfo = ({
|
||||
const finalName = trimmed.length > 0 ? trimmed : defaultLabel;
|
||||
|
||||
if (finalName !== itemName) {
|
||||
if (type === 'folder') {
|
||||
updateFolderNameInDraft(itemId, finalName);
|
||||
} else {
|
||||
updateLinkInDraft(itemId, { name: finalName });
|
||||
}
|
||||
updateFolderNameInDraft(itemId, finalName);
|
||||
}
|
||||
};
|
||||
|
||||
const { Icon, colorKey } = ICON_CONFIG[type];
|
||||
|
||||
return (
|
||||
<CommandMenuPageInfoLayout
|
||||
icon={
|
||||
<StyledNavigationMenuItemIconContainer
|
||||
$backgroundColor={getNavigationMenuItemIconColors(theme)[colorKey]}
|
||||
$backgroundColor={getNavigationMenuItemIconColors(theme).folder}
|
||||
>
|
||||
<Icon
|
||||
<IconFolder
|
||||
size={theme.spacing(3.5)}
|
||||
color={theme.grayScale.gray1}
|
||||
stroke={theme.icon.stroke.md}
|
||||
@@ -94,9 +74,7 @@ export const CommandMenuFolderLinkInfo = ({
|
||||
}
|
||||
title={
|
||||
<TitleInput
|
||||
instanceId={
|
||||
type === 'folder' ? `folder-name-${itemId}` : `link-label-${itemId}`
|
||||
}
|
||||
instanceId={`folder-name-${itemId}`}
|
||||
sizeVariant="sm"
|
||||
value={itemName}
|
||||
onChange={handleChange}
|
||||
@@ -110,7 +88,6 @@ export const CommandMenuFolderLinkInfo = ({
|
||||
onFocus={() => setShouldFocusTitleInput(false)}
|
||||
/>
|
||||
}
|
||||
label={type === 'link' ? t`link` : undefined}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,94 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { IconLink } from 'twenty-ui/display';
|
||||
|
||||
import { CommandMenuPageInfoLayout } from '@/command-menu/components/CommandMenuPageInfoLayout';
|
||||
import { commandMenuPageInfoState } from '@/command-menu/states/commandMenuPageInfoState';
|
||||
import { commandMenuShouldFocusTitleInputComponentState } from '@/command-menu/states/commandMenuShouldFocusTitleInputComponentState';
|
||||
import { NavigationMenuItemType } from '@/navigation-menu-item/constants/NavigationMenuItemType';
|
||||
import { StyledNavigationMenuItemIconContainer } from '@/navigation-menu-item/components/NavigationMenuItemIconContainer';
|
||||
import { useUpdateLinkInDraft } from '@/navigation-menu-item/hooks/useUpdateLinkInDraft';
|
||||
import { useWorkspaceSectionItems } from '@/navigation-menu-item/hooks/useWorkspaceSectionItems';
|
||||
import { selectedNavigationMenuItemInEditModeState } from '@/navigation-menu-item/states/selectedNavigationMenuItemInEditModeState';
|
||||
import { getNavigationMenuItemIconColors } from '@/navigation-menu-item/utils/getNavigationMenuItemIconColors';
|
||||
import { TitleInput } from '@/ui/input/components/TitleInput';
|
||||
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
|
||||
|
||||
export const CommandMenuLinkInfo = () => {
|
||||
const theme = useTheme();
|
||||
const { t } = useLingui();
|
||||
const commandMenuPageInfo = useRecoilValue(commandMenuPageInfoState);
|
||||
const [shouldFocusTitleInput, setShouldFocusTitleInput] =
|
||||
useRecoilComponentState(
|
||||
commandMenuShouldFocusTitleInputComponentState,
|
||||
commandMenuPageInfo.instanceId,
|
||||
);
|
||||
const selectedNavigationMenuItemInEditMode = useRecoilValue(
|
||||
selectedNavigationMenuItemInEditModeState,
|
||||
);
|
||||
const items = useWorkspaceSectionItems();
|
||||
const { updateLinkInDraft } = useUpdateLinkInDraft();
|
||||
|
||||
const defaultLabel = t`Link label`;
|
||||
const placeholder = t`Link label`;
|
||||
|
||||
const selectedItem = selectedNavigationMenuItemInEditMode
|
||||
? items.find(
|
||||
(item) =>
|
||||
item.itemType === NavigationMenuItemType.LINK &&
|
||||
item.id === selectedNavigationMenuItemInEditMode,
|
||||
)
|
||||
: undefined;
|
||||
|
||||
if (!selectedItem) return null;
|
||||
|
||||
const itemId = selectedItem.id;
|
||||
const itemName = selectedItem.name ?? defaultLabel;
|
||||
|
||||
const handleChange = (text: string) => {
|
||||
updateLinkInDraft(itemId, { name: text });
|
||||
};
|
||||
|
||||
const handleSave = () => {
|
||||
const trimmed = itemName.trim();
|
||||
const finalName = trimmed.length > 0 ? trimmed : defaultLabel;
|
||||
|
||||
if (finalName !== itemName) {
|
||||
updateLinkInDraft(itemId, { name: finalName });
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<CommandMenuPageInfoLayout
|
||||
icon={
|
||||
<StyledNavigationMenuItemIconContainer
|
||||
$backgroundColor={getNavigationMenuItemIconColors(theme).link}
|
||||
>
|
||||
<IconLink
|
||||
size={theme.spacing(3.5)}
|
||||
color={theme.grayScale.gray1}
|
||||
stroke={theme.icon.stroke.md}
|
||||
/>
|
||||
</StyledNavigationMenuItemIconContainer>
|
||||
}
|
||||
title={
|
||||
<TitleInput
|
||||
instanceId={`link-label-${itemId}`}
|
||||
sizeVariant="sm"
|
||||
value={itemName}
|
||||
onChange={handleChange}
|
||||
placeholder={placeholder}
|
||||
onEnter={handleSave}
|
||||
onEscape={handleSave}
|
||||
onClickOutside={handleSave}
|
||||
onTab={handleSave}
|
||||
onShiftTab={handleSave}
|
||||
shouldFocus={shouldFocusTitleInput}
|
||||
onFocus={() => setShouldFocusTitleInput(false)}
|
||||
/>
|
||||
}
|
||||
label={t`link`}
|
||||
/>
|
||||
);
|
||||
};
|
||||
+13
-5
@@ -2,27 +2,35 @@ import { useLingui } from '@lingui/react/macro';
|
||||
import { OverflowingTextWithTooltip } from 'twenty-ui/display';
|
||||
|
||||
import { CommandMenuPageInfoLayout } from '@/command-menu/components/CommandMenuPageInfoLayout';
|
||||
import { useSelectedNavigationMenuItemEditData } from '@/command-menu/pages/navigation-menu-item/hooks/useSelectedNavigationMenuItemEditData';
|
||||
import { NavigationMenuItemIcon } from '@/navigation-menu-item/components/NavigationMenuItemIcon';
|
||||
import { useSelectedNavigationMenuItemEditItem } from '@/navigation-menu-item/hooks/useSelectedNavigationMenuItemEditItem';
|
||||
import { useSelectedNavigationMenuItemEditItemLabel } from '@/navigation-menu-item/hooks/useSelectedNavigationMenuItemEditItemLabel';
|
||||
import { NavigationMenuItemType } from '@/navigation-menu-item/constants/NavigationMenuItemType';
|
||||
import { ViewKey } from '@/views/types/ViewKey';
|
||||
|
||||
export const CommandMenuObjectViewRecordInfo = () => {
|
||||
const { t } = useLingui();
|
||||
const { processedItem, selectedItemLabel } =
|
||||
useSelectedNavigationMenuItemEditData();
|
||||
const { selectedItem } = useSelectedNavigationMenuItemEditItem();
|
||||
const { selectedItemLabel } = useSelectedNavigationMenuItemEditItemLabel();
|
||||
|
||||
const processedItem =
|
||||
selectedItem && selectedItem.itemType !== NavigationMenuItemType.FOLDER
|
||||
? selectedItem
|
||||
: undefined;
|
||||
|
||||
if (!processedItem || !selectedItemLabel) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isViewOrRecord =
|
||||
processedItem.itemType === 'view' || processedItem.itemType === 'record';
|
||||
processedItem.itemType === NavigationMenuItemType.VIEW ||
|
||||
processedItem.itemType === NavigationMenuItemType.RECORD;
|
||||
if (!isViewOrRecord) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const label =
|
||||
processedItem.itemType === 'record'
|
||||
processedItem.itemType === NavigationMenuItemType.RECORD
|
||||
? t`record`
|
||||
: processedItem.viewKey === ViewKey.Index
|
||||
? t`object`
|
||||
|
||||
@@ -3,13 +3,15 @@ import { useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { OverflowingTextWithTooltip } from 'twenty-ui/display';
|
||||
|
||||
import { CommandMenuFolderLinkInfo } from '@/command-menu/components/CommandMenuFolderLinkInfo';
|
||||
import { CommandMenuFolderInfo } from '@/command-menu/components/CommandMenuFolderInfo';
|
||||
import { CommandMenuLinkInfo } from '@/command-menu/components/CommandMenuLinkInfo';
|
||||
import { CommandMenuMultipleRecordsInfo } from '@/command-menu/components/CommandMenuMultipleRecordsInfo';
|
||||
import { CommandMenuObjectViewRecordInfo } from '@/command-menu/components/CommandMenuObjectViewRecordInfo';
|
||||
import { CommandMenuPageLayoutInfo } from '@/command-menu/components/CommandMenuPageLayoutInfo';
|
||||
import { CommandMenuRecordInfo } from '@/command-menu/components/CommandMenuRecordInfo';
|
||||
import { CommandMenuWorkflowStepInfo } from '@/command-menu/components/CommandMenuWorkflowStepInfo';
|
||||
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
|
||||
import { NavigationMenuItemType } from '@/navigation-menu-item/constants/NavigationMenuItemType';
|
||||
import { useWorkspaceSectionItems } from '@/navigation-menu-item/hooks/useWorkspaceSectionItems';
|
||||
import { selectedNavigationMenuItemInEditModeState } from '@/navigation-menu-item/states/selectedNavigationMenuItemInEditModeState';
|
||||
|
||||
@@ -44,11 +46,18 @@ export const CommandMenuPageInfo = ({ pageChip }: CommandMenuPageInfoProps) => {
|
||||
if (isNavigationMenuItemEditPage && isDefined(selectedNavItem)) {
|
||||
const itemType = selectedNavItem.itemType;
|
||||
|
||||
if (itemType === 'folder' || itemType === 'link') {
|
||||
return <CommandMenuFolderLinkInfo type={itemType} />;
|
||||
if (itemType === NavigationMenuItemType.FOLDER) {
|
||||
return <CommandMenuFolderInfo />;
|
||||
}
|
||||
|
||||
if (itemType === 'view' || itemType === 'record') {
|
||||
if (itemType === NavigationMenuItemType.LINK) {
|
||||
return <CommandMenuLinkInfo />;
|
||||
}
|
||||
|
||||
if (
|
||||
itemType === NavigationMenuItemType.VIEW ||
|
||||
itemType === NavigationMenuItemType.RECORD
|
||||
) {
|
||||
return <CommandMenuObjectViewRecordInfo />;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user