323 add object name inside the search (#9962)
Closes https://github.com/twentyhq/core-team-issues/issues/323 Before: <img width="495" alt="Capture d’écran 2025-01-31 à 18 11 56" src="https://github.com/user-attachments/assets/dd1d3ac1-6c97-4398-b233-d323eeacdbb9" /> After: <img width="500" alt="Capture d’écran 2025-01-31 à 18 09 58" src="https://github.com/user-attachments/assets/68d23990-2d0b-437d-ad2e-a686cdb320e1" />
This commit is contained in:
@ -8,6 +8,7 @@ import { ReactNode } from 'react';
|
|||||||
|
|
||||||
export type CommandMenuItemProps = {
|
export type CommandMenuItemProps = {
|
||||||
label: string;
|
label: string;
|
||||||
|
description?: string;
|
||||||
to?: string;
|
to?: string;
|
||||||
id: string;
|
id: string;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
@ -19,6 +20,7 @@ export type CommandMenuItemProps = {
|
|||||||
|
|
||||||
export const CommandMenuItem = ({
|
export const CommandMenuItem = ({
|
||||||
label,
|
label,
|
||||||
|
description,
|
||||||
to,
|
to,
|
||||||
id,
|
id,
|
||||||
onClick,
|
onClick,
|
||||||
@ -40,6 +42,7 @@ export const CommandMenuItem = ({
|
|||||||
<MenuItemCommand
|
<MenuItemCommand
|
||||||
LeftIcon={Icon}
|
LeftIcon={Icon}
|
||||||
text={label}
|
text={label}
|
||||||
|
description={description}
|
||||||
hotKeys={hotKeys}
|
hotKeys={hotKeys}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
onItemClick({
|
onItemClick({
|
||||||
|
|||||||
@ -124,6 +124,7 @@ export const CommandMenuList = ({
|
|||||||
id={item.id}
|
id={item.id}
|
||||||
Icon={item.Icon}
|
Icon={item.Icon}
|
||||||
label={item.label}
|
label={item.label}
|
||||||
|
description={item.description}
|
||||||
to={item.to}
|
to={item.to}
|
||||||
onClick={item.onCommandClick}
|
onClick={item.onCommandClick}
|
||||||
hotKeys={item.hotKeys}
|
hotKeys={item.hotKeys}
|
||||||
|
|||||||
@ -123,6 +123,8 @@ export const SearchRecordsAction: Story = {
|
|||||||
await sleep(openTimeout);
|
await sleep(openTimeout);
|
||||||
await userEvent.type(searchInput, 'n');
|
await userEvent.type(searchInput, 'n');
|
||||||
expect(await canvas.findByText('Linkedin')).toBeVisible();
|
expect(await canvas.findByText('Linkedin')).toBeVisible();
|
||||||
|
const companyTexts = await canvas.findAllByText('Company');
|
||||||
|
expect(companyTexts[0]).toBeVisible();
|
||||||
expect(await canvas.findByText(companiesMock[0].name)).toBeVisible();
|
expect(await canvas.findByText(companiesMock[0].name)).toBeVisible();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -77,6 +77,7 @@ export const useSearchRecords = () => {
|
|||||||
people?.map(({ id, name: { firstName, lastName }, avatarUrl }) => ({
|
people?.map(({ id, name: { firstName, lastName }, avatarUrl }) => ({
|
||||||
id,
|
id,
|
||||||
label: `${firstName} ${lastName}`,
|
label: `${firstName} ${lastName}`,
|
||||||
|
description: 'Person',
|
||||||
to: `object/person/${id}`,
|
to: `object/person/${id}`,
|
||||||
shouldCloseCommandMenuOnClick: true,
|
shouldCloseCommandMenuOnClick: true,
|
||||||
Icon: () => (
|
Icon: () => (
|
||||||
@ -96,6 +97,7 @@ export const useSearchRecords = () => {
|
|||||||
companies?.map((company) => ({
|
companies?.map((company) => ({
|
||||||
id: company.id,
|
id: company.id,
|
||||||
label: company.name ?? '',
|
label: company.name ?? '',
|
||||||
|
description: 'Company',
|
||||||
to: `object/company/${company.id}`,
|
to: `object/company/${company.id}`,
|
||||||
shouldCloseCommandMenuOnClick: true,
|
shouldCloseCommandMenuOnClick: true,
|
||||||
Icon: () => (
|
Icon: () => (
|
||||||
@ -116,6 +118,7 @@ export const useSearchRecords = () => {
|
|||||||
opportunities?.map(({ id, name }) => ({
|
opportunities?.map(({ id, name }) => ({
|
||||||
id,
|
id,
|
||||||
label: name ?? '',
|
label: name ?? '',
|
||||||
|
description: 'Opportunity',
|
||||||
to: `object/opportunity/${id}`,
|
to: `object/opportunity/${id}`,
|
||||||
shouldCloseCommandMenuOnClick: true,
|
shouldCloseCommandMenuOnClick: true,
|
||||||
Icon: () => (
|
Icon: () => (
|
||||||
@ -143,6 +146,7 @@ export const useSearchRecords = () => {
|
|||||||
notes?.map((note) => ({
|
notes?.map((note) => ({
|
||||||
id: note.id,
|
id: note.id,
|
||||||
label: note.title ?? '',
|
label: note.title ?? '',
|
||||||
|
description: 'Note',
|
||||||
to: '',
|
to: '',
|
||||||
onCommandClick: () => openNoteRightDrawer(note.id),
|
onCommandClick: () => openNoteRightDrawer(note.id),
|
||||||
shouldCloseCommandMenuOnClick: true,
|
shouldCloseCommandMenuOnClick: true,
|
||||||
@ -156,6 +160,7 @@ export const useSearchRecords = () => {
|
|||||||
tasks?.map((task) => ({
|
tasks?.map((task) => ({
|
||||||
id: task.id,
|
id: task.id,
|
||||||
label: task.title ?? '',
|
label: task.title ?? '',
|
||||||
|
description: 'Task',
|
||||||
to: '',
|
to: '',
|
||||||
onCommandClick: () => openTaskRightDrawer(task.id),
|
onCommandClick: () => openTaskRightDrawer(task.id),
|
||||||
shouldCloseCommandMenuOnClick: true,
|
shouldCloseCommandMenuOnClick: true,
|
||||||
@ -182,6 +187,7 @@ export const useSearchRecords = () => {
|
|||||||
objectRecords.map((objectRecord) => ({
|
objectRecords.map((objectRecord) => ({
|
||||||
id: objectRecord.record.id,
|
id: objectRecord.record.id,
|
||||||
label: objectRecord.recordIdentifier.name,
|
label: objectRecord.recordIdentifier.name,
|
||||||
|
description: objectRecord.objectMetadataItem.labelSingular,
|
||||||
to: `object/${objectRecord.objectMetadataItem.nameSingular}/${objectRecord.record.id}`,
|
to: `object/${objectRecord.objectMetadataItem.nameSingular}/${objectRecord.record.id}`,
|
||||||
shouldCloseCommandMenuOnClick: true,
|
shouldCloseCommandMenuOnClick: true,
|
||||||
Icon: () => (
|
Icon: () => (
|
||||||
|
|||||||
@ -16,6 +16,7 @@ export type Command = {
|
|||||||
id: string;
|
id: string;
|
||||||
to?: string;
|
to?: string;
|
||||||
label: string;
|
label: string;
|
||||||
|
description?: string;
|
||||||
type?: CommandType;
|
type?: CommandType;
|
||||||
scope?: CommandScope;
|
scope?: CommandScope;
|
||||||
Icon?: IconComponent;
|
Icon?: IconComponent;
|
||||||
|
|||||||
@ -63,9 +63,24 @@ const StyledMenuItemCommandContainer = styled.div<{ isSelected?: boolean }>`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledDescription = styled.span`
|
||||||
|
color: ${({ theme }) => theme.font.color.light};
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '·';
|
||||||
|
margin: ${({ theme }) => theme.spacing(0, 1)};
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledTextContainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
`;
|
||||||
|
|
||||||
export type MenuItemCommandProps = {
|
export type MenuItemCommandProps = {
|
||||||
LeftIcon?: IconComponent;
|
LeftIcon?: IconComponent;
|
||||||
text: string;
|
text: string;
|
||||||
|
description?: string;
|
||||||
hotKeys?: string[];
|
hotKeys?: string[];
|
||||||
className?: string;
|
className?: string;
|
||||||
isSelected?: boolean;
|
isSelected?: boolean;
|
||||||
@ -76,6 +91,7 @@ export type MenuItemCommandProps = {
|
|||||||
export const MenuItemCommand = ({
|
export const MenuItemCommand = ({
|
||||||
LeftIcon,
|
LeftIcon,
|
||||||
text,
|
text,
|
||||||
|
description,
|
||||||
hotKeys,
|
hotKeys,
|
||||||
className,
|
className,
|
||||||
isSelected,
|
isSelected,
|
||||||
@ -97,7 +113,10 @@ export const MenuItemCommand = ({
|
|||||||
<LeftIcon size={theme.icon.size.sm} />
|
<LeftIcon size={theme.icon.size.sm} />
|
||||||
</StyledBigIconContainer>
|
</StyledBigIconContainer>
|
||||||
)}
|
)}
|
||||||
<StyledMenuItemLabelText>{text}</StyledMenuItemLabelText>
|
<StyledTextContainer>
|
||||||
|
<StyledMenuItemLabelText>{text}</StyledMenuItemLabelText>
|
||||||
|
{description && <StyledDescription>{description}</StyledDescription>}
|
||||||
|
</StyledTextContainer>
|
||||||
{RightComponent}
|
{RightComponent}
|
||||||
</StyledMenuItemLeftContent>
|
</StyledMenuItemLeftContent>
|
||||||
{!isMobile && <MenuItemCommandHotKeys hotKeys={hotKeys} />}
|
{!isMobile && <MenuItemCommandHotKeys hotKeys={hotKeys} />}
|
||||||
|
|||||||
@ -35,6 +35,15 @@ export const Default: Story = {
|
|||||||
decorators: [ComponentDecorator],
|
decorators: [ComponentDecorator],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const WithDescription: Story = {
|
||||||
|
args: {
|
||||||
|
text: 'Menu item',
|
||||||
|
hotKeys: ['⌘', '1'],
|
||||||
|
description: 'Description',
|
||||||
|
},
|
||||||
|
decorators: [ComponentDecorator],
|
||||||
|
};
|
||||||
|
|
||||||
export const Catalog: CatalogStory<Story, typeof MenuItemCommand> = {
|
export const Catalog: CatalogStory<Story, typeof MenuItemCommand> = {
|
||||||
args: {
|
args: {
|
||||||
text: 'Menu item',
|
text: 'Menu item',
|
||||||
|
|||||||
Reference in New Issue
Block a user