@@ -14,6 +14,8 @@ import { Button, ButtonProps } from '../Button';
14
14
import { IconButton } from '../IconButton' ;
15
15
import { Link , LinkProps } from '../Link' ;
16
16
17
+ import { getIconColor , getTextColor , getBackgroundColorHover } from './utils' ;
18
+
17
19
/* -------------------------------------------------------------------------------------------------
18
20
* MenuRoot
19
21
* -----------------------------------------------------------------------------------------------*/
@@ -142,13 +144,15 @@ const DropdownMenuContent = styled(DropdownMenu.Content)`
142
144
/* -------------------------------------------------------------------------------------------------
143
145
* MenuItem
144
146
* -----------------------------------------------------------------------------------------------*/
147
+ export type ItemVariant = 'danger' | 'default' ;
145
148
146
149
interface ItemSharedProps extends Pick < DropdownMenu . MenuItemProps , 'disabled' | 'onSelect' > {
147
150
children ?: React . ReactNode ;
148
151
isExternal ?: boolean ;
149
152
isFocused ?: boolean ;
150
153
startIcon ?: React . ReactNode ;
151
154
endIcon ?: React . ReactNode ;
155
+ variant ?: ItemVariant ;
152
156
}
153
157
154
158
interface ItemExternalLinkProps extends ItemSharedProps , Omit < LinkProps , 'onSelect' > {
@@ -175,38 +179,49 @@ type ItemProps<TComponent extends React.ComponentType = typeof BaseLink> =
175
179
| ItemInternalLinkProps < TComponent >
176
180
| ItemExternalLinkProps ;
177
181
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 ) => {
179
192
return (
180
193
< DropdownMenu . Item asChild onSelect = { onSelect } disabled = { disabled } >
181
194
{ isLink || isExternal ? (
182
195
< OptionLink
183
- color = "neutral800"
196
+ color = { getTextColor ( variant , disabled ) }
184
197
startIcon = { startIcon }
185
198
endIcon = { endIcon }
186
199
{ ...props }
187
200
isExternal = { isExternal ?? false }
201
+ $variant = { variant }
188
202
>
189
- < Typography > { props . children } </ Typography >
203
+ { props . children }
190
204
</ OptionLink >
191
205
) : (
192
206
< OptionButton
193
207
cursor = "pointer"
194
- color = "neutral800"
208
+ color = { getTextColor ( variant , disabled ) }
195
209
background = "transparent"
196
210
borderStyle = "none"
197
211
gap = { 2 }
212
+ $variant = { variant }
198
213
{ ...props }
199
214
>
200
215
{ startIcon && (
201
- < Flex tag = "span" aria-hidden >
216
+ < Flex tag = "span" color = { getIconColor ( variant , disabled ) } aria-hidden >
202
217
{ startIcon }
203
218
</ Flex >
204
219
) }
205
220
206
221
< Typography grow = { 1 } > { props . children } </ Typography >
207
222
208
223
{ endIcon && (
209
- < Flex tag = "span" aria-hidden >
224
+ < Flex tag = "span" color = { getIconColor ( variant , disabled ) } aria-hidden >
210
225
{ endIcon }
211
226
</ Flex >
212
227
) }
@@ -216,19 +231,18 @@ const MenuItem = ({ onSelect, disabled = false, isLink, startIcon, endIcon, isEx
216
231
) ;
217
232
} ;
218
233
219
- const getOptionStyle = ( { theme } : { theme : DefaultTheme } ) => css `
234
+ const getOptionStyle = ( { theme, $variant } : { theme : DefaultTheme ; $variant : ItemVariant } ) => css `
220
235
text-align : left;
221
236
width : 100% ;
222
237
border-radius : ${ theme . borderRadius } ;
223
238
padding : ${ theme . spaces [ 2 ] } ${ theme . spaces [ 4 ] } ;
224
239
225
240
& [aria-disabled = 'true' ] {
226
241
cursor : not-allowed;
227
- color : ${ theme . colors . neutral500 } ;
228
242
}
229
243
230
244
& [data-highlighted ] {
231
- background-color : ${ theme . colors . primary100 } ;
245
+ background-color : ${ theme . colors [ getBackgroundColorHover ( $variant ) ] } ;
232
246
}
233
247
234
248
& : focus-visible {
@@ -240,11 +254,11 @@ const getOptionStyle = ({ theme }: { theme: DefaultTheme }) => css`
240
254
}
241
255
` ;
242
256
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 } ) }
245
259
` ;
246
260
247
- const OptionLink = styled ( Link ) `
261
+ const OptionLink = styled ( Link ) < { $variant : ItemVariant } > `
248
262
/* We include this here again because typically when people use OptionLink they provide an as prop which cancels the Box props */
249
263
color: ${ ( { theme, color } ) => extractStyleFromTheme ( theme . colors , color , undefined ) } ;
250
264
text-decoration: none;
@@ -259,7 +273,7 @@ const OptionLink = styled(Link)`
259
273
fill: currentColor;
260
274
}
261
275
262
- ${ getOptionStyle }
276
+ ${ ( { theme , $variant } ) => getOptionStyle ( { theme , $variant } ) }
263
277
` ;
264
278
265
279
/* -------------------------------------------------------------------------------------------------
@@ -334,7 +348,7 @@ const MenuSubTrigger = React.forwardRef<HTMLButtonElement, SubTriggerProps>(({ d
334
348
) ;
335
349
} ) ;
336
350
337
- const SubmenuTrigger = styled ( OptionButton ) `
351
+ const SubmenuTrigger = styled < FlexComponent < 'button' | 'a' > > ( OptionButton ) `
338
352
&[data-state='open'] {
339
353
background-color: ${ ( { theme } ) => theme . colors . primary100 } ;
340
354
}
0 commit comments