@spaced-out/ui-design-system 0.3.48 → 0.3.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/lib/components/AvatarGroup/AvatarGroup.js.flow +2 -2
  3. package/lib/components/ButtonDropdown/ButtonDropdown.js +22 -10
  4. package/lib/components/ButtonDropdown/ButtonDropdown.js.flow +58 -33
  5. package/lib/components/ButtonDropdown/ButtonDropdown.module.css +8 -1
  6. package/lib/components/ButtonDropdown/SimpleButtonDropdown.js +3 -0
  7. package/lib/components/ButtonDropdown/SimpleButtonDropdown.js.flow +6 -1
  8. package/lib/components/ButtonTabs/ButtonTabDropdown.js +13 -6
  9. package/lib/components/ButtonTabs/ButtonTabDropdown.js.flow +40 -24
  10. package/lib/components/ButtonTabs/ButtonTabDropdown.module.css +4 -0
  11. package/lib/components/ButtonTabs/ButtonTabs.js +2 -0
  12. package/lib/components/ButtonTabs/ButtonTabs.js.flow +4 -0
  13. package/lib/components/Card/Card.js +2 -1
  14. package/lib/components/Card/Card.js.flow +1 -0
  15. package/lib/components/Dropdown/Dropdown.js +23 -8
  16. package/lib/components/Dropdown/Dropdown.js.flow +57 -32
  17. package/lib/components/Dropdown/Dropdown.module.css +5 -0
  18. package/lib/components/Dropdown/SimpleDropdown.js +2 -0
  19. package/lib/components/Dropdown/SimpleDropdown.js.flow +4 -0
  20. package/lib/components/FilterButtonOverlay/FilterButtonOverlay.js +23 -8
  21. package/lib/components/FilterButtonOverlay/FilterButtonOverlay.js.flow +56 -26
  22. package/lib/components/InlineDropdown/InlineDropdown.js +25 -8
  23. package/lib/components/InlineDropdown/InlineDropdown.js.flow +57 -30
  24. package/lib/components/InlineDropdown/InlineDropdown.module.css +5 -0
  25. package/lib/components/InlineDropdown/SimpleInlineDropdown.js +2 -0
  26. package/lib/components/InlineDropdown/SimpleInlineDropdown.js.flow +4 -0
  27. package/lib/components/Modal/Modal.module.css +45 -13
  28. package/lib/components/Table/StaticTable.js +1 -1
  29. package/lib/components/Table/StaticTable.js.flow +1 -1
  30. package/lib/components/Table/Table.docs.js +1 -1
  31. package/lib/components/Table/Table.docs.js.flow +1 -1
  32. package/lib/components/Tabs/TabList/TabDropdown.js +14 -7
  33. package/lib/components/Tabs/TabList/TabDropdown.js.flow +38 -22
  34. package/lib/components/Tabs/TabList/TabDropdown.module.css +4 -0
  35. package/lib/components/Tabs/TabList/TabList.js +4 -2
  36. package/lib/components/Tabs/TabList/TabList.js.flow +4 -0
  37. package/lib/components/TokenListInput/TokenListInput.js +26 -7
  38. package/lib/components/TokenListInput/TokenListInput.js.flow +58 -32
  39. package/lib/components/TokenListInput/TokenListInput.module.css +5 -0
  40. package/lib/components/Tooltip/Tooltip.js +2 -1
  41. package/lib/components/Tooltip/Tooltip.js.flow +2 -2
  42. package/lib/components/Typeahead/SimpleTypeahead.js +3 -1
  43. package/lib/components/Typeahead/SimpleTypeahead.js.flow +4 -0
  44. package/lib/components/Typeahead/Typeahead.js +25 -8
  45. package/lib/components/Typeahead/Typeahead.js.flow +58 -30
  46. package/lib/components/Typeahead/Typeahead.module.css +5 -0
  47. package/lib/hooks/index.js +11 -0
  48. package/lib/hooks/index.js.flow +1 -0
  49. package/lib/hooks/useReferenceElementWidth/index.js +16 -0
  50. package/lib/hooks/useReferenceElementWidth/index.js.flow +3 -0
  51. package/lib/hooks/useReferenceElementWidth/useReferenceElementWidth.js +21 -0
  52. package/lib/hooks/useReferenceElementWidth/useReferenceElementWidth.js.flow +23 -0
  53. package/lib/utils/click-away/click-away.js +4 -0
  54. package/lib/utils/click-away/click-away.js.flow +34 -0
  55. package/package.json +1 -1
