@@ -29,6 +29,7 @@ import FormField from "components/forms/FormField";
29
29
import DropdownOptionTooltipWrapper from "components/forms/fields/Dropdown/DropdownOptionTooltipWrapper" ;
30
30
import Icon from "components/Icon" ;
31
31
import { IconNames } from "components/icons" ;
32
+ import { TooltipContent } from "interfaces/dropdownOption" ;
32
33
33
34
const getOptionBackgroundColor = (
34
35
state : OptionProps < CustomOptionType , false >
@@ -37,9 +38,9 @@ const getOptionBackgroundColor = (
37
38
} ;
38
39
39
40
export interface CustomOptionType {
40
- label : string ;
41
+ label : React . ReactNode ;
41
42
value : string ;
42
- tooltipContent ?: string ;
43
+ tooltipContent ?: TooltipContent ;
43
44
helpText ?: string ;
44
45
isDisabled ?: boolean ;
45
46
iconName ?: IconNames ;
@@ -62,8 +63,12 @@ export interface IDropdownWrapper {
62
63
placeholder ?: string ;
63
64
/** E.g. scroll to view dropdown menu in a scrollable parent container */
64
65
onMenuOpen ?: ( ) => void ;
65
- /** Table filter dropdowns have filter icon and height: 40px */
66
- tableFilter ?: boolean ;
66
+ /** Table filter dropdowns have filter icon and height: 40px
67
+ * Button dropdowns have hover/active state, padding, height like actual buttons */
68
+ variant ?: "table-filter" | "button" ;
69
+ /** This makes the menu fit all text without wrapping,
70
+ * aligning right to fit text on screen */
71
+ nowrapMenu ?: boolean ;
67
72
}
68
73
69
74
const baseClass = "dropdown-wrapper" ;
@@ -84,10 +89,11 @@ const DropdownWrapper = ({
84
89
iconName,
85
90
placeholder,
86
91
onMenuOpen,
87
- tableFilter = false ,
92
+ variant,
93
+ nowrapMenu,
88
94
} : IDropdownWrapper ) => {
89
95
const wrapperClassNames = classnames ( baseClass , className , {
90
- [ `${ baseClass } __table-filter` ] : tableFilter ,
96
+ [ `${ baseClass } __table-filter` ] : variant === "table-filter" ,
91
97
[ `${ wrapperClassname } ` ] : ! ! wrapperClassname ,
92
98
} ) ;
93
99
@@ -164,7 +170,8 @@ const DropdownWrapper = ({
164
170
children,
165
171
...props
166
172
} : ValueContainerProps < CustomOptionType , false > ) => {
167
- const iconToDisplay = iconName || ( tableFilter ? "filter" : null ) ;
173
+ const iconToDisplay =
174
+ iconName || ( variant === "table-filter" ? "filter" : null ) ;
168
175
169
176
return (
170
177
components . ValueContainer && (
@@ -179,80 +186,150 @@ const DropdownWrapper = ({
179
186
} ;
180
187
181
188
const customStyles : StylesConfig < CustomOptionType , false > = {
182
- container : ( provided ) => ( {
183
- ...provided ,
184
- width : "100%" ,
185
- height : "40px" ,
186
- } ) ,
187
- control : ( provided , state ) => ( {
188
- ...provided ,
189
- display : "flex" ,
190
- flexDirection : "row" ,
191
- width : "100%" ,
192
- backgroundColor : COLORS [ "ui-off-white" ] ,
193
- paddingLeft : "8px" , // TODO: Update to match styleguide of (16px) when updating rest of UI (8px)
194
- paddingRight : "8px" ,
195
- cursor : "pointer" ,
196
- boxShadow : "none" ,
197
- borderRadius : "4px" ,
198
- borderColor : state . isFocused
199
- ? COLORS [ "core-fleet-blue" ]
200
- : COLORS [ "ui-fleet-black-10" ] ,
201
- "&:hover" : {
189
+ container : ( provided ) => {
190
+ const buttonVariantContainer = {
191
+ borderRadius : "6px" ,
192
+ "&:active" : {
193
+ backgroundColor : "rgba(25, 33, 71, 0.05)" ,
194
+ } ,
195
+ height : "38px" ,
196
+ } ;
197
+
198
+ return {
199
+ ...provided ,
200
+ width : "100%" ,
201
+ height : "40px" ,
202
+ ...( variant === "button" && buttonVariantContainer ) ,
203
+ } ;
204
+ } ,
205
+
206
+ control : ( provided , state ) => {
207
+ if ( variant === "button" )
208
+ return {
209
+ backgroundColor : "initial" ,
210
+ borderColor : "none" ,
211
+ display : "flex" ,
212
+ flexDirection : "row" ,
213
+ width : "max-content" ,
214
+ padding : PADDING [ "pad-small" ] ,
215
+ border : 0 ,
216
+ borderRadius : "6px" ,
217
+ boxShadow : "none" ,
218
+ cursor : "pointer" ,
219
+ ".dropdown-wrapper__indicator path" : {
220
+ stroke : COLORS [ "core-fleet-blue" ] ,
221
+ } ,
222
+ "&:hover" : {
223
+ backgroundColor : "rgba(25, 33, 71, 0.05)" ,
224
+ boxShadow : "none" ,
225
+ ".dropdown-wrapper__placeholder" : {
226
+ color : COLORS [ "core-vibrant-blue-over" ] ,
227
+ } ,
228
+ ".dropdown-wrapper__indicator path" : {
229
+ stroke : COLORS [ "core-vibrant-blue-over" ] ,
230
+ } ,
231
+ } ,
232
+ "&.react-select__control--is-focused" : {
233
+ backgroundColor : "rgba(25, 33, 71, 0.05)" ,
234
+ } ,
235
+ "&:active .dropdown-wrapper__indicator path" : {
236
+ stroke : COLORS [ "core-vibrant-blue-down" ] ,
237
+ } ,
238
+ // TODO: Figure out a way to apply separate &:focus-visible styling
239
+ // Currently only relying on &:focus styling for tabbing through app
240
+ ...( state . menuIsOpen && {
241
+ ".dropdown-wrapper__indicator svg" : {
242
+ transform : "rotate(180deg)" ,
243
+ transition : "transform 0.25s ease" ,
244
+ } ,
245
+ } ) ,
246
+ ...( variant === "button" && { height : "22px" } ) ,
247
+ } ;
248
+
249
+ return {
250
+ ...provided ,
251
+ display : "flex" ,
252
+ flexDirection : "row" ,
253
+ width : "100%" ,
254
+ backgroundColor : COLORS [ "ui-off-white" ] ,
255
+ paddingLeft : "8px" , // TODO: Update to match styleguide of (16px) when updating rest of UI (8px)
256
+ paddingRight : "8px" ,
257
+ cursor : "pointer" ,
202
258
boxShadow : "none" ,
203
- borderColor : COLORS [ "core-fleet-blue" ] ,
204
- ".dropdown-wrapper__single-value" : {
205
- color : COLORS [ "core-vibrant-blue-over" ] ,
259
+ borderRadius : "4px" ,
260
+ borderColor : state . isFocused
261
+ ? COLORS [ "core-fleet-blue" ]
262
+ : COLORS [ "ui-fleet-black-10" ] ,
263
+ "&:hover" : {
264
+ boxShadow : "none" ,
265
+ borderColor : COLORS [ "core-fleet-blue" ] ,
266
+ ".dropdown-wrapper__single-value" : {
267
+ color : COLORS [ "core-vibrant-blue-over" ] ,
268
+ } ,
269
+ ".dropdown-wrapper__indicator path" : {
270
+ stroke : COLORS [ "core-vibrant-blue-over" ] ,
271
+ } ,
206
272
} ,
207
- ".dropdown-wrapper__indicator path" : {
208
- stroke : COLORS [ "core-vibrant-blue-over" ] ,
273
+ // When tabbing
274
+ // Relies on --is-focused for styling as &:focus-visible cannot be applied
275
+ "&.react-select__control--is-focused" : {
276
+ ".dropdown-wrapper__single-value" : {
277
+ color : COLORS [ "core-vibrant-blue-over" ] ,
278
+ } ,
279
+ ".dropdown-wrapper__indicator path" : {
280
+ stroke : COLORS [ "core-vibrant-blue-over" ] ,
281
+ } ,
209
282
} ,
210
283
".filter-icon path" : {
211
284
fill : COLORS [ "core-vibrant-blue-over" ] ,
212
285
} ,
213
- } ,
214
- // When tabbing
215
- // Relies on --is-focused for styling as &:focus-visible cannot be applied
216
- "&.dropdown-wrapper__control--is-focused" : {
217
- ".dropdown-wrapper__single-value" : {
218
- color : COLORS [ "core-vibrant-blue-over" ] ,
219
- } ,
220
- ".dropdown-wrapper__indicator path" : {
221
- stroke : COLORS [ "core-vibrant-blue-over" ] ,
286
+ ...( state . isDisabled && {
287
+ ".dropdown-wrapper__single-value" : {
288
+ color : COLORS [ "ui-fleet-black-50" ] ,
289
+ } ,
290
+ ".dropdown-wrapper__indicator path" : {
291
+ stroke : COLORS [ "ui-fleet-black-50" ] ,
292
+ } ,
293
+ ".filter-icon path" : {
294
+ fill : COLORS [ "ui-fleet-black-50" ] ,
295
+ } ,
296
+ } ) ,
297
+ "&:active" : {
298
+ ".dropdown-wrapper__single-value" : {
299
+ color : COLORS [ "core-vibrant-blue-down" ] ,
300
+ } ,
301
+ ".dropdown-wrapper__indicator path" : {
302
+ stroke : COLORS [ "core-vibrant-blue-down" ] ,
303
+ } ,
304
+ ".filter-icon path" : {
305
+ fill : COLORS [ "core-vibrant-blue-down" ] ,
306
+ } ,
222
307
} ,
223
- ".filter-icon path" : {
224
- fill : COLORS [ "core-vibrant-blue-over" ] ,
225
- } ,
226
- } ,
227
- ...( state . isDisabled && {
228
- ".dropdown-wrapper__single-value" : {
229
- color : COLORS [ "ui-fleet-black-50" ] ,
230
- } ,
231
- ".dropdown-wrapper__indicator path" : {
232
- stroke : COLORS [ "ui-fleet-black-50" ] ,
233
- } ,
234
- ".filter-icon path" : {
235
- fill : COLORS [ "ui-fleet-black-50" ] ,
236
- } ,
237
- } ) ,
238
- "&:active" : {
239
- ".dropdown-wrapper__single-value" : {
240
- color : COLORS [ "core-vibrant-blue-down" ] ,
241
- } ,
242
- ".dropdown-wrapper__indicator path" : {
243
- stroke : COLORS [ "core-vibrant-blue-down" ] ,
244
- } ,
245
- ".filter-icon path" : {
246
- fill : COLORS [ "core-vibrant-blue-down" ] ,
247
- } ,
248
- } ,
249
- ...( state . menuIsOpen && {
250
- ".dropdown-wrapper__indicator svg" : {
251
- transform : "rotate(180deg)" ,
252
- transition : "transform 0.25s ease" ,
253
- } ,
254
- } ) ,
255
- } ) ,
308
+ ...( state . menuIsOpen && {
309
+ ".dropdown-wrapper__indicator svg" : {
310
+ transform : "rotate(180deg)" ,
311
+ transition : "transform 0.25s ease" ,
312
+ } ,
313
+ } ) ,
314
+ } ;
315
+ } ,
316
+ placeholder : ( provided , state ) => {
317
+ const buttonVariantPlaceholder = {
318
+ color : state . isFocused
319
+ ? COLORS [ "core-vibrant-blue-over" ]
320
+ : COLORS [ "core-fleet-blue" ] ,
321
+ fontSize : "14px" ,
322
+ fontWeight : "bold" ,
323
+ lineHeight : "normal" ,
324
+ paddingLeft : 0 ,
325
+ marginTop : variant === "button" ? "-1px" : "1px" , // TODO: Figure out vertical centering to not need pixel fix
326
+ } ;
327
+
328
+ return {
329
+ ...provided ,
330
+ ...( variant === "button" && buttonVariantPlaceholder ) ,
331
+ } ;
332
+ } ,
256
333
singleValue : ( provided ) => ( {
257
334
...provided ,
258
335
fontSize : "16px" ,
@@ -274,22 +351,28 @@ const DropdownWrapper = ({
274
351
zIndex : 6 ,
275
352
overflow : "hidden" ,
276
353
border : 0 ,
277
- marginTop : 0 ,
354
+ marginTop : variant === "button" ? "3px" : 0 ,
355
+ left : 0 ,
278
356
maxHeight : "none" ,
279
357
position : "absolute" ,
280
- left : "0" ,
281
358
animation : "fade-in 150ms ease-out" ,
359
+ ...( nowrapMenu && {
360
+ width : "fit-content" ,
361
+ left : "auto" ,
362
+ right : "0" ,
363
+ } ) ,
282
364
} ) ,
283
365
menuList : ( provided ) => ( {
284
366
...provided ,
285
367
padding : PADDING [ "pad-small" ] ,
286
368
maxHeight : "none" ,
369
+ ...( nowrapMenu && { width : "fit-content" } ) ,
287
370
} ) ,
288
371
valueContainer : ( provided ) => ( {
289
372
...provided ,
290
373
padding : 0 ,
291
374
display : "flex" ,
292
- gap : PADDING [ "pad-small" ] ,
375
+ gap : PADDING [ variant === "button" ? "pad-xsmall" : "pad-small" ] ,
293
376
} ) ,
294
377
option : ( provided , state ) => ( {
295
378
...provided ,
@@ -303,6 +386,7 @@ const DropdownWrapper = ({
303
386
backgroundColor : state . isDisabled
304
387
? "transparent"
305
388
: COLORS [ "ui-vibrant-blue-10" ] ,
389
+ cursor : state . isDisabled ? "not-allowed" : "pointer" ,
306
390
} ,
307
391
"&:active" : {
308
392
backgroundColor : state . isDisabled
@@ -320,11 +404,15 @@ const DropdownWrapper = ({
320
404
flexDirection : "column" ,
321
405
gap : "8px" ,
322
406
width : "100%" ,
407
+ whiteSpace : nowrapMenu ? "nowrap" : "normal" ,
323
408
} ,
324
409
".dropdown-wrapper__help-text" : {
325
410
fontSize : "12px" ,
326
- whiteSpace : "normal" ,
327
- color : COLORS [ "ui-fleet-black-75" ] ,
411
+ width : "100%" ,
412
+ whiteSpace : nowrapMenu ? "nowrap" : "normal" ,
413
+ color : state . isDisabled
414
+ ? COLORS [ "ui-fleet-black-50" ]
415
+ : COLORS [ "ui-fleet-black-75" ] ,
328
416
fontStyle : "italic" ,
329
417
fontWeight : "normal" ,
330
418
} ,
0 commit comments