545 replace objects icons and names with records avatars and labelidentifiers in command menu context chips (#10787)

Closes https://github.com/twentyhq/core-team-issues/issues/545

This PR:
- Introduces `commandMenuNavigationMorphItemsState` which stores the
information about the `recordId` and the `objectMetadataItemId` for each
page
- Creates `CommandMenuContextChipEffect`, which queries the records from
the previous pages in case a record has been updated during the
navigation, to keep up to date information and stores it inside
`commandMenuNavigationRecordsState`
- `useCommandMenuContextChips` returns the context chips information
- Style updates (icons background and color)
- Updates `useCommandMenu` to set and reset these new states


https://github.com/user-attachments/assets/8886848a-721d-4709-9330-8e84ebc0d51e
This commit is contained in:
Raphaël Bosi
2025-03-12 15:26:14 +01:00
committed by GitHub
parent e030fc8917
commit bfc542290b
22 changed files with 620 additions and 174 deletions
@@ -0,0 +1,133 @@
import { CommandMenuContextRecordChipAvatars } from '@/command-menu/components/CommandMenuContextRecordChipAvatars';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { commandMenuNavigationMorphItemByPageState } from '@/command-menu/states/commandMenuNavigationMorphItemsState';
import { commandMenuNavigationRecordsState } from '@/command-menu/states/commandMenuNavigationRecordsState';
import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState';
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
import { getObjectRecordIdentifier } from '@/object-metadata/utils/getObjectRecordIdentifier';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useMemo } from 'react';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared';
const StyledIconWrapper = styled.div`
background: ${({ theme }) => theme.background.primary};
border-radius: ${({ theme }) => theme.border.radius.sm};
display: flex;
align-items: center;
justify-content: center;
`;
export const useCommandMenuContextChips = () => {
const commandMenuNavigationStack = useRecoilValue(
commandMenuNavigationStackState,
);
const { navigateCommandMenuHistory } = useCommandMenu();
const theme = useTheme();
const commandMenuNavigationMorphItemByPage = useRecoilValue(
commandMenuNavigationMorphItemByPageState,
);
const commandMenuNavigationRecords = useRecoilValue(
commandMenuNavigationRecordsState,
);
const contextChips = useMemo(() => {
const filteredCommandMenuNavigationStack =
commandMenuNavigationStack.filter(
(page) => page.page !== CommandMenuPages.Root,
);
return filteredCommandMenuNavigationStack
.map((page, index) => {
const isLastChip =
index === filteredCommandMenuNavigationStack.length - 1;
const isRecordPage = page.page === CommandMenuPages.ViewRecord;
if (isRecordPage && !isLastChip) {
const commandMenuNavigationMorphItem =
commandMenuNavigationMorphItemByPage.get(page.pageId);
if (!isDefined(commandMenuNavigationMorphItem?.recordId)) {
return null;
}
const objectMetadataItem = commandMenuNavigationRecords.find(
({ objectMetadataItem }) =>
objectMetadataItem.id ===
commandMenuNavigationMorphItem.objectMetadataId,
)?.objectMetadataItem;
const record = commandMenuNavigationRecords.find(
({ record }) =>
record.id === commandMenuNavigationMorphItem.recordId,
)?.record;
if (!isDefined(objectMetadataItem) || !isDefined(record)) {
return null;
}
const name = getObjectRecordIdentifier({
objectMetadataItem,
record,
}).name;
return {
page,
Icons: [
<CommandMenuContextRecordChipAvatars
objectMetadataItem={objectMetadataItem}
record={record}
/>,
],
text: name,
onClick: () => {
navigateCommandMenuHistory(index);
},
};
}
return {
page,
Icons: isLastChip
? [<page.pageIcon size={theme.icon.size.sm} />]
: [
<StyledIconWrapper>
<page.pageIcon
size={theme.icon.size.sm}
color={
isDefined(page.pageIconColor) &&
page.pageIconColor !== 'currentColor'
? page.pageIconColor
: theme.font.color.tertiary
}
/>
</StyledIconWrapper>,
],
text: page.pageTitle,
onClick: isLastChip
? undefined
: () => {
navigateCommandMenuHistory(index);
},
};
})
.filter(isDefined);
}, [
commandMenuNavigationMorphItemByPage,
commandMenuNavigationRecords,
commandMenuNavigationStack,
navigateCommandMenuHistory,
theme.font.color.tertiary,
theme.icon.size.sm,
]);
return {
contextChips,
};
};