@@ -7,6 +7,10 @@ import {
7
7
  // $FlowFixMe[untyped-import]
8
8
  flip,
9
9
  // $FlowFixMe[untyped-import]
10
+ FloatingFocusManager,
11
+ // $FlowFixMe[untyped-import]
12
+ FloatingPortal,
13
+ // $FlowFixMe[untyped-import]
10
14
  offset,
11
15
  // $FlowFixMe[untyped-import]
12
16
  shift,
@@ -14,6 +18,7 @@ import {
14
18
  useFloating,
15
19
  } from '@floating-ui/react';
16
20
 
21
+ import {useReferenceElementWidth} from '../../hooks';
17
22
  import {spaceNone, spaceXXSmall} from '../../styles/variables/_space';
18
23
  import {classify} from '../../utils/classify';
19
24
  import {type ClickAwayRefType, ClickAway} from '../../utils/click-away';
@@ -24,6 +29,7 @@ import type {AnchorType} from '../ButtonDropdown';
24
29
  import {Icon} from '../Icon';
25
30
  import type {MenuOption, MenuProps} from '../Menu';
26
31
  import {Menu} from '../Menu';
32
+ import {type ElevationType, getElevationValue} from '../Tooltip';
27
33
  import {Truncate} from '../Truncate';
28
34
 
29
35
  import css from './InlineDropdown.module.css';
@@ -43,6 +49,7 @@ export type InlineDropdownProps = {
43
49
  onMenuOpen?: () => mixed,
44
50
  onMenuClose?: () => mixed,
45
51
  size?: 'medium' | 'small' | 'extraSmall',
52
+ elevation?: ElevationType,
46
53
  clickAwayRef?: ClickAwayRefType,
47
54
  ...
48
55
  };
@@ -63,13 +70,12 @@ export const InlineDropdown: React$AbstractComponent<
63
70
  onMenuClose,
64
71
  children,
65
72
  clickAwayRef,
73
+ elevation = 'modal',
66
74
  ...restButtonProps
67
75
  }: InlineDropdownProps,
68
76
  ref,
