Skip to content

Commit 20fb5ea

Browse files
authored
fix: variant danger and icon color in menu item (#1923)
1 parent a3535e7 commit 20fb5ea

File tree

5 files changed

+68
-18
lines changed

5 files changed

+68
-18
lines changed

.changeset/heavy-ducks-complain.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@strapi/design-system': patch
3+
---
4+
5+
fix: variant danger and icon color in menu item

docs/stories/SimpleMenu.stories.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Meta, StoryObj } from '@storybook/react';
22
import { IconButton, SimpleMenu, MenuItem, Menu } from '@strapi/design-system';
3-
import { Bell } from '@strapi/icons';
3+
import { Bell, Check, WarningCircle } from '@strapi/icons';
44

55
const meta: Meta<typeof SimpleMenu> = {
66
title: 'Design System/Components/SimpleMenu',
@@ -21,10 +21,10 @@ export const Basic = {
2121
Open
2222
</MenuItem>
2323
<MenuItem endIcon={<Bell />} disabled onSelect={() => console.log('cloning')}>
24-
Clone
24+
Disabled
2525
</MenuItem>
2626
<MenuItem onSelect={() => console.log('editing')}>Edit</MenuItem>
27-
<MenuItem color="danger600" onSelect={() => console.log('delete')}>
27+
<MenuItem startIcon={<Bell />} variant="danger" onSelect={() => console.log('delete')}>
2828
Delete
2929
</MenuItem>
3030
</SimpleMenu>

packages/design-system/src/components/SimpleMenu/Menu.tsx

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import { Button, ButtonProps } from '../Button';
1414
import { IconButton } from '../IconButton';
1515
import { Link, LinkProps } from '../Link';
1616

17+
import { getIconColor, getTextColor, getBackgroundColorHover } from './utils';
18+
1719
/* -------------------------------------------------------------------------------------------------
1820
* MenuRoot
1921
* -----------------------------------------------------------------------------------------------*/
@@ -142,13 +144,15 @@ const DropdownMenuContent = styled(DropdownMenu.Content)`
142144
/* -------------------------------------------------------------------------------------------------
143145
* MenuItem
144146
* -----------------------------------------------------------------------------------------------*/
147+
export type ItemVariant = 'danger' | 'default';
145148

146149
interface ItemSharedProps extends Pick<DropdownMenu.MenuItemProps, 'disabled' | 'onSelect'> {
147150
children?: React.ReactNode;
148151
isExternal?: boolean;
149152
isFocused?: boolean;
150153
startIcon?: React.ReactNode;
151154
endIcon?: React.ReactNode;
155+
variant?: ItemVariant;
152156
}
153157

154158
interface ItemExternalLinkProps extends ItemSharedProps, Omit<LinkProps, 'onSelect'> {
@@ -175,38 +179,49 @@ type ItemProps<TComponent extends React.ComponentType = typeof BaseLink> =
175179
| ItemInternalLinkProps<TComponent>
176180
| ItemExternalLinkProps;
177181

178-
const MenuItem = ({ onSelect, disabled = false, isLink, startIcon, endIcon, isExternal, ...props }: ItemProps) => {
182+
const MenuItem = ({
183+
onSelect,
184+
disabled = false,
185+
isLink,
186+
startIcon,
187+
endIcon,
188+
isExternal,
189+
variant = 'default',
190+
...props
191+
}: ItemProps) => {
179192
return (
180193
<DropdownMenu.Item asChild onSelect={onSelect} disabled={disabled}>
181194
{isLink || isExternal ? (
182195
<OptionLink
183-
color="neutral800"
196+
color={getTextColor(variant, disabled)}
184197
startIcon={startIcon}
185198
endIcon={endIcon}
186199
{...props}
187200
isExternal={isExternal ?? false}
201+
$variant={variant}
188202
>
189-
<Typography>{props.children}</Typography>
203+
{props.children}
190204
</OptionLink>
191205
) : (
192206
<OptionButton
193207
cursor="pointer"
194-
color="neutral800"
208+
color={getTextColor(variant, disabled)}
195209
background="transparent"
196210
borderStyle="none"
197211
gap={2}
212+
$variant={variant}
198213
{...props}
199214
>
200215
{startIcon && (
201-
<Flex tag="span" aria-hidden>
216+
<Flex tag="span" color={getIconColor(variant, disabled)} aria-hidden>
202217
{startIcon}
203218
</Flex>
204219
)}
205220

206221
<Typography grow={1}>{props.children}</Typography>
207222

208223
{endIcon && (
209-
<Flex tag="span" aria-hidden>
224+
<Flex tag="span" color={getIconColor(variant, disabled)} aria-hidden>
210225
{endIcon}
211226
</Flex>
212227
)}
@@ -216,19 +231,18 @@ const MenuItem = ({ onSelect, disabled = false, isLink, startIcon, endIcon, isEx
216231
);
217232
};
218233

219-
const getOptionStyle = ({ theme }: { theme: DefaultTheme }) => css`
234+
const getOptionStyle = ({ theme, $variant }: { theme: DefaultTheme; $variant: ItemVariant }) => css`
220235
text-align: left;
221236
width: 100%;
222237
border-radius: ${theme.borderRadius};
223238
padding: ${theme.spaces[2]} ${theme.spaces[4]};
224239
225240
&[aria-disabled='true'] {
226241
cursor: not-allowed;
227-
color: ${theme.colors.neutral500};
228242
}
229243
230244
&[data-highlighted] {
231-
background-color: ${theme.colors.primary100};
245+
background-color: ${theme.colors[getBackgroundColorHover($variant)]};
232246
}
233247
234248
&:focus-visible {
@@ -240,11 +254,11 @@ const getOptionStyle = ({ theme }: { theme: DefaultTheme }) => css`
240254
}
241255
`;
242256

243-
const OptionButton = styled<FlexComponent<'button' | 'a'>>(Flex)`
244-
${getOptionStyle}
257+
const OptionButton = styled<FlexComponent<'button' | 'a'>>(Flex)<{ $variant: ItemVariant }>`
258+
${({ theme, $variant }) => getOptionStyle({ theme, $variant })}
245259
`;
246260

247-
const OptionLink = styled(Link)`
261+
const OptionLink = styled(Link)<{ $variant: ItemVariant }>`
248262
/* We include this here again because typically when people use OptionLink they provide an as prop which cancels the Box props */
249263
color: ${({ theme, color }) => extractStyleFromTheme(theme.colors, color, undefined)};
250264
text-decoration: none;
@@ -259,7 +273,7 @@ const OptionLink = styled(Link)`
259273
fill: currentColor;
260274
}
261275
262-
${getOptionStyle}
276+
${({ theme, $variant }) => getOptionStyle({ theme, $variant })}
263277
`;
264278

265279
/* -------------------------------------------------------------------------------------------------
@@ -334,7 +348,7 @@ const MenuSubTrigger = React.forwardRef<HTMLButtonElement, SubTriggerProps>(({ d
334348
);
335349
});
336350

337-
const SubmenuTrigger = styled(OptionButton)`
351+
const SubmenuTrigger = styled<FlexComponent<'button' | 'a'>>(OptionButton)`
338352
&[data-state='open'] {
339353
background-color: ${({ theme }) => theme.colors.primary100};
340354
}

packages/design-system/src/components/SimpleMenu/SimpleMenu.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { stripReactIdOfColon } from '../../helpers/strings';
44
import { useComposedRefs } from '../../hooks/useComposeRefs';
55
import { useId } from '../../hooks/useId';
66
import { useIntersection } from '../../hooks/useIntersection';
7+
import { BaseLink } from '../BaseLink';
78

89
import * as Menu from './Menu';
910

@@ -75,7 +76,7 @@ const SimpleMenu = React.forwardRef<HTMLButtonElement, SimpleMenuProps>(
7576
);
7677

7778
const MenuItem = Menu.Item;
78-
type MenuItemProps = Menu.ItemProps;
79+
type MenuItemProps<T extends React.ComponentType = typeof BaseLink> = Menu.ItemProps<T>;
7980

8081
export { SimpleMenu, MenuItem, Menu };
8182
export type { SimpleMenuProps, MenuItemProps };
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { DefaultTheme } from 'styled-components';
2+
3+
import type { ItemVariant } from './Menu';
4+
5+
export const getBackgroundColorHover = (variant: ItemVariant): keyof DefaultTheme['colors'] => {
6+
switch (variant) {
7+
case 'danger':
8+
return 'danger100';
9+
default:
10+
return 'primary100';
11+
}
12+
};
13+
14+
export const getTextColor = (variant: ItemVariant, disabled?: boolean): keyof DefaultTheme['colors'] => {
15+
switch (variant) {
16+
case 'danger':
17+
return disabled ? 'danger500' : 'danger700';
18+
default:
19+
return disabled ? 'neutral500' : 'neutral800';
20+
}
21+
};
22+
23+
export const getIconColor = (variant: ItemVariant, disabled?: boolean): keyof DefaultTheme['colors'] => {
24+
switch (variant) {
25+
case 'danger':
26+
return disabled ? 'danger500' : 'danger700';
27+
default:
28+
return disabled ? 'neutral300' : 'neutral500';
29+
}
30+
};

0 commit comments

Comments
 (0)