@@ -10,17 +10,14 @@ import {Node} from '@react-types/shared';
10
10
import { IconChevron } from 'sentry/icons' ;
11
11
import overflowEllipsis from 'sentry/styles/overflowEllipsis' ;
12
12
import space from 'sentry/styles/space' ;
13
+ import { Theme } from 'sentry/utils/theme' ;
13
14
15
+ type Priority = 'primary' | 'danger' ;
14
16
export type MenuItemProps = {
15
17
/**
16
18
* Item key. Must be unique across the entire menu, including sub-menus.
17
19
*/
18
20
key : string ;
19
- /**
20
- * Item label. Should prefereably be a string. If not, make sure that
21
- * there are appropriate aria-labels.
22
- */
23
- label : React . ReactNode ;
24
21
/**
25
22
* Sub-items that are nested inside this item. By default, sub-items are
26
23
* rendered collectively as menu sections inside the current menu. If
@@ -37,6 +34,11 @@ export type MenuItemProps = {
37
34
* when `children` is also defined.
38
35
*/
39
36
isSubmenu ?: boolean ;
37
+ /**
38
+ * Item label. Should prefereably be a string. If not, make sure that
39
+ * there are appropriate aria-labels.
40
+ */
41
+ label ?: React . ReactNode ;
40
42
/*
41
43
* Items to be added to the left of the label
42
44
*/
@@ -52,6 +54,11 @@ export type MenuItemProps = {
52
54
* item's key is passed as an argument.
53
55
*/
54
56
onAction ?: ( key : MenuItemProps [ 'key' ] ) => void ;
57
+ /**
58
+ * Accented text and background (on hover) colors. Primary = purple, and
59
+ * danger = red.
60
+ */
61
+ priority ?: Priority ;
55
62
/**
56
63
* Whether to show a line divider below this menu item
57
64
*/
@@ -194,6 +201,7 @@ const MenuItem = withRouter(
194
201
keyboardProps
195
202
) ;
196
203
const {
204
+ priority,
197
205
details,
198
206
leadingItems,
199
207
leadingItemsSpanFullHeight,
@@ -208,11 +216,13 @@ const MenuItem = withRouter(
208
216
ref = { ref }
209
217
as = { renderAs }
210
218
isDisabled = { isDisabled }
219
+ priority = { priority }
211
220
data-test-id = { item . key }
221
+ { ...( item . to && { 'data-test-href' : item . to } ) }
212
222
{ ...props }
213
223
{ ...( isSubmenuTrigger && { role : 'menuitemradio' } ) }
214
224
>
215
- < InnerWrap isFocused = { isFocused } >
225
+ < InnerWrap isFocused = { isFocused } priority = { priority } >
216
226
{ leadingItems && (
217
227
< LeadingItems
218
228
isDisabled = { isDisabled }
@@ -223,10 +233,18 @@ const MenuItem = withRouter(
223
233
) }
224
234
< ContentWrap isFocused = { isFocused } showDividers = { showDividers } >
225
235
< LabelWrap >
226
- < Label isDisabled = { isDisabled } { ...labelProps } aria-hidden = "true" >
236
+ < Label { ...labelProps } aria-hidden = "true" >
227
237
{ label }
228
238
</ Label >
229
- { details && < Details { ...descriptionProps } > { details } </ Details > }
239
+ { details && (
240
+ < Details
241
+ isDisabled = { isDisabled }
242
+ priority = { priority }
243
+ { ...descriptionProps }
244
+ >
245
+ { details }
246
+ </ Details >
247
+ ) }
230
248
</ LabelWrap >
231
249
{ ( trailingItems || isSubmenuTrigger ) && (
232
250
< TrailingItems
@@ -247,16 +265,26 @@ const MenuItem = withRouter(
247
265
) ;
248
266
export default MenuItem ;
249
267
250
- const MenuItemWrap = styled ( 'li' ) < { isDisabled ?: boolean } > `
268
+ const MenuItemWrap = styled ( 'li' ) < {
269
+ isDisabled ?: boolean ;
270
+ isFocused ?: boolean ;
271
+ priority ?: Priority ;
272
+ } > `
251
273
position: static;
252
274
list-style-type: none;
253
275
margin: 0;
254
276
padding: 0 ${ space ( 0.5 ) } ;
255
277
cursor: pointer;
256
278
257
279
color: ${ p => p . theme . textColor } ;
258
-
259
- ${ p => p . isDisabled && `cursor: initial;` }
280
+ ${ p => p . priority === 'primary' && `color: ${ p . theme . activeText } ;` }
281
+ ${ p => p . priority === 'danger' && `color: ${ p . theme . errorText } ;` }
282
+ ${ p =>
283
+ p . isDisabled &&
284
+ `
285
+ color: ${ p . theme . subText } ;
286
+ cursor: initial;
287
+ ` }
260
288
261
289
&:focus {
262
290
outline: none;
@@ -266,14 +294,30 @@ const MenuItemWrap = styled('li')<{isDisabled?: boolean}>`
266
294
}
267
295
` ;
268
296
269
- const InnerWrap = styled ( 'div' ) < { isFocused : boolean } > `
297
+ const getHoverBackground = ( theme : Theme , priority ?: Priority ) => {
298
+ let hoverBackground : string ;
299
+ switch ( priority ) {
300
+ case 'primary' :
301
+ hoverBackground = theme . purple100 ;
302
+ break ;
303
+ case 'danger' :
304
+ hoverBackground = theme . red100 ;
305
+ break ;
306
+ default :
307
+ hoverBackground = theme . hover ;
308
+ }
309
+
310
+ return `background: ${ hoverBackground } ; z-index: 1;` ;
311
+ } ;
312
+
313
+ const InnerWrap = styled ( 'div' ) < { isFocused : boolean ; priority ?: Priority } > `
270
314
display: flex;
271
315
position: relative;
272
316
padding: 0 ${ space ( 1 ) } ;
273
317
border-radius: ${ p => p . theme . borderRadius } ;
274
318
box-sizing: border-box;
275
319
276
- ${ p => p . isFocused && `background: ${ p . theme . hover } ; z-index: 1;` }
320
+ ${ p => p . isFocused && getHoverBackground ( p . theme , p . priority ) }
277
321
` ;
278
322
279
323
const LeadingItems = styled ( 'div' ) < { isDisabled ?: boolean ; spanFullHeight ?: boolean } > `
@@ -319,21 +363,23 @@ const LabelWrap = styled('div')`
319
363
width: 100%;
320
364
` ;
321
365
322
- const Label = styled ( 'p' ) < { isDisabled ?: boolean } > `
366
+ const Label = styled ( 'p' ) `
323
367
margin-bottom: 0;
324
368
line-height: 1.4;
325
369
white-space: nowrap;
326
370
${ overflowEllipsis }
327
-
328
- ${ p => p . isDisabled && `color: ${ p . theme . subText } ;` }
329
371
` ;
330
372
331
- const Details = styled ( 'p' ) `
373
+ const Details = styled ( 'p' ) < { isDisabled : boolean ; priority ?: Priority } > `
332
374
font-size: ${ p => p . theme . fontSizeSmall } ;
333
375
color: ${ p => p . theme . subText } ;
334
376
line-height: 1.2;
335
377
margin-bottom: 0;
336
378
${ overflowEllipsis }
379
+
380
+ ${ p => p . priority === 'primary' && `color: ${ p . theme . activeText } ;` }
381
+ ${ p => p . priority === 'danger' && `color: ${ p . theme . errorText } ;` }
382
+ ${ p => p . isDisabled && `color: ${ p . theme . subText } ;` }
337
383
` ;
338
384
339
385
const TrailingItems = styled ( 'div' ) < { isDisabled ?: boolean ; spanFullHeight ?: boolean } > `
0 commit comments