69
77
  ): React.Node => {
70
- const menuBtnRef = React.useRef(null);
71
- React.useImperativeHandle(ref, () => menuBtnRef.current);
72
- const {x, y, refs, strategy} = useFloating({
78
+ const {x, y, refs, strategy, context} = useFloating({
73
79
  open: true,
74
80
  strategy: 'absolute',
75
81
  placement: anchorPosition,
@@ -77,8 +83,10 @@ export const InlineDropdown: React$AbstractComponent<
77
83
  middleware: [shift(), flip(), offset(parseInt(spaceXXSmall))],
78
84
  });
79
85
 
86
+ const dropdownWidth = useReferenceElementWidth(refs.reference?.current);
87
+
80
88
  const onMenuToggle = (isOpen: boolean) => {
81
- isOpen ? onMenuOpen && onMenuOpen() : onMenuClose && onMenuClose();
89
+ isOpen ? onMenuOpen?.() : onMenuClose?.();
82
90
  };
83
91
 
84
92
  return (
@@ -90,7 +98,7 @@ export const InlineDropdown: React$AbstractComponent<
90
98
  css.inlineDropdownContainer,
91
99
  classNames?.dropdownContainer,
92
100
  )}
93
- ref={menuBtnRef}
101
+ ref={ref}
94
102
  >
95
103
  <UnstyledButton
96
104
  {...restButtonProps}
@@ -120,31 +128,50 @@ export const InlineDropdown: React$AbstractComponent<
120
128
  />
121
129
  </UnstyledButton>
122
130
  {isOpen && menu && (
123
- <div
124
- ref={mergeRefs([refs.setFloating, boundaryRef])}
125
- style={{
126
- display: 'flex',
127
- position: strategy,
128
- top: y ?? spaceNone,
129
- left: x ?? spaceNone,
130
- }}
131
- >
132
- <Menu
133
- {...menu}
134
- onSelect={(option, e) => {
135
- onOptionSelect && onOptionSelect(option, e);
136
- if (
137
- // option.keepMenuOpenOnOptionSelect - to allow the menu persist its open stat upon option selection in normal variant
138
- !option.keepMenuOpenOnOptionSelect &&
139
- (!menu.optionsVariant || menu.optionsVariant === 'normal')
140
- ) {
141
- clickAway();
142
- }
143
- }}
144
- size={menu.size || 'medium'}
145
- onTabOut={clickAway}
146
- />
147
- </div>
131
+ <FloatingPortal>
132
+ <FloatingFocusManager
133
+ modal={false}
134
+ context={context}
135
+ initialFocus={triggerRef}
136
+ >
137
+ <div
138
+ className={css.menuWrapper}
139
+ ref={mergeRefs([refs.setFloating, boundaryRef])}
140
+ style={{
141
+ display: 'flex',
142
+ position: strategy,
143
+ top: y ?? spaceNone,
144
+ left: x ?? spaceNone,
145
+ /* NOTE(Sharad): The FloatingPortal renders the menu outside the normal DOM structure,
146
+ so its parent is effectively the <body> element. This means the menu
147
+ would otherwise default to the body's width. To support fluid width,
148
+ we must manually set the dropdown width here; otherwise, it uses a fixed width.
149
+ Also, Only treat menu as non-fluid if isFluid is strictly false, since default is true in menu and undefined means fluid. */ ...(menu.isFluid !==
150
+ false && {
151
+ '--dropdown-width': dropdownWidth,
152
+ }),
153
+ '--menu-elevation': getElevationValue(elevation),
154
+ }}
155
+ >
156
+ <Menu
157
+ {...menu}
158
+ onSelect={(option, e) => {
159
+ onOptionSelect && onOptionSelect(option, e);
160
+ if (
161
+ // option.keepMenuOpenOnOptionSelect - to allow the menu persist its open stat upon option selection in normal variant
162
+ !option.keepMenuOpenOnOptionSelect &&
163
+ (!menu.optionsVariant ||
164
+ menu.optionsVariant === 'normal')
165
+ ) {
166
+ clickAway();
167
+ }
168
+ }}
169
+ size={menu.size || 'medium'}
170
+ onTabOut={clickAway}
171
+ />
172
+ </div>
173
+ </FloatingFocusManager>
174
+ </FloatingPortal>
148
175
  )}
149
176
  </div>
150
177
  )}
@@ -42,3 +42,8 @@
42
42
  color: colorTextDisabled;
43
43
  cursor: not-allowed;
44
44
  }
45
+
46
+ .menuWrapper {
47
+ width: var(--dropdown-width);
48
+ z-index: var(--menu-elevation);
49
+ }
@@ -32,6 +32,7 @@ const SimpleInlineDropdownBase = (props, ref) => {
32
32
  showLabelTooltip,
33
33
  clickAwayRef,
34
34
  allowWrap = false,
35
+ elevation = 'modal',
35
36
  ...buttonProps
36
37
  } = props;
37
38
  const [btnText, setBtnText] = React.useState('');
