@spaced-out/ui-design-system 0.1.94-beta.7 → 0.1.94-beta.8

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 (37) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/lib/components/ButtonDropdown/ButtonDropdown.js +3 -1
  3. package/lib/components/ButtonDropdown/ButtonDropdown.js.flow +4 -2
  4. package/lib/components/ButtonDropdown/SimpleButtonDropdown.js +9 -1
  5. package/lib/components/ButtonDropdown/SimpleButtonDropdown.js.flow +14 -2
  6. package/lib/components/Dropdown/Dropdown.js +3 -1
  7. package/lib/components/Dropdown/Dropdown.js.flow +4 -2
  8. package/lib/components/Dropdown/SimpleDropdown.js +7 -1
  9. package/lib/components/Dropdown/SimpleDropdown.js.flow +10 -1
  10. package/lib/components/InlineDropdown/InlineDropdown.js +3 -1
  11. package/lib/components/InlineDropdown/InlineDropdown.js.flow +4 -2
  12. package/lib/components/InlineDropdown/SimpleInlineDropdown.js +9 -1
  13. package/lib/components/InlineDropdown/SimpleInlineDropdown.js.flow +14 -1
  14. package/lib/components/Menu/Menu.js +20 -4
  15. package/lib/components/Menu/Menu.js.flow +24 -0
  16. package/lib/components/Menu/Menu.module.css +70 -4
  17. package/lib/components/OptionButton/OptionButton.js +4 -2
  18. package/lib/components/OptionButton/OptionButton.js.flow +4 -0
  19. package/lib/components/OptionButton/SimpleOptionButton.js +9 -1
  20. package/lib/components/OptionButton/SimpleOptionButton.js.flow +14 -2
  21. package/lib/components/PageTitle/PageTitle.js +15 -3
  22. package/lib/components/PageTitle/PageTitle.js.flow +33 -14
  23. package/lib/components/PageTitle/PageTitle.module.css +9 -3
  24. package/lib/components/SideMenuLink/SideMenuLink.js +4 -3
  25. package/lib/components/SideMenuLink/SideMenuLink.js.flow +3 -2
  26. package/lib/components/Typeahead/SimpleTypeahead.js +10 -2
  27. package/lib/components/Typeahead/SimpleTypeahead.js.flow +14 -1
  28. package/lib/components/Typeahead/Typeahead.js +3 -1
  29. package/lib/components/Typeahead/Typeahead.js.flow +4 -2
  30. package/lib/types/charts.js.flow +30 -0
  31. package/lib/utils/charts/charts.js +17 -4
  32. package/lib/utils/charts/charts.js.flow +17 -3
  33. package/lib/utils/charts/columnChart.js +1 -0
  34. package/lib/utils/charts/columnChart.js.flow +1 -0
  35. package/lib/utils/click-away/click-away.js +9 -0
  36. package/lib/utils/click-away/click-away.js.flow +16 -0
  37. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [0.1.94-beta.8](https://github.com/spaced-out/ui-design-system/compare/v0.1.94-beta.7...v0.1.94-beta.8) (2024-05-22)
6
+
7
+
8
+ ### Features
9
+
10
+ * added header and footer in menu component ([#210](https://github.com/spaced-out/ui-design-system/issues/210)) ([3d52788](https://github.com/spaced-out/ui-design-system/commit/3d52788a4aea929b4db7cb53b956c046ea1b7d79))
11
+ * adding back button in page title ([#213](https://github.com/spaced-out/ui-design-system/issues/213)) ([920e90e](https://github.com/spaced-out/ui-design-system/commit/920e90ed20c2df97c8fcc699294710853613ee29))
12
+ * button disabled and name changes ([#216](https://github.com/spaced-out/ui-design-system/issues/216)) ([7b26959](https://github.com/spaced-out/ui-design-system/commit/7b26959ad27439ad91de9307108ac834a276c566))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * removed the additional default space from the chart ([#215](https://github.com/spaced-out/ui-design-system/issues/215)) ([36e49c9](https://github.com/spaced-out/ui-design-system/commit/36e49c9bfd609e2a08a08c8fe533ec8779b5cf10))
18
+
5
19
  ### [0.1.94-beta.7](https://github.com/spaced-out/ui-design-system/compare/v0.1.94-beta.6...v0.1.94-beta.7) (2024-05-20)
6
20
 
7
21
 
@@ -50,6 +50,7 @@ const ButtonDropdown = /*#__PURE__*/React.forwardRef((_ref, forwardRef) => {
50
50
  isFluid,
51
51
  tooltip,
52
52
  onClick,
53
+ clickAwayRef,
53
54
  ...restButtonProps
54
55
  } = _ref;
55
56
  const menuBtnRef = React.useRef(null);
@@ -77,7 +78,8 @@ const ButtonDropdown = /*#__PURE__*/React.forwardRef((_ref, forwardRef) => {
77
78
  }
78
79
  };
79
80
  return /*#__PURE__*/React.createElement(_clickAway.ClickAway, {
80
- onChange: onMenuToggle
81
+ onChange: onMenuToggle,
82
+ clickAwayRef: clickAwayRef
81
83
  }, _ref2 => {
82
84
  let {
83
85
  isOpen,
@@ -17,7 +17,7 @@ import {
17
17
  import {sizeFluid} from '../../styles/variables/_size';
18
18
  import {spaceNone, spaceXXSmall} from '../../styles/variables/_space';
19
19
  import {classify} from '../../utils/classify';
20
- import {ClickAway} from '../../utils/click-away';
20
+ import {type ClickAwayRefType, ClickAway} from '../../utils/click-away';
21
21
  import type {ButtonProps} from '../Button';
22
22
  import {Button} from '../Button';
23
23
  import {ConditionalWrapper} from '../ConditionalWrapper';
@@ -62,6 +62,7 @@ export type ButtonDropdownProps = {
62
62
  onMenuOpen?: () => mixed,
63
63
  onMenuClose?: () => mixed,
64
64
  tooltip?: BaseTooltipProps,
65
+ clickAwayRef?: ClickAwayRefType,
65
66
  ...
66
67
  };
67
68
 
@@ -86,6 +87,7 @@ export const ButtonDropdown: React$AbstractComponent<
86
87
  isFluid,
87
88
  tooltip,
88
89
  onClick,
90
+ clickAwayRef,
89
91
  ...restButtonProps
90
92
  }: ButtonDropdownProps,
91
93
  forwardRef,
@@ -112,7 +114,7 @@ export const ButtonDropdown: React$AbstractComponent<
112
114
  };
113
115
 
114
116
  return (
115
- <ClickAway onChange={onMenuToggle}>
117
+ <ClickAway onChange={onMenuToggle} clickAwayRef={clickAwayRef}>
116
118
  {({isOpen, onOpen, cancelNext, clickAway}) => (
117
119
  <div
118
120
  data-testid="ButtonDropdown"
@@ -26,6 +26,10 @@ const SimpleButtonDropdownBase = (props, ref) => {
26
26
  resolveSecondaryLabel,
27
27
  children,
28
28
  isFluid,
29
+ menuVirtualization,
30
+ header,
31
+ footer,
32
+ clickAwayRef,
29
33
  ...buttonProps
30
34
  } = props;
31
35
  const [btnText, setBtnText] = React.useState('');
@@ -60,6 +64,7 @@ const SimpleButtonDropdownBase = (props, ref) => {
60
64
  onOptionSelect: handleOptionChange,
61
65
  onMenuOpen: onMenuOpen,
62
66
  onMenuClose: onMenuClose,
67
+ clickAwayRef: clickAwayRef,
63
68
  menu: {
64
69
  isFluid,
65
70
  options,
@@ -68,7 +73,10 @@ const SimpleButtonDropdownBase = (props, ref) => {
68
73
  allowSearch,
69
74
  resolveLabel,
70
75
  resolveSecondaryLabel,
71
- size
76
+ size,
77
+ virtualization: menuVirtualization,
78
+ header,
79
+ footer
72
80
  }
73
81
  }), optionsVariant === 'checkbox' ? btnText : children);
74
82
  };
@@ -2,12 +2,13 @@
2
2
 
3
3
  import * as React from 'react';
4
4
 
5
+ import type {ClickAwayRefType} from '../../utils/click-away';
5
6
  import {
6
7
  getButtonLabelFromSelectedKeys,
7
8
  getSelectedKeysFromSelectedOption,
8
9
  } from '../../utils/menu';
9
10
  import type {ButtonProps} from '../Button';
10
- import type {MenuOption, MenuOptionsVariant} from '../Menu';
11
+ import type {MenuOption, MenuOptionsVariant, Virtualization} from '../Menu';
11
12
  import type {BaseTooltipProps} from '../Tooltip';
12
13
 
13
14
  import type {AnchorType} from './ButtonDropdown';
@@ -34,10 +35,12 @@ export type SimpleButtonDropdownProps = {
34
35
 
35
36
  // Menu props
36
37
  options?: Array<MenuOption>,
37
-
38
38
  optionsVariant?: MenuOptionsVariant,
39
39
  allowSearch?: boolean,
40
40
  selectedKeys?: Array<string>,
41
+ menuVirtualization?: Virtualization,
42
+ header?: React.Node,
43
+ footer?: React.Node,
41
44
 
42
45
  // events
43
46
  onOptionSelect?: (option: MenuOption, ?SyntheticEvent<HTMLElement>) => mixed,
@@ -47,6 +50,7 @@ export type SimpleButtonDropdownProps = {
47
50
  // Resolvers
48
51
  resolveLabel?: (option: MenuOption) => string | React.Node,
49
52
  resolveSecondaryLabel?: (option: MenuOption) => string | React.Node,
53
+ clickAwayRef?: ClickAwayRefType,
50
54
  ...
51
55
  };
52
56
 
@@ -66,6 +70,10 @@ const SimpleButtonDropdownBase = (props: SimpleButtonDropdownProps, ref) => {
66
70
  resolveSecondaryLabel,
67
71
  children,
68
72
  isFluid,
73
+ menuVirtualization,
74
+ header,
75
+ footer,
76
+ clickAwayRef,
69
77
  ...buttonProps
70
78
  } = props;
71
79
 
@@ -119,6 +127,7 @@ const SimpleButtonDropdownBase = (props: SimpleButtonDropdownProps, ref) => {
119
127
  onOptionSelect={handleOptionChange}
120
128
  onMenuOpen={onMenuOpen}
121
129
  onMenuClose={onMenuClose}
130
+ clickAwayRef={clickAwayRef}
122
131
  menu={{
123
132
  isFluid,
124
133
  options,
@@ -128,6 +137,9 @@ const SimpleButtonDropdownBase = (props: SimpleButtonDropdownProps, ref) => {
128
137
  resolveLabel,
129
138
  resolveSecondaryLabel,
130
139
  size,
140
+ virtualization: menuVirtualization,
141
+ header,
142
+ footer,
131
143
  }}
132
144
  >
133
145
  {optionsVariant === 'checkbox' ? btnText : children}
@@ -28,6 +28,7 @@ const Dropdown = /*#__PURE__*/React.forwardRef((_ref, ref) => {
28
28
  onMenuClose,
29
29
  scrollMenuToBottom = false,
30
30
  dropdownInputText = '',
31
+ clickAwayRef,
31
32
  ...inputProps
32
33
  } = _ref;
33
34
  const dropdownRef = React.useRef();
@@ -51,7 +52,8 @@ const Dropdown = /*#__PURE__*/React.forwardRef((_ref, ref) => {
51
52
  }
52
53
  };
53
54
  return /*#__PURE__*/React.createElement(_clickAway.ClickAway, {
54
- onChange: onMenuToggle
55
+ onChange: onMenuToggle,
56
+ clickAwayRef: clickAwayRef
55
57
  }, _ref2 => {
56
58
  let {
57
59
  isOpen,
@@ -15,7 +15,7 @@ import {
15
15
  import {sizeFluid} from '../../styles/variables/_size';
16
16
  import {spaceNone, spaceXXSmall} from '../../styles/variables/_space';
17
17
  import {classify} from '../../utils/classify';
18
- import {ClickAway} from '../../utils/click-away';
18
+ import {type ClickAwayRefType, ClickAway} from '../../utils/click-away';
19
19
  import type {InputProps} from '../Input';
20
20
  import {Input} from '../Input';
21
21
  import type {MenuOption, MenuProps} from '../Menu';
@@ -35,6 +35,7 @@ export type DropdownProps = {
35
35
  scrollMenuToBottom?: boolean,
36
36
  dropdownInputText?: string,
37
37
  menu?: MenuProps,
38
+ clickAwayRef?: ClickAwayRefType,
38
39
  ...
39
40
  };
40
41
 
@@ -53,6 +54,7 @@ export const Dropdown: React$AbstractComponent<
53
54
  onMenuClose,
54
55
  scrollMenuToBottom = false,
55
56
  dropdownInputText = '',
57
+ clickAwayRef,
56
58
  ...inputProps
57
59
  }: DropdownProps,
58
60
  ref,
@@ -75,7 +77,7 @@ export const Dropdown: React$AbstractComponent<
75
77
  };
76
78
 
77
79
  return (
78
- <ClickAway onChange={onMenuToggle}>
80
+ <ClickAway onChange={onMenuToggle} clickAwayRef={clickAwayRef}>
79
81
  {({isOpen, onOpen, cancelNext, clickAway}) => (
80
82
  <div
81
83
  data-testid="Dropdown"
@@ -26,6 +26,9 @@ const SimpleDropdownBase = (props, ref) => {
26
26
  menuVirtualization,
27
27
  resolveSecondaryLabel,
28
28
  isMenuFluid = true,
29
+ header,
30
+ footer,
31
+ clickAwayRef,
29
32
  ...inputProps
30
33
  } = props;
31
34
  const [dropdownInputText, setDropdownInputText] = React.useState('');
@@ -61,6 +64,7 @@ const SimpleDropdownBase = (props, ref) => {
61
64
  onMenuOpen: onMenuOpen,
62
65
  onMenuClose: onMenuClose,
63
66
  dropdownInputText: dropdownInputText,
67
+ clickAwayRef: clickAwayRef,
64
68
  menu: {
65
69
  options,
66
70
  selectedKeys: dropdownSelectedKeys,
@@ -70,7 +74,9 @@ const SimpleDropdownBase = (props, ref) => {
70
74
  resolveSecondaryLabel,
71
75
  virtualization: menuVirtualization,
72
76
  size,
73
- isFluid: isMenuFluid
77
+ isFluid: isMenuFluid,
78
+ header,
79
+ footer
74
80
  }
75
81
  }));
76
82
  };
@@ -2,6 +2,7 @@
2
2
 
3
3
  import * as React from 'react';
4
4
 
5
+ import type {ClickAwayRefType} from '../../utils/click-away';
5
6
  import {
6
7
  getSelectedKeysFromSelectedOption,
7
8
  getTextLabelFromSelectedKeys,
@@ -26,15 +27,17 @@ export type SimpleDropdownProps = {
26
27
  ...InputProps,
27
28
 
28
29
  classNames?: ClassNames,
30
+ clickAwayRef?: ClickAwayRefType,
29
31
 
30
32
  // Menu props
31
33
  options?: Array<MenuOption>,
32
-
33
34
  optionsVariant?: MenuOptionsVariant,
34
35
  allowSearch?: boolean,
35
36
  selectedKeys?: Array<string>,
36
37
  isMenuFluid?: boolean,
37
38
  menuVirtualization?: Virtualization,
39
+ header?: React.Node,
40
+ footer?: React.Node,
38
41
 
39
42
  // events
40
43
  onChange?: (option: MenuOption, ?SyntheticEvent<HTMLElement>) => mixed,
@@ -63,6 +66,9 @@ const SimpleDropdownBase = (props: SimpleDropdownProps, ref) => {
63
66
  menuVirtualization,
64
67
  resolveSecondaryLabel,
65
68
  isMenuFluid = true,
69
+ header,
70
+ footer,
71
+ clickAwayRef,
66
72
  ...inputProps
67
73
  } = props;
68
74
 
@@ -117,6 +123,7 @@ const SimpleDropdownBase = (props: SimpleDropdownProps, ref) => {
117
123
  onMenuOpen={onMenuOpen}
118
124
  onMenuClose={onMenuClose}
119
125
  dropdownInputText={dropdownInputText}
126
+ clickAwayRef={clickAwayRef}
120
127
  menu={{
121
128
  options,
122
129
  selectedKeys: dropdownSelectedKeys,
@@ -127,6 +134,8 @@ const SimpleDropdownBase = (props: SimpleDropdownProps, ref) => {
127
134
  virtualization: menuVirtualization,
128
135
  size,
129
136
  isFluid: isMenuFluid,
137
+ header,
138
+ footer,
130
139
  }}
131
140
  />
132
141
  );
@@ -29,6 +29,7 @@ const InlineDropdown = /*#__PURE__*/React.forwardRef((_ref, ref) => {
29
29
  onMenuOpen,
30
30
  onMenuClose,
31
31
  children,
32
+ clickAwayRef,
32
33
  ...restButtonProps
33
34
  } = _ref;
34
35
  const menuBtnRef = React.useRef(null);
@@ -49,7 +50,8 @@ const InlineDropdown = /*#__PURE__*/React.forwardRef((_ref, ref) => {
49
50
  isOpen ? onMenuOpen && onMenuOpen() : onMenuClose && onMenuClose();
50
51
  };
51
52
  return /*#__PURE__*/React.createElement(_clickAway.ClickAway, {
52
- onChange: onMenuToggle
53
+ onChange: onMenuToggle,
54
+ clickAwayRef: clickAwayRef
53
55
  }, _ref2 => {
54
56
  let {
55
57
  isOpen,
@@ -16,7 +16,7 @@ import {
16
16
 
17
17
  import {spaceNone, spaceXXSmall} from '../../styles/variables/_space';
18
18
  import {classify} from '../../utils/classify';
19
- import {ClickAway} from '../../utils/click-away';
19
+ import {type ClickAwayRefType, ClickAway} from '../../utils/click-away';
20
20
  import type {UnstyledButtonProps} from '../Button';
21
21
  import {UnstyledButton} from '../Button';
22
22
  import type {AnchorType} from '../ButtonDropdown';
@@ -42,6 +42,7 @@ export type InlineDropdownProps = {
42
42
  onMenuOpen?: () => mixed,
43
43
  onMenuClose?: () => mixed,
44
44
  size?: 'medium' | 'small' | 'extraSmall',
45
+ clickAwayRef?: ClickAwayRefType,
45
46
  ...
46
47
  };
47
48
 
@@ -60,6 +61,7 @@ export const InlineDropdown: React$AbstractComponent<
60
61
  onMenuOpen,
61
62
  onMenuClose,
62
63
  children,
64
+ clickAwayRef,
63
65
  ...restButtonProps
64
66
  }: InlineDropdownProps,
65
67
  ref,
@@ -79,7 +81,7 @@ export const InlineDropdown: React$AbstractComponent<
79
81
  };
80
82
 
81
83
  return (
82
- <ClickAway onChange={onMenuToggle}>
84
+ <ClickAway onChange={onMenuToggle} clickAwayRef={clickAwayRef}>
83
85
  {({isOpen, onOpen, cancelNext, clickAway}) => (
84
86
  <div
85
87
  data-testid="InlineDropdown"
@@ -26,6 +26,10 @@ const SimpleInlineDropdownBase = (props, ref) => {
26
26
  resolveSecondaryLabel,
27
27
  children,
28
28
  isFluid,
29
+ menuVirtualization,
30
+ header,
31
+ footer,
32
+ clickAwayRef,
29
33
  ...buttonProps
30
34
  } = props;
31
35
  const [btnText, setBtnText] = React.useState('');
@@ -60,6 +64,7 @@ const SimpleInlineDropdownBase = (props, ref) => {
60
64
  onOptionSelect: handleOptionChange,
61
65
  onMenuOpen: onMenuOpen,
62
66
  onMenuClose: onMenuClose,
67
+ clickAwayRef: clickAwayRef,
63
68
  menu: {
64
69
  isFluid,
65
70
  options,
@@ -68,7 +73,10 @@ const SimpleInlineDropdownBase = (props, ref) => {
68
73
  allowSearch,
69
74
  resolveLabel,
70
75
  resolveSecondaryLabel,
71
- size: size === 'extraSmall' ? 'small' : size
76
+ size: size === 'extraSmall' ? 'small' : size,
77
+ virtualization: menuVirtualization,
78
+ header,
79
+ footer
72
80
  }
73
81
  }), optionsVariant === 'checkbox' ? btnText : children);
74
82
  };
@@ -2,13 +2,14 @@
2
2
 
3
3
  import * as React from 'react';
4
4
 
5
+ import type {ClickAwayRefType} from '../../utils/click-away';
5
6
  import {
6
7
  getButtonLabelFromSelectedKeys,
7
8
  getSelectedKeysFromSelectedOption,
8
9
  } from '../../utils/menu';
9
10
  import type {ButtonProps} from '../Button';
10
11
  import type {AnchorType} from '../ButtonDropdown';
11
- import type {MenuOption, MenuOptionsVariant} from '../Menu';
12
+ import type {MenuOption, MenuOptionsVariant, Virtualization} from '../Menu';
12
13
 
13
14
  import {InlineDropdown} from './InlineDropdown';
14
15
 
@@ -40,10 +41,14 @@ export type SimpleInlineDropdownProps = {
40
41
  onOptionSelect?: (option: MenuOption, ?SyntheticEvent<HTMLElement>) => mixed,
41
42
  onMenuOpen?: () => mixed,
42
43
  onMenuClose?: () => mixed,
44
+ menuVirtualization?: Virtualization,
45
+ header?: React.Node,
46
+ footer?: React.Node,
43
47
 
44
48
  // Resolvers
45
49
  resolveLabel?: (option: MenuOption) => string | React.Node,
46
50
  resolveSecondaryLabel?: (option: MenuOption) => string | React.Node,
51
+ clickAwayRef?: ClickAwayRefType,
47
52
  ...
48
53
  };
49
54
 
@@ -63,6 +68,10 @@ const SimpleInlineDropdownBase = (props: SimpleInlineDropdownProps, ref) => {
63
68
  resolveSecondaryLabel,
64
69
  children,
65
70
  isFluid,
71
+ menuVirtualization,
72
+ header,
73
+ footer,
74
+ clickAwayRef,
66
75
  ...buttonProps
67
76
  } = props;
68
77
 
@@ -116,6 +125,7 @@ const SimpleInlineDropdownBase = (props: SimpleInlineDropdownProps, ref) => {
116
125
  onOptionSelect={handleOptionChange}
117
126
  onMenuOpen={onMenuOpen}
118
127
  onMenuClose={onMenuClose}
128
+ clickAwayRef={clickAwayRef}
119
129
  menu={{
120
130
  isFluid,
121
131
  options,
@@ -125,6 +135,9 @@ const SimpleInlineDropdownBase = (props: SimpleInlineDropdownProps, ref) => {
125
135
  resolveLabel,
126
136
  resolveSecondaryLabel,
127
137
  size: size === 'extraSmall' ? 'small' : size,
138
+ virtualization: menuVirtualization,
139
+ header,
140
+ footer,
128
141
  }}
129
142
  >
130
143
  {optionsVariant === 'checkbox' ? btnText : children}
@@ -133,30 +133,46 @@ const Menu = /*#__PURE__*/React.forwardRef((props, ref) => {
133
133
  enable: false,
134
134
  menuHeight: null,
135
135
  itemHeight: null
136
- }
136
+ },
137
+ header,
138
+ footer
137
139
  } = props;
138
140
  const [searchText, setSearchText] = React.useState('');
139
141
  const {
140
142
  menuHeight
141
143
  } = virtualization;
144
+ const hasHeader = header ? true : false;
145
+ const hasFooter = footer ? true : false;
142
146
  return /*#__PURE__*/React.createElement("div", {
143
147
  className: (0, _classify.classify)(_MenuModule.default.menuCard, {
144
148
  [_MenuModule.default.fluid]: isFluid,
145
149
  [_MenuModule.default.medium]: size === 'medium',
146
- [_MenuModule.default.small]: size === 'small'
150
+ [_MenuModule.default.mediumWithHeader]: size === 'medium' && hasHeader && !hasFooter,
151
+ [_MenuModule.default.mediumWithFooter]: size === 'medium' && !hasHeader && hasFooter,
152
+ [_MenuModule.default.mediumWithHeaderAndFooter]: size === 'medium' && hasFooter && hasHeader,
153
+ [_MenuModule.default.small]: size === 'small',
154
+ [_MenuModule.default.smallWithHeader]: size === 'small' && hasHeader && !hasFooter,
155
+ [_MenuModule.default.smallWithFooter]: size === 'small' && !hasHeader && hasFooter,
156
+ [_MenuModule.default.smallWithHeaderAndFooter]: size === 'small' && hasFooter && hasHeader,
157
+ [_MenuModule.default.menuCardTopPaddingZero]: header,
158
+ [_MenuModule.default.menuCardBottomPaddingZero]: footer
147
159
  }, classNames?.wrapper),
148
160
  style: {
149
161
  width,
150
162
  maxHeight: menuHeight ? menuHeight + 'px' : ''
151
163
  },
152
164
  ref: ref
153
- }, allowSearch && /*#__PURE__*/React.createElement(_SearchInput.SearchInput, {
165
+ }, hasHeader && /*#__PURE__*/React.createElement("div", {
166
+ className: _MenuModule.default.menuHeader
167
+ }, header), allowSearch && /*#__PURE__*/React.createElement(_SearchInput.SearchInput, {
154
168
  value: searchText,
155
169
  onChange: e => setSearchText(e.target.value),
156
170
  onClear: () => setSearchText(''),
157
171
  size: size
158
172
  }), /*#__PURE__*/React.createElement(RenderOption, _extends({}, props, {
159
173
  searchText: searchText
160
- })));
174
+ })), hasFooter && /*#__PURE__*/React.createElement("div", {
175
+ className: _MenuModule.default.menuFooter
176
+ }, footer));
161
177
  });
162
178
  exports.Menu = Menu;
@@ -78,6 +78,8 @@ export type BaseMenuProps = {
78
78
  resolveSecondaryLabel?: (option: MenuOption) => string | React.Node,
79
79
  // When virtualization is enabled, the MenuOptionButtons will be rendered only when they are present in the Menu's viewport
80
80
  virtualization?: Virtualization,
81
+ header?: React.Node,
82
+ footer?: React.Node,
81
83
  };
82
84
 
83
85
  export type MenuOptionTypes = {
@@ -311,9 +313,15 @@ export const Menu: React$AbstractComponent<MenuProps, HTMLDivElement> =
311
313
  menuHeight: null,
312
314
  itemHeight: null,
313
315
  },
316
+ header,
317
+ footer,
314
318
  } = props;
315
319
  const [searchText, setSearchText] = React.useState('');
316
320
  const {menuHeight} = virtualization;
321
+
322
+ const hasHeader = header ? true : false;
323
+ const hasFooter = footer ? true : false;
324
+
317
325
  return (
318
326
  <div
319
327
  className={classify(
@@ -321,7 +329,21 @@ export const Menu: React$AbstractComponent<MenuProps, HTMLDivElement> =
321
329
  {
322
330
  [css.fluid]: isFluid,
323
331
  [css.medium]: size === 'medium',
332
+ [css.mediumWithHeader]:
333
+ size === 'medium' && hasHeader && !hasFooter,
334
+ [css.mediumWithFooter]:
335
+ size === 'medium' && !hasHeader && hasFooter,
336
+ [css.mediumWithHeaderAndFooter]:
337
+ size === 'medium' && hasFooter && hasHeader,
324
338
  [css.small]: size === 'small',
339
+ [css.smallWithHeader]:
340
+ size === 'small' && hasHeader && !hasFooter,
341
+ [css.smallWithFooter]:
342
+ size === 'small' && !hasHeader && hasFooter,
343
+ [css.smallWithHeaderAndFooter]:
344
+ size === 'small' && hasFooter && hasHeader,
345
+ [css.menuCardTopPaddingZero]: header,
346
+ [css.menuCardBottomPaddingZero]: footer,
325
347
  },
326
348
  classNames?.wrapper,
327
349
  )}
@@ -331,6 +353,7 @@ export const Menu: React$AbstractComponent<MenuProps, HTMLDivElement> =
331
353
  }}
332
354
  ref={ref}
333
355
  >
356
+ {hasHeader && <div className={css.menuHeader}>{header}</div>}
334
357
  {allowSearch && (
335
358
  <SearchInput
336
359
  value={searchText}
@@ -340,6 +363,7 @@ export const Menu: React$AbstractComponent<MenuProps, HTMLDivElement> =
340
363
  />
341
364
  )}
342
365
  <RenderOption {...props} searchText={searchText} />
366
+ {hasFooter && <div className={css.menuFooter}>{footer}</div>}
343
367
  </div>
344
368
  );
345
369
  },
@@ -22,6 +22,7 @@
22
22
  size160,
23
23
  size42,
24
24
  size34,
25
+ size50,
25
26
  size300,
26
27
  size240,
27
28
  size228,
@@ -34,12 +35,12 @@
34
35
  spaceSmall,
35
36
  spaceXSmall,
36
37
  spaceXXSmall,
37
- spaceMedium,
38
- spaceNone
38
+ spaceMedium
39
39
  ) from '../../styles/variables/_space.css';
40
40
 
41
41
  @value (
42
- elevationMenu
42
+ elevationMenu,
43
+ elevationCard
43
44
  ) from '../../styles/variables/_elevation.css';
44
45
 
45
46
  .menuCard {
@@ -49,13 +50,21 @@
49
50
  background-color: colorBackgroundTertiary;
50
51
  display: flex;
51
52
  flex-flow: column;
52
- padding: spaceSmall spaceXSmall;
53
+ padding: spaceXSmall;
53
54
  min-width: size160;
54
55
  border-radius: borderRadiusMedium;
55
56
  overflow: auto;
56
57
  z-index: elevationMenu;
57
58
  }
58
59
 
60
+ .menuCardTopPaddingZero {
61
+ padding-top: spaceNone;
62
+ }
63
+
64
+ .menuCardBottomPaddingZero {
65
+ padding-bottom: spaceNone;
66
+ }
67
+
59
68
  .menuCard:empty {
60
69
  padding: spaceNone;
61
70
  border: none;
@@ -67,12 +76,30 @@
67
76
  max-height: size276;
68
77
  }
69
78
 
79
+ .mediumWithHeader,
80
+ .mediumWithFooter {
81
+ max-height: calc(size276 + size50);
82
+ }
83
+
84
+ .mediumWithHeaderAndFooter {
85
+ max-height: calc(size276 + size50 + size50);
86
+ }
87
+
70
88
  .small {
71
89
  width: size240;
72
90
  min-width: size240;
73
91
  max-height: size228;
74
92
  }
75
93
 
94
+ .smallWithHeader,
95
+ .smallWithHeaderAndFooter {
96
+ max-height: calc(size228 + size50);
97
+ }
98
+
99
+ .smallWithHeaderAndFooter {
100
+ max-height: calc(size228 + size50 + size50);
101
+ }
102
+
76
103
  .fluid {
77
104
  width: sizeFluid;
78
105
  min-width: size160;
@@ -223,3 +250,42 @@
223
250
  margin-bottom: spaceXSmall;
224
251
  margin-left: spaceSmall;
225
252
  }
253
+
254
+ .menuHeader {
255
+ position: sticky;
256
+ background-color: colorBackgroundTertiary;
257
+ padding: spaceXSmall spaceNone;
258
+ top: spaceNone;
259
+ margin-bottom: spaceXSmall;
260
+ z-index: calc(elevationCard/4);
261
+ min-height: size50;
262
+ max-height: size50;
263
+ }
264
+
265
+ .menuHeader::after {
266
+ content: '';
267
+ position: absolute;
268
+ left: calc(spaceXSmall * -1);
269
+ right: calc(spaceXSmall * -1);
270
+ bottom: spaceNone;
271
+ border-bottom: borderWidthPrimary solid colorBorderPrimary;
272
+ }
273
+
274
+ .menuFooter {
275
+ position: sticky;
276
+ background-color: colorBackgroundTertiary;
277
+ padding: spaceXSmall spaceNone;
278
+ bottom: spaceNone;
279
+ margin-top: spaceXSmall;
280
+ min-height: size50;
281
+ max-height: size50;
282
+ }
283
+
284
+ .menuFooter::before {
285
+ content: '';
286
+ position: absolute;
287
+ left: calc(spaceXSmall * -1);
288
+ right: calc(spaceXSmall * -1);
289
+ top: spaceNone;
290
+ border-top: borderWidthPrimary solid colorBorderPrimary;
291
+ }