Improve command menu chip design (#9915)

Before:

<img width="236" alt="Capture d’écran 2025-01-29 à 17 07 13"
src="https://github.com/user-attachments/assets/edc277f3-3e50-405a-9981-3ac63e270f3f"
/>
<img width="259" alt="Capture d’écran 2025-01-29 à 17 07 23"
src="https://github.com/user-attachments/assets/81863c50-5b96-4cbf-bc15-ab437d839fa1"
/>
<img width="224" alt="Capture d’écran 2025-01-29 à 17 07 41"
src="https://github.com/user-attachments/assets/c0783544-6928-4b05-bf86-66d37ddca5e5"
/>

After:

<img width="230" alt="Capture d’écran 2025-01-29 à 17 03 49"
src="https://github.com/user-attachments/assets/c47be446-32fa-40d1-af25-207ed91c0ea2"
/>
<img width="254" alt="Capture d’écran 2025-01-29 à 17 04 15"
src="https://github.com/user-attachments/assets/99b9ab30-c77d-4392-8ef6-2a1a5fb00047"
/>
<img width="218" alt="Capture d’écran 2025-01-29 à 17 04 37"
src="https://github.com/user-attachments/assets/6e214a42-438d-495f-9855-fd5397fcc6d3"
/>
This commit is contained in:
Raphaël Bosi
2025-01-29 17:37:59 +01:00
committed by GitHub
parent 9d32e63111
commit 04bc42aa47
6 changed files with 32 additions and 53 deletions

View File

@ -1,6 +1,7 @@
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { Fragment } from 'react/jsx-runtime';
const StyledChip = styled.div<{ variant?: 'default' | 'small' }>` const StyledChip = styled.div`
align-items: center; align-items: center;
background: ${({ theme }) => theme.background.transparent.light}; background: ${({ theme }) => theme.background.transparent.light};
border: 1px solid ${({ theme }) => theme.border.color.medium}; border: 1px solid ${({ theme }) => theme.border.color.medium};
@ -8,8 +9,7 @@ const StyledChip = styled.div<{ variant?: 'default' | 'small' }>`
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
gap: ${({ theme }) => theme.spacing(1)}; gap: ${({ theme }) => theme.spacing(1)};
height: ${({ theme, variant }) => height: ${({ theme }) => theme.spacing(6)};
variant === 'small' ? theme.spacing(6) : theme.spacing(8)};
padding: 0 ${({ theme }) => theme.spacing(2)}; padding: 0 ${({ theme }) => theme.spacing(2)};
font-size: ${({ theme }) => theme.font.size.sm}; font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme }) => theme.font.weight.medium}; font-weight: ${({ theme }) => theme.font.weight.medium};
@ -21,43 +21,18 @@ const StyledIconsContainer = styled.div`
display: flex; display: flex;
`; `;
const StyledIconWrapper = styled.div<{ withIconBackground?: boolean }>`
background: ${({ theme, withIconBackground }) =>
withIconBackground ? theme.background.primary : 'unset'};
border-radius: ${({ theme }) => theme.border.radius.sm};
padding: ${({ theme }) => theme.spacing(0.5)};
border: 1px solid
${({ theme, withIconBackground }) =>
withIconBackground ? theme.border.color.medium : 'transparent'};
&:not(:first-of-type) {
margin-left: -${({ theme }) => theme.spacing(1)};
}
display: flex;
align-items: center;
justify-content: center;
`;
export const CommandMenuContextChip = ({ export const CommandMenuContextChip = ({
Icons, Icons,
text, text,
withIconBackground,
variant = 'default',
}: { }: {
Icons: React.ReactNode[]; Icons: React.ReactNode[];
text?: string; text?: string;
withIconBackground?: boolean;
variant?: 'default' | 'small';
}) => { }) => {
return ( return (
<StyledChip variant={variant}> <StyledChip>
<StyledIconsContainer> <StyledIconsContainer>
{Icons.map((Icon, index) => ( {Icons.map((Icon, index) => (
<StyledIconWrapper <Fragment key={index}>{Icon}</Fragment>
key={index}
withIconBackground={withIconBackground}
>
{Icon}
</StyledIconWrapper>
))} ))}
</StyledIconsContainer> </StyledIconsContainer>
<span>{text}</span> <span>{text}</span>

View File

@ -7,11 +7,9 @@ import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMeta
export const CommandMenuContextRecordChip = ({ export const CommandMenuContextRecordChip = ({
objectMetadataItemId, objectMetadataItemId,
instanceId, instanceId,
variant = 'default',
}: { }: {
objectMetadataItemId: string; objectMetadataItemId: string;
instanceId?: string; instanceId?: string;
variant?: 'default' | 'small';
}) => { }) => {
const { objectMetadataItem } = useObjectMetadataItemById({ const { objectMetadataItem } = useObjectMetadataItemById({
objectId: objectMetadataItemId, objectId: objectMetadataItemId,
@ -43,8 +41,6 @@ export const CommandMenuContextRecordChip = ({
totalCount, totalCount,
)} )}
Icons={Avatars} Icons={Avatars}
withIconBackground={true}
variant={variant}
/> />
); );
}; };

View File

@ -3,8 +3,24 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useRecordChipData } from '@/object-record/hooks/useRecordChipData'; import { useRecordChipData } from '@/object-record/hooks/useRecordChipData';
import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { useTheme } from '@emotion/react'; import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { Avatar } from 'twenty-ui'; import { Avatar } from 'twenty-ui';
const StyledIconWrapper = styled.div<{ withIconBackground?: boolean }>`
background: ${({ theme, withIconBackground }) =>
withIconBackground ? theme.background.primary : 'unset'};
border-radius: ${({ theme }) => theme.border.radius.sm};
border: 1px solid
${({ theme, withIconBackground }) =>
withIconBackground ? theme.border.color.medium : 'transparent'};
&:not(:first-of-type) {
margin-left: -${({ theme }) => theme.spacing(1)};
}
display: flex;
align-items: center;
justify-content: center;
`;
export const CommandMenuContextRecordChipAvatars = ({ export const CommandMenuContextRecordChipAvatars = ({
objectMetadataItem, objectMetadataItem,
record, record,
@ -24,7 +40,9 @@ export const CommandMenuContextRecordChipAvatars = ({
const theme = useTheme(); const theme = useTheme();
return ( return (
<> <StyledIconWrapper
withIconBackground={recordChipData.avatarType !== 'rounded'}
>
{Icon ? ( {Icon ? (
<Icon color={IconColor} size={theme.icon.size.sm} /> <Icon color={IconColor} size={theme.icon.size.sm} />
) : ( ) : (
@ -36,6 +54,6 @@ export const CommandMenuContextRecordChipAvatars = ({
size="sm" size="sm"
/> />
)} )}
</> </StyledIconWrapper>
); );
}; };

View File

@ -47,7 +47,6 @@ export const ResetContextToSelectionCommandButton = () => {
<CommandMenuContextRecordChip <CommandMenuContextRecordChip
objectMetadataItemId={objectMetadataItem.id} objectMetadataItemId={objectMetadataItem.id}
instanceId="command-menu-previous" instanceId="command-menu-previous"
variant="small"
/> />
} }
onClick={resetPreviousCommandMenuContext} onClick={resetPreviousCommandMenuContext}

View File

@ -30,22 +30,6 @@ export const MultipleIcons: Story = {
}, },
}; };
export const WithIconBackground: Story = {
args: {
Icons: [<IconUser size={16} />],
text: 'Person',
withIconBackground: true,
},
};
export const MultipleIconsWithIconBackground: Story = {
args: {
Icons: [<IconUser size={16} />, <IconBuildingSkyscraper size={16} />],
text: 'Person & Company',
withIconBackground: true,
},
};
export const IconsOnly: Story = { export const IconsOnly: Story = {
args: { args: {
Icons: [<IconUser size={16} />, <IconBuildingSkyscraper size={16} />], Icons: [<IconUser size={16} />, <IconBuildingSkyscraper size={16} />],

View File

@ -9,5 +9,12 @@ export const getAvatarType = (objectNameSingular: string) => {
return 'squared'; return 'squared';
} }
if (
objectNameSingular === CoreObjectNameSingular.Task ||
objectNameSingular === CoreObjectNameSingular.Note
) {
return 'icon';
}
return 'rounded'; return 'rounded';
}; };