|
17 | 17 | import { useMemo, useState } from 'react'
|
18 | 18 |
|
19 | 19 | import {
|
| 20 | + ActionMenu, |
| 21 | + ActionMenuItemType, |
20 | 22 | Button,
|
21 | 23 | ButtonStyleType,
|
22 | 24 | ButtonVariantType,
|
23 | 25 | ComponentSizeType,
|
24 | 26 | DynamicTabType,
|
25 |
| - PopupMenu, |
26 |
| - SelectPicker, |
27 |
| - SelectPickerOptionType, |
28 |
| - SelectPickerProps, |
| 27 | + Icon, |
29 | 28 | } from '@devtron-labs/devtron-fe-common-lib'
|
30 | 29 |
|
31 |
| -import { ReactComponent as ICArrowLeft } from '@Icons/ic-arrow-left.svg' |
32 |
| -import { ReactComponent as ICCross } from '@Icons/ic-cross.svg' |
33 |
| - |
34 | 30 | import { DynamicTabsSelectProps } from './types'
|
35 | 31 |
|
36 |
| -const DynamicTabsSelect = ({ |
37 |
| - tabs, |
38 |
| - getMarkTabActiveHandler, |
39 |
| - selectedTab, |
40 |
| - handleTabCloseAction, |
41 |
| -}: DynamicTabsSelectProps) => { |
| 32 | +const DynamicTabsSelect = ({ tabs, getMarkTabActiveHandler, handleTabCloseAction }: DynamicTabsSelectProps) => { |
42 | 33 | const [isMenuOpen, setIsMenuOpen] = useState(false)
|
43 | 34 |
|
44 |
| - const handleToggleOpenMenuState = (isOpen: boolean) => { |
45 |
| - setIsMenuOpen(isOpen) |
46 |
| - } |
47 |
| - |
48 |
| - const options: SelectPickerOptionType<DynamicTabType>[] = useMemo( |
| 35 | + const options = useMemo( |
49 | 36 | () =>
|
50 | 37 | tabs.map((tab) => {
|
51 | 38 | const [kind, name] = tab.title.split('/')
|
52 | 39 |
|
53 | 40 | return {
|
54 | 41 | label: kind,
|
| 42 | + id: tab.id, |
55 | 43 | value: tab,
|
56 | 44 | description: name,
|
57 |
| - endIcon: ( |
58 |
| - <div className="flex top"> |
59 |
| - <Button |
60 |
| - dataTestId="close-dynamic-tab-option" |
61 |
| - icon={<ICCross />} |
62 |
| - variant={ButtonVariantType.borderLess} |
63 |
| - style={ButtonStyleType.negativeGrey} |
64 |
| - data-id={tab.id} |
65 |
| - onClick={handleTabCloseAction} |
66 |
| - size={ComponentSizeType.xs} |
67 |
| - ariaLabel={`Close dynamic tab ${kind}`} |
68 |
| - showAriaLabelInTippy={false} |
69 |
| - /> |
70 |
| - </div> |
71 |
| - ), |
72 |
| - } |
| 45 | + trailingItem: { |
| 46 | + type: 'button', |
| 47 | + config: { |
| 48 | + dataTestId: 'close-dynamic-tab-option', |
| 49 | + icon: <Icon name="ic-close-small" color={null} />, |
| 50 | + variant: ButtonVariantType.borderLess, |
| 51 | + style: ButtonStyleType.negativeGrey, |
| 52 | + 'data-id': tab.id, |
| 53 | + onClick: handleTabCloseAction, |
| 54 | + size: ComponentSizeType.xs, |
| 55 | + ariaLabel: `Close dynamic tab ${kind}`, |
| 56 | + showAriaLabelInTippy: false, |
| 57 | + }, |
| 58 | + }, |
| 59 | + } as ActionMenuItemType & Record<'value', DynamicTabType> |
73 | 60 | }),
|
74 | 61 | [tabs],
|
75 | 62 | )
|
76 | 63 |
|
77 |
| - const onChangeTab = (option: SelectPickerOptionType<DynamicTabType>): void => { |
78 |
| - setIsMenuOpen(false) |
79 |
| - getMarkTabActiveHandler(option.value)() |
80 |
| - } |
81 |
| - |
82 |
| - const handleCloseMenu = () => { |
83 |
| - setIsMenuOpen(false) |
| 64 | + const onClick = (item: (typeof options)[number]) => { |
| 65 | + getMarkTabActiveHandler(item.value)() |
84 | 66 | }
|
85 | 67 |
|
86 |
| - // NOTE: by default react select compares option references |
87 |
| - // therefore if we don't wrap value and options in useMemo we need to provide isOptionSelected |
88 |
| - const isOptionSelected = (option: SelectPickerOptionType<DynamicTabType>) => option.value.id === selectedTab.id |
89 |
| - |
90 |
| - const handleOnEscPress = (e: React.KeyboardEvent) => { |
91 |
| - if (e.key !== 'Escape') { |
92 |
| - return |
93 |
| - } |
94 |
| - |
95 |
| - handleCloseMenu() |
96 |
| - } |
97 |
| - |
98 |
| - const selectFilter: SelectPickerProps<DynamicTabType>['filterOption'] = (option, searchText) => |
99 |
| - option.data.value.id.toLowerCase().includes(searchText.toLowerCase()) |
100 |
| - |
101 | 68 | return (
|
102 |
| - <PopupMenu autoClose autoPosition onToggleCallback={handleToggleOpenMenuState}> |
103 |
| - <PopupMenu.Button rootClassName="flex"> |
104 |
| - <ICArrowLeft |
105 |
| - className={`rotate icon-dim-18 ${isMenuOpen ? 'fcn-9' : 'fcn-7'}`} |
106 |
| - style={{ ['--rotateBy' as string]: isMenuOpen ? '90deg' : '-90deg' }} |
107 |
| - /> |
108 |
| - </PopupMenu.Button> |
109 |
| - {/* NOTE: Since we can't control open state of popup menu through prop we can control it by simply |
110 |
| - hooking a state using onToggleCallback and rendering the PopupMenu.Body conditionally through that state */} |
111 |
| - {isMenuOpen && ( |
112 |
| - <PopupMenu.Body rootClassName="w-300 mt-8 dynamic-tabs-select-popup-body" style={{ right: '12px' }}> |
113 |
| - <SelectPicker<DynamicTabType, false> |
114 |
| - inputId="dynamic-tabs-select" |
115 |
| - placeholder="Search tabs" |
116 |
| - options={options} |
117 |
| - onChange={onChangeTab} |
118 |
| - isOptionSelected={isOptionSelected} |
119 |
| - filterOption={selectFilter} |
120 |
| - onKeyDown={handleOnEscPress} |
121 |
| - shouldMenuAlignRight |
122 |
| - menuPosition="absolute" |
123 |
| - menuIsOpen |
124 |
| - autoFocus |
125 |
| - /> |
126 |
| - </PopupMenu.Body> |
127 |
| - )} |
128 |
| - </PopupMenu> |
| 69 | + <ActionMenu |
| 70 | + id="dynamic-tabs-select" |
| 71 | + onClick={onClick} |
| 72 | + position="bottom" |
| 73 | + isSearchable |
| 74 | + onOpen={setIsMenuOpen} |
| 75 | + options={[{ items: options }]} |
| 76 | + > |
| 77 | + <Button |
| 78 | + dataTestId="close-dynamic-tab-option" |
| 79 | + icon={<Icon name="ic-caret-down-small" color={null} rotateBy={isMenuOpen ? 180 : 0} />} |
| 80 | + variant={ButtonVariantType.secondary} |
| 81 | + style={ButtonStyleType.neutral} |
| 82 | + size={ComponentSizeType.xxs} |
| 83 | + ariaLabel="Open dynamic tabs select menu" |
| 84 | + showAriaLabelInTippy={false} |
| 85 | + /> |
| 86 | + </ActionMenu> |
129 | 87 | )
|
130 | 88 | }
|
131 | 89 |
|
|
0 commit comments