@@ -67,6 +68,7 @@ const SimpleInlineDropdownBase = (props, ref) => {
67
68
  onMenuOpen: onMenuOpen,
68
69
  onMenuClose: onMenuClose,
69
70
  clickAwayRef: clickAwayRef,
71
+ elevation: elevation,
70
72
  menu: {
71
73
  isFluid,
72
74
  options,
@@ -11,6 +11,7 @@ import {
11
11
  import type {ButtonProps} from '../Button';
12
12
  import type {AnchorType} from '../ButtonDropdown';
13
13
  import type {MenuOption, MenuOptionsVariant, Virtualization} from '../Menu';
14
+ import type {ElevationType} from '../Tooltip';
14
15
 
15
16
  import {InlineDropdown} from './InlineDropdown';
16
17
 
@@ -28,6 +29,7 @@ export type SimpleInlineDropdownProps = {
28
29
  // Input props
29
30
  ...ButtonProps,
30
31
 
32
+ elevation?: ElevationType,
31
33
  classNames?: ClassNames,
32
34
  anchorPosition?: AnchorType,
33
35
 
@@ -79,6 +81,7 @@ const SimpleInlineDropdownBase = (props: SimpleInlineDropdownProps, ref) => {
79
81
  showLabelTooltip,
80
82
  clickAwayRef,
81
83
  allowWrap = false,
84
+ elevation = 'modal',
82
85
  ...buttonProps
83
86
  } = props;
84
87
 
@@ -133,6 +136,7 @@ const SimpleInlineDropdownBase = (props: SimpleInlineDropdownProps, ref) => {
133
136
  onMenuOpen={onMenuOpen}
134
137
  onMenuClose={onMenuClose}
135
138
  clickAwayRef={clickAwayRef}
139
+ elevation={elevation}
136
140
  menu={{
137
141
  isFluid,
138
142
  options,
@@ -1,10 +1,41 @@
1
- @value (colorBackgroundTertiary, colorBackgroundPrimary, colorBackdropFill) from '../../styles/variables/_color.css';
2
- @value (spaceNone, spaceSmall, spaceMedium, spaceXXSmall, spaceHalfFluid, spaceNegHalfFluid) from '../../styles/variables/_space.css';
3
- @value (sizeFluid, size60, size320, size480, size640) from '../../styles/variables/_size.css';
4
- @value (elevationNone, elevationModal, elevationBackdrop) from '../../styles/variables/_elevation.css';
5
- @value (opacity100, opacity0) from '../../styles/variables/_opacity.css';
6
- @value (motionDurationNormal, motionEaseInEaseOut) from '../../styles/variables/_motion.css';
7
- @value (borderRadiusMedium) from '../../styles/variables/_border.css';
1
+ @value (
2
+ colorBackgroundTertiary,
3
+ colorBackgroundPrimary,
4
+ colorBackdropFill
5
+ ) from '../../styles/variables/_color.css';
6
+ @value (
7
+ spaceNone,
8
+ spaceSmall,
9
+ spaceXSmall,
10
+ spaceMedium,
11
+ spaceXXSmall,
12
+ spaceHalfFluid,
13
+ spaceNegHalfFluid
14
+ ) from '../../styles/variables/_space.css';
15
+ @value (
16
+ sizeFluid,
17
+ size58,
18
+ size60,
19
+ size66,
20
+ size320,
21
+ size480,
22
+ size640
23
+ ) from '../../styles/variables/_size.css';
24
+ @value (
25
+ elevationNone,
26
+ elevationModal,
27
+ elevationBackdrop
28
+ ) from '../../styles/variables/_elevation.css';
29
+ @value (
30
+ opacity100,
31
+ opacity0
32
+ ) from '../../styles/variables/_opacity.css';
33
+ @value (
34
+ motionDurationNormal
35
+ ) from '../../styles/variables/_motion.css';
36
+ @value (
37
+ borderRadiusMedium
38
+ ) from '../../styles/variables/_border.css';
8
39
 
9
40
  .modalContainer {
10
41
  display: flex;
@@ -83,12 +114,12 @@
83
114
  .modalHeader {
84
115
  composes: borderBottomPrimary from '../../styles/border.module.css';
85
116
  composes: subTitleLarge from '../../styles/typography.module.css';
86
- padding: spaceNone spaceSmall spaceNone spaceMedium;
87
- min-height: size60;
117
+ padding: spaceSmall spaceSmall spaceSmall spaceMedium;
118
+ min-height: size58;
88
119
  display: flex;
89
120
  justify-content: space-between;
90
121
  align-items: center;
91
- gap: spaceMedium;
122
+ gap: spaceXSmall;
92
123
  }
93
124
 
94
125
  .headerContent {
@@ -103,16 +134,17 @@
103
134
 
104
135
  .modalFooter {
105
136
  composes: borderTopPrimary from '../../styles/border.module.css';
137
+ min-height: size66;
106
138
  background-color: colorBackgroundPrimary;
107
139
  margin-top: auto;
108
- padding: spaceMedium;
140
+ padding: spaceSmall spaceMedium;
109
141
  display: flex;
110
142
  justify-content: flex-end;
111
143
  align-items: center;
112
- gap: spaceMedium;
144
+ gap: spaceXSmall;
113
145
  }
114
146
 
115
147
  .modalFooterActions {
116
148
  display: flex;
117
- gap: spaceSmall;
149
+ gap: spaceXSmall;
118
150
  }
@@ -74,7 +74,7 @@ function StaticTable(props) {
74
74
  }, [width]);
75
75
 
76
76
  /**
77
- * this function is also used to decide weather to show checkbox in header or not. so it's value is undefined incase selectedKeys is not there.
77
+ * this function is also used to decide weather to show checkbox in header or not. so it's value is undefined in case selectedKeys is not there.
78
78
  */
79
79
 
80
80
  const handleHeaderCheckboxClick = selectedKeys ? ({
@@ -89,7 +89,7 @@ export function StaticTable<Data: GenericObject, Extras: GenericObject>(props: {
89
89
  }, [width]);
90
90
 
91
91
  /**
92
- * this function is also used to decide weather to show checkbox in header or not. so it's value is undefined incase selectedKeys is not there.
92
+ * this function is also used to decide weather to show checkbox in header or not. so it's value is undefined in case selectedKeys is not there.
93
93
  */
94
94
 
95
95
  const handleHeaderCheckboxClick = selectedKeys
@@ -104,7 +104,7 @@ const TABLE_DOCS = exports.TABLE_DOCS = {
104
104
  }
105
105
  },
106
106
  selectedKeys: {
107
- description: 'array of keys which are selected. This prop is also used to decide weather to show checkboxes or not. So, pass an empty array incase no row is selected.',
107
+ description: 'array of keys which are selected. This prop is also used to decide weather to show checkboxes or not. So, pass an empty array in case no row is selected.',
108
108
  control: {
109
109
  type: 'object'
110
110
  },
@@ -89,7 +89,7 @@ export const TABLE_DOCS = {
89
89
  },
90
90
  selectedKeys: {
91
91
  description:
92
- 'array of keys which are selected. This prop is also used to decide weather to show checkboxes or not. So, pass an empty array incase no row is selected.',
92
+ 'array of keys which are selected. This prop is also used to decide weather to show checkboxes or not. So, pass an empty array in case no row is selected.',
93
93
  control: {
94
94
  type: 'object',
95
95
  },
@@ -11,6 +11,7 @@ var _classify = require("../../../utils/classify");
11
11
  var _clickAway = require("../../../utils/click-away");
12
12
  var _mergeRefs = require("../../../utils/merge-refs");
13
13
  var _Menu = require("../../Menu");
14
+ var _Tooltip = require("../../Tooltip");
14
15
  var _Tab = require("../Tab");
15
16
  var _TabDropdownModule = _interopRequireDefault(require("./TabDropdown.module.css"));
16
17
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -22,14 +23,15 @@ const TabDropdown = _ref => {
22
23
  size,
23
24
  onOptionSelect,
24
25
  props,
26
+ elevation = 'modal',
25
27
  classNames
26
28
  } = _ref;
27
- const menuBtnRef = React.useRef();
28
29
  const {
29
30
  x,
30
31
  y,
31
32
  refs,
32
- strategy
33
+ strategy,
34
+ context
33
35
  } = (0, _react2.useFloating)({
34
36
  open: true,
35
37
  strategy: 'absolute',
@@ -47,8 +49,7 @@ const TabDropdown = _ref => {
47
49
  } = _ref2;
48
50
  return /*#__PURE__*/React.createElement("div", {
49
51
  "data-testid": "TabDropdown",
50
- className: (0, _classify.classify)(_TabDropdownModule.default.tabDropdownContainer, classNames?.wrapper),
51
- ref: menuBtnRef
52
+ className: (0, _classify.classify)(_TabDropdownModule.default.tabDropdownContainer, classNames?.wrapper)
52
53
  }, /*#__PURE__*/React.createElement(_Tab.Tab, _extends({}, props?.tab, {
53
54
  size: size,
54
55
  ref: (0, _mergeRefs.mergeRefs)([refs.setReference, triggerRef]),
@@ -60,13 +61,19 @@ const TabDropdown = _ref => {
60
61
  wrapper: _TabDropdownModule.default.dotTabWrapper,
61
62
  iconTextWrap: _TabDropdownModule.default.dotTextWrap
62
63
  }
63
- })), isOpen && props?.menu && /*#__PURE__*/React.createElement("div", {
64
+ })), isOpen && props?.menu && /*#__PURE__*/React.createElement(_react2.FloatingPortal, null, /*#__PURE__*/React.createElement(_react2.FloatingFocusManager, {
65
+ modal: false,
66
+ context: context,
67
+ initialFocus: refs.reference
68
+ }, /*#__PURE__*/React.createElement("div", {
64
69
  ref: (0, _mergeRefs.mergeRefs)([refs.setFloating, boundaryRef]),
70
+ className: _TabDropdownModule.default.menuWrapper,
65
71
  style: {
66
72
  display: 'flex',
67
73
  position: strategy,
68
74
  top: y ?? _space.spaceNone,
69
- left: x ?? _space.spaceNone
75
+ left: x ?? _space.spaceNone,
76
+ '--menu-elevation': (0, _Tooltip.getElevationValue)(elevation)
70
77
  }
71
78
  }, /*#__PURE__*/React.createElement(_Menu.Menu, _extends({}, props.menu, {
72
79
  onSelect: (option, e) => {
@@ -75,7 +82,7 @@ const TabDropdown = _ref => {
75
82
  },
76
83
  size: props.menu.size || size,
77
84
  onTabOut: clickAway
78
- }))));
85
+ }))))));
79
86
  });
80
87
  };
81
88
  exports.TabDropdown = TabDropdown;
@@ -7,6 +7,10 @@ import {
7
7
  // $FlowFixMe[untyped-import]
8
8
  flip,
9
9
  // $FlowFixMe[untyped-import]
10
+ FloatingFocusManager,
11
+ // $FlowFixMe[untyped-import]
12
+ FloatingPortal,
13
+ // $FlowFixMe[untyped-import]
10
14
  offset,
11
15
  // $FlowFixMe[untyped-import]
12
16
  shift,
@@ -21,6 +25,8 @@ import {mergeRefs} from '../../../utils/merge-refs';
21
25
  import type {AnchorType} from '../../ButtonDropdown';
22
26
  import type {MenuOption, MenuProps} from '../../Menu';
23
27
  import {Menu} from '../../Menu';
28
+ import type {ElevationType} from '../../Tooltip';
29
+ import {getElevationValue} from '../../Tooltip';
24
30
  import type {TabProps} from '../Tab';
25
31
  import {Tab} from '../Tab';
26
32
 
@@ -40,6 +46,7 @@ export type TabDropdownProps = {
40
46
  classNames?: ClassNames,
41
47
  selected?: boolean,
42
48
  disabled?: boolean,
49
+ elevation?: ElevationType,
43
50
  };
44
51
 
45
52
  export const TabDropdown = ({
@@ -47,10 +54,10 @@ export const TabDropdown = ({
47
54
  size,
48
55
  onOptionSelect,
49
56
  props,
57
+ elevation = 'modal',
50
58
  classNames,
51
59
  }: TabDropdownProps): React.Node => {
52
- const menuBtnRef = React.useRef();
53
- const {x, y, refs, strategy} = useFloating({
60
+ const {x, y, refs, strategy, context} = useFloating({
54
61
  open: true,
55
62
  strategy: 'absolute',
56
63
  placement: anchorPosition,
@@ -64,7 +71,6 @@ export const TabDropdown = ({
64
71
  <div
65
72
  data-testid="TabDropdown"
66
73
  className={classify(css.tabDropdownContainer, classNames?.wrapper)}
67
- ref={menuBtnRef}
68
74
  >
69
75
  <Tab
70
76
  {...props?.tab}
@@ -80,25 +86,35 @@ export const TabDropdown = ({
80
86
  }}
81
87
  />
82
88
  {isOpen && props?.menu && (
83
- <div
84
- ref={mergeRefs([refs.setFloating, boundaryRef])}
85
- style={{
86
- display: 'flex',
87
- position: strategy,
88
- top: y ?? spaceNone,
89
- left: x ?? spaceNone,
90
- }}
91
- >
92
- <Menu
93
- {...props.menu}
94
- onSelect={(option, e) => {
95
- onOptionSelect && onOptionSelect(option, e);
96
- clickAway();
97
- }}
98
- size={props.menu.size || size}
99
- onTabOut={clickAway}
100
- />
101
- </div>
89
+ <FloatingPortal>
90
+ <FloatingFocusManager
91
+ modal={false}
92
+ context={context}
93
+ initialFocus={refs.reference}
94
+ >
95
+ <div
96
+ ref={mergeRefs([refs.setFloating, boundaryRef])}
97
+ className={css.menuWrapper}
98
+ style={{
99
+ display: 'flex',
100
+ position: strategy,
101
+ top: y ?? spaceNone,
102
+ left: x ?? spaceNone,
103
+ '--menu-elevation': getElevationValue(elevation),
104
+ }}
105
+ >
106
+ <Menu
107
+ {...props.menu}
108
+ onSelect={(option, e) => {
109
+ onOptionSelect && onOptionSelect(option, e);
110
+ clickAway();
111
+ }}
112
+ size={props.menu.size || size}
113
+ onTabOut={clickAway}
114
+ />
115
+ </div>
116
+ </FloatingFocusManager>
117
+ </FloatingPortal>
102
118
  )}
103
119
  </div>
104
120
  )}
@@ -20,3 +20,7 @@
20
20
  .dotTextWrap {
21
21
  width: spaceFluid;
22
22
  }
23
+
24
+ .menuWrapper {
25
+ z-index: var(--menu-elevation);
26
+ }
@@ -20,7 +20,8 @@ const TabList = exports.TabList = /*#__PURE__*/React.forwardRef((_ref, forwardRe
20
20
  size,
21
21
  onSelect,
22
22
  selectedTab,
23
- menuWidth
23
+ menuWidth,
24
+ elevation = 'modal'
24
25
  } = _ref;
25
26
  const ref = React.useRef(null);
26
27
  React.useImperativeHandle(forwardRef, () => ref.current);
@@ -104,7 +105,8 @@ const TabList = exports.TabList = /*#__PURE__*/React.forwardRef((_ref, forwardRe
104
105
  selectedKeys,
105
106
  width: menuWidth
106
107
  }
107
- }
108
+ },
109
+ elevation: elevation
108
110
  }) : null;
109
111
  nodes = [...tabListNodes, tabDropDownNode];
110
112
  return nodes;
@@ -6,6 +6,7 @@ import {useWindowSize} from '../../../hooks/useWindowSize/useWindowSize';
6
6
  import {size36, size100} from '../../../styles/variables/_size';
7
7
  import {spaceMedium} from '../../../styles/variables/_space';
8
8
  import {classify} from '../../../utils/classify';
9
+ import type {ElevationType} from '../../Tooltip';
9
10
 
10
11
  import {TabDropdown} from './TabDropdown';
11
12
 
@@ -21,6 +22,7 @@ export type TabListProps = {
21
22
  size?: 'medium',
22
23
  selectedTab?: {tabId: string, label?: string},
23
24
  menuWidth?: string,
25
+ elevation?: ElevationType,
24
26
  };
25
27
 
26
28
  export const TabList: React$AbstractComponent<TabListProps, HTMLDivElement> =
@@ -33,6 +35,7 @@ export const TabList: React$AbstractComponent<TabListProps, HTMLDivElement> =
33
35
  onSelect,
34
36
  selectedTab,
35
37
  menuWidth,
38
+ elevation = 'modal',
36
39
  }: TabListProps,
37
40
  forwardRef,
38
41
  ): React.Node => {
@@ -120,6 +123,7 @@ export const TabList: React$AbstractComponent<TabListProps, HTMLDivElement> =
120
123
  width: menuWidth,
121
124
  },
122
125
  }}
126
+ elevation={elevation}
123
127
  />
124
128
  ) : null;
125
129
 
@@ -8,7 +8,7 @@ exports.TokenListInput = TokenListInput;
8
8
  var React = _interopRequireWildcard(require("react"));
9
9
  var _react2 = require("@floating-ui/react");
10
10
  var _without = _interopRequireDefault(require("lodash/without"));
11
- var _size = require("../../styles/variables/_size");
11
+ var _hooks = require("../../hooks");
12
12
  var _space = require("../../styles/variables/_space");
13
13
  var _typography = require("../../types/typography");
14
14
  var _classify = _interopRequireDefault(require("../../utils/classify"));
@@ -20,6 +20,7 @@ var _CircularLoader = require("../CircularLoader");
20
20
  var _Icon = require("../Icon");
21
21
  var _Menu = require("../Menu");
22
22
  var _Text = require("../Text");
23
+ var _Tooltip = require("../Tooltip");
23
24
  var _TokenValueChips = require("./TokenValueChips");
24
25
  var _TokenListInputModule = _interopRequireDefault(require("./TokenListInput.module.css"));
25
26
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -55,14 +56,16 @@ function TokenListInput(props) {
55
56
  tabIndex,
56
57
  values,
57
58
  resolveTokenValue,
58
- inputProps
59
+ inputProps,
60
+ elevation = 'modal'
59
61
  } = props;
60
62
  const menuRef = React.useRef(null);
61
63
  const {
62
64
  x,
63
65
  y,
64
66
  refs,
65
- strategy
67
+ strategy,
68
+ context
66
69
  } = (0, _react2.useFloating)({
67
70
  open: true,
68
71
  strategy: _ButtonDropdown.STRATEGY_TYPE.absolute,
@@ -71,6 +74,7 @@ function TokenListInput(props) {
71
74
  middleware: [(0, _react2.flip)(), (0, _react2.offset)(parseInt(_space.spaceXXSmall))]
72
75
  });
73
76
  const inputRef = React.useRef();
77
+ const dropdownWidth = (0, _hooks.useReferenceElementWidth)(refs.reference?.current);
74
78
  const onOpenToggle = isOpen => {
75
79
  if (isOpen) {
76
80
  onMenuOpen?.();
@@ -152,8 +156,9 @@ function TokenListInput(props) {
152
156
  triggerRef
153
157
  } = _ref;
154
158
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
159
+ ref: menuRef,
155
160
  className: (0, _classify.default)(_TokenListInputModule.default.tokenListContainer, classNames?.wrapper),
156
- ref: menuRef
161
+ "data-testid": "TokenListInput"
157
162
  }, /*#__PURE__*/React.createElement("div", {
158
163
  onClick: () => {
159
164
  if (disabled || locked || values.length >= limit) {
@@ -224,13 +229,27 @@ function TokenListInput(props) {
224
229
  color: _typography.TEXT_COLORS.danger
225
230
  }, errorText) : typeof helperText === 'string' ? /*#__PURE__*/React.createElement(_Text.BodySmall, {
226
231
  color: _typography.TEXT_COLORS.secondary
227
- }, helperText) : helperText), !locked && isOpen && menu && /*#__PURE__*/React.createElement("div", {
232
+ }, helperText) : helperText), !locked && isOpen && menu && /*#__PURE__*/React.createElement(_react2.FloatingPortal, null, /*#__PURE__*/React.createElement(_react2.FloatingFocusManager, {
233
+ modal: false,
234
+ context: context,
235
+ returnFocus: false,
236
+ initialFocus: refs.reference
237
+ }, /*#__PURE__*/React.createElement("div", {
238
+ className: _TokenListInputModule.default.menuWrapper,
228
239
  ref: (0, _mergeRefs.mergeRefs)([refs.setFloating, boundaryRef]),
229
240
  style: {
230
241
  position: strategy,
231
242
  top: y ?? _space.spaceNone,
232
243
  left: x ?? _space.spaceNone,
233
- width: _size.sizeFluid
244
+ /* NOTE(Sharad): The FloatingPortal renders the menu outside the normal DOM structure,
245
+ so its parent is effectively the <body> element. This means the menu
246
+ would otherwise default to the body's width. To support fluid width,
247
+ we must manually set the dropdown width here; otherwise, it uses a fixed width.
248
+ Also, Only treat menu as non-fluid if isFluid is strictly false, since default is true in menu and undefined means fluid. */
249
+ ...(menu.isFluid !== false && {
250
+ '--dropdown-width': dropdownWidth
251
+ }),
252
+ '--menu-elevation': (0, _Tooltip.getElevationValue)(elevation)
234
253
  }
235
254
  }, /*#__PURE__*/React.createElement(_Menu.Menu, _extends({}, menu, {
236
255
  onSelect: option => {
@@ -246,7 +265,7 @@ function TokenListInput(props) {
246
265
  size: menu.size || size,
247
266
  onTabOut: clickAway,
248
267
  ref: menuRef
249
- })))));
268
+ })))))));
250
269
  });
251
270
  }
252
271
  TokenListInput.displayName = 'TokenListInput';