@sproutsocial/seeds-react-menu 1.2.0 → 1.2.2

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sproutsocial/seeds-react-menu",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "Seeds React Menu",
5
5
  "author": "Sprout Social, Inc.",
6
6
  "license": "MIT",
@@ -78,8 +78,8 @@ const handleStateChange = (
78
78
  * @description An ActionMenu contains a list of clickable items like buttons or links. ActionMenus do not hold a selection.
79
79
  *
80
80
  * **To select menu items:**
81
- * @see {@link https://github.com/sproutsocial/seeds/tree/dev/seeds-react/seeds-react-menu/src/SingleSelectMenu | SingleSelectMenu}
82
- * @see {@link https://github.com/sproutsocial/seeds/tree/dev/seeds-react/seeds-react-menu/src/MultiSelectMenu | MultiSelectMenu}
81
+ * @see {@link https://seeds.sproutsocial.com/components/single-select-menu SingleSelectMenu}
82
+ * @see {@link https://seeds.sproutsocial.com/components/multi-select-menu MultiSelectMenu}
83
83
  */
84
84
  export const ActionMenu = <I extends TypeMenuItemProps = TypeMenuItemProps>({
85
85
  children: childrenProp,
@@ -52,9 +52,7 @@ export const AutocompleteTextInputExample: Story = {
52
52
  itemToString={(item) => (item ? TEST_BOOKS[item.index].title : "")}
53
53
  menuToggleElement={
54
54
  <>
55
- <MenuLabel htmlFor="my-combobox" mb={300}>
56
- Choose a book
57
- </MenuLabel>
55
+ <MenuLabel mb={300}>Choose a book</MenuLabel>
58
56
  <AutocompleteInput />
59
57
  </>
60
58
  }
@@ -80,9 +78,7 @@ export const AutocompleteWithItemsAsProps: Story = {
80
78
  itemToString={(item) => (item ? TEST_BOOKS[item.index].title : "")}
81
79
  menuToggleElement={
82
80
  <>
83
- <MenuLabel htmlFor="my-combobox" mb={300}>
84
- Choose a book
85
- </MenuLabel>
81
+ <MenuLabel mb={300}>Choose a book</MenuLabel>
86
82
  <AutocompleteInput />
87
83
  </>
88
84
  }
@@ -104,11 +100,9 @@ export const AutocompleteTextWithButtonExample: Story = {
104
100
  itemToString={(item) => (item ? TEST_BOOKS[item.index].title : "")}
105
101
  menuToggleElement={
106
102
  <>
107
- <MenuLabel htmlFor="my-combobox" mb={300}>
108
- Choose a book
109
- </MenuLabel>
103
+ <MenuLabel mb={300}>Choose a book</MenuLabel>
110
104
  <Box display="flex" alignItems="center" gap={200}>
111
- <AutocompleteInput />
105
+ <AutocompleteInput style={{ flex: 2 }} />
112
106
  <MenuToggleButton>
113
107
  <Icon name="chevron-down" aria-label="Open Menu" />
114
108
  </MenuToggleButton>
@@ -137,9 +131,7 @@ export const AutocompleteTokenInputExample: Story = {
137
131
  itemToString={(item) => (item ? TEST_BOOKS[item.index].title : "")}
138
132
  menuToggleElement={
139
133
  <>
140
- <MenuLabel htmlFor="my-combobox" mb={300}>
141
- Choose a book
142
- </MenuLabel>
134
+ <MenuLabel mb={300}>Choose a book</MenuLabel>
143
135
  <AutocompleteTokenInput />
144
136
  <MenuToggleButton mt={200} width="100%" p="0">
145
137
  <Icon name="chevron-down" aria-label="Open Menu" />
@@ -170,9 +162,7 @@ export const AutocompleteSelectExample: Story = {
170
162
  itemToString={(item) => (item ? TEST_BOOKS[item.index].title : "")}
171
163
  menuToggleElement={
172
164
  <>
173
- <MenuLabel htmlFor="my-combobox" mb={300}>
174
- Choose a book
175
- </MenuLabel>
165
+ <MenuLabel mb={300}>Choose a book</MenuLabel>
176
166
  <AutocompleteSelect />
177
167
  </>
178
168
  }
@@ -247,9 +237,7 @@ const TestControlledMultiAutocomplete = (args: CustomAutocompleteArgs) => {
247
237
  itemToString={(item) => (item ? TEST_BOOKS[item.index].title : "")}
248
238
  menuToggleElement={
249
239
  <>
250
- <MenuLabel htmlFor="my-combobox" mb={300}>
251
- Choose a book
252
- </MenuLabel>
240
+ <MenuLabel mb={300}>Choose a book</MenuLabel>
253
241
  <AutocompleteTokenInput />
254
242
  <MenuToggleButton mt={200} width="100%" p="0">
255
243
  <Icon name="chevron-down" aria-label="Open Menu" />
@@ -1,7 +1,6 @@
1
1
  import React from "react";
2
2
 
3
3
  import type { TypeMenuItemProps } from "../MenuItem";
4
- import type { TypeMenuRootProps } from "../MenuRoot";
5
4
  import type { TypeAutocompleteProps } from "./AutocompleteTypes";
6
5
  import { SingleAutocomplete } from "./SingleAutocomplete";
7
6
  import { MultiAutocomplete } from "./MultiAutocomplete";
@@ -9,11 +8,11 @@ import { MultiAutocomplete } from "./MultiAutocomplete";
9
8
  /**
10
9
  * @link https://seeds.sproutsocial.com/components/autocomplete/
11
10
  *
12
- * @description A Autocomplete allows selecting a {@link https://github.com/sproutsocial/seeds/tree/dev/seeds-react/seeds-react-menu/src/MenuItem | MenuItems} to be selected from a list or groups of lists to populate an input.
11
+ * @description A Autocomplete allows selecting {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuitem MenuItems} from a list or groups of lists to populate an input.
13
12
  *
14
13
  */
15
14
  export const Autocomplete = <I extends TypeMenuItemProps = TypeMenuItemProps>({
16
- multiSelect,
15
+ multiSelect = false,
17
16
  ...rest
18
17
  }: TypeAutocompleteProps<I>) => {
19
18
  if (multiSelect) {
@@ -1,34 +1,38 @@
1
- import type { TypeMenuRootOwnProps } from "../MenuRoot";
2
1
  import type {
3
2
  TypeDownshiftComboboxProps,
4
3
  TypeDownshiftMultiSelectProps,
5
4
  } from "../MenuContext";
6
5
  import type { TypeGetIsItemVisibleFn } from "../hooks/useItemFiltering";
7
- import type { TypeMenuRootProps } from "../MenuRoot";
8
6
  import type { TypeMenuItemProps } from "../MenuItem";
9
7
  import type {
10
8
  TypeChildrenOrItems,
11
9
  TypeHigherOrderComponentProps,
12
10
  } from "../types";
13
11
 
14
- export type TypeSingleAutocompleteProps<
15
- I extends TypeMenuItemProps = TypeMenuItemProps
16
- > = TypeHigherOrderComponentProps &
17
- TypeChildrenOrItems<I> &
12
+ export type TypeBaseAutocompleteProps = TypeHigherOrderComponentProps &
18
13
  TypeDownshiftComboboxProps & {
14
+ /** A function that can be passed to override the default filtering logic */
19
15
  getIsItemVisible?: TypeGetIsItemVisibleFn;
16
+ /** Set multiSelect to true to allow multiple selections.
17
+ * Default: false*/
18
+ multiSelect?: boolean;
20
19
  };
21
20
 
21
+ export type TypeSingleAutocompleteProps<
22
+ I extends TypeMenuItemProps = TypeMenuItemProps
23
+ > = TypeBaseAutocompleteProps & {
24
+ multiSelect?: false;
25
+ } & TypeChildrenOrItems<I>;
26
+
22
27
  export type TypeMultiAutocompleteProps<
23
28
  I extends TypeMenuItemProps = TypeMenuItemProps
24
- > = TypeSingleAutocompleteProps<I> &
29
+ > = TypeBaseAutocompleteProps &
25
30
  TypeDownshiftMultiSelectProps & {
26
- /* Determine whether or not the combobox should display selected items in the dropdown */
31
+ multiSelect?: true;
32
+ /** Determines whether a multiselect autocomplete will display selected items in the dropdown */
27
33
  showSelectedItemsInDropdown?: boolean;
28
- };
34
+ } & TypeChildrenOrItems<I>;
29
35
 
30
36
  export type TypeAutocompleteProps<
31
37
  I extends TypeMenuItemProps = TypeMenuItemProps
32
- > =
33
- | (TypeSingleAutocompleteProps<I> & { multiSelect?: false })
34
- | (TypeMultiAutocompleteProps<I> & { multiSelect: true });
38
+ > = TypeSingleAutocompleteProps<I> | TypeMultiAutocompleteProps<I>;
@@ -1,4 +1,3 @@
1
- import React, { useEffect } from "react";
2
1
  import { useCombobox } from "downshift";
3
2
  import { useMenuChildren } from "../hooks/useMenuChildren";
4
3
  import { itemToString as defaultItemToString } from "../utils/downshiftDefaults";
@@ -8,7 +7,7 @@ import { useItemFiltering } from "../hooks/useItemFiltering";
8
7
  import { MenuRoot } from "../MenuRoot";
9
8
 
10
9
  import type { TypeMenuItemProps } from "../MenuItem";
11
- import type { TypeAutocompleteProps } from "./AutocompleteTypes";
10
+ import type { TypeSingleAutocompleteProps } from "./AutocompleteTypes";
12
11
 
13
12
  export const SingleAutocomplete = <
14
13
  I extends TypeMenuItemProps = TypeMenuItemProps
@@ -21,7 +20,7 @@ export const SingleAutocomplete = <
21
20
  itemToString = defaultItemToString,
22
21
  getIsItemVisible,
23
22
  ...useComboboxProps
24
- }: TypeAutocompleteProps<I>) => {
23
+ }: TypeSingleAutocompleteProps<I>) => {
25
24
  /** Get a list of menuItems and children */
26
25
  const { allMenuItems, children } = useMenuChildren({
27
26
  children: childrenProp,
@@ -6,9 +6,9 @@ import { useCallback } from "react";
6
6
  import type { TypeMenuItemProps } from "../MenuItem";
7
7
 
8
8
  /**
9
- * @link https://seeds.sproutsocial.com/components/menu-content/
9
+ * @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menucontent
10
10
  *
11
- * @description MenuContent is used to contain lists or grouped lists of {@link https://github.com/sproutsocial/seeds/tree/dev/seeds-react/seeds-react-menu/src/MenuItem | MenuItems}.
11
+ * @description MenuContent is used to contain lists or grouped lists of {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuitem MenuItems}.
12
12
  *
13
13
  * @example
14
14
  * <ActionMenu>
@@ -24,8 +24,8 @@ import type { TypeMenuItemProps } from "../MenuItem";
24
24
  * <MenuFooter>Footer</MenuFooter>
25
25
  * </ActionMenu>
26
26
  *
27
- * @see {@link https://seeds.sproutsocial.com/components/menu-item/ | MenuItem}
28
- * @see {@link https://seeds.sproutsocial.com/components/menu-group/ | MenuGroup}
27
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuitem MenuItem}
28
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menugroup MenuGroup}
29
29
  */
30
30
 
31
31
  const MenuContent = <I extends TypeMenuItemProps = TypeMenuItemProps>({
@@ -28,8 +28,11 @@ export interface TypeDownshiftMultiSelectProps
28
28
  >
29
29
  > {
30
30
  // Multi Select Props with conflicting useSelect prop names
31
+ /** Optional override to the built-in getA11yStatusMessage function for multiple selection*/
31
32
  getA11yMultiStatusMessage?: UseMultipleSelectionProps<TypeInternalItemProps>["getA11yStatusMessage"];
33
+ /** Optional override to the built-in onStateChange function for multiple selection*/
32
34
  onMultiSelectStateChange?: UseMultipleSelectionProps<TypeInternalItemProps>["onStateChange"];
35
+ /** Optional override to the built-in stateReducer function for multiple selection*/
33
36
  multiSelectStateReducer?: UseMultipleSelectionProps<TypeInternalItemProps>["stateReducer"];
34
37
  }
35
38
 
@@ -125,7 +128,9 @@ export interface TypeMenuProviderProps {
125
128
  }
126
129
 
127
130
  export interface TypeMenuToggleContext extends TypeMenuContext {
128
- ref?: (arg0: React.ElementRef<any> | HTMLElement) => void;
131
+ ref?:
132
+ | React.RefObject<any>
133
+ | ((arg0: React.ElementRef<any> | HTMLElement) => void);
129
134
  toggle?: () => void;
130
135
  show?: () => void;
131
136
  hide?: () => void;
@@ -3,11 +3,11 @@ import type { TypeMenuFooterProps } from "./MenuFooterTypes";
3
3
  import { StyledMenuFooterBox } from "./styles";
4
4
 
5
5
  /**
6
- * @link https://seeds.sproutsocial.com/components/menu-footer/
6
+ * @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menufooter
7
7
  *
8
8
  * @description MenuFooter is a container used to hold footer content within a Menu.
9
9
  *
10
- * @see {@link https://seeds.sproutsocial.com/components/menu-header/ | MenuHeader}
10
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuheader MenuHeader}
11
11
  */
12
12
 
13
13
  export const MenuFooter = ({ children, ...rest }: TypeMenuFooterProps) => {
@@ -1,14 +1,13 @@
1
1
  import React from "react";
2
2
  import type { TypeMenuItemProps } from "../MenuItem";
3
- import type { TypeMenuRootProps } from "../MenuRoot";
4
3
  import type { TypeMenuGroupProps } from "./MenuGroupTypes";
5
4
  import { StyledMenuGroup, StyledTitle, StyledMenuGroupUl } from "./styles";
6
5
  import { mapMenuItems } from "../hooks/useMenuChildren";
7
6
 
8
7
  /**
9
- * @link https://seeds.sproutsocial.com/components/menu-group/
8
+ * @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menugroup
10
9
  *
11
- * @description MenuGroup is used to group lists of {@link https://github.com/sproutsocial/seeds/tree/dev/seeds-react/seeds-react-menu/src/MenuItem | MenuItems}.
10
+ * @description MenuGroup is used to group lists of {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuitem MenuItems}.
12
11
  *
13
12
  * @example
14
13
  * <ActionMenu>
@@ -22,7 +21,8 @@ import { mapMenuItems } from "../hooks/useMenuChildren";
22
21
  * </MenuContent>
23
22
  * </ActionMenu>
24
23
  *
25
- * @see {@link https://seeds.sproutsocial.com/components/menu-item/ | MenuItem}
24
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuitem MenuItem}
25
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menucontent MenuContent}
26
26
  */
27
27
 
28
28
  const MenuGroup = <I extends TypeMenuItemProps = TypeMenuItemProps>({
@@ -8,11 +8,13 @@ import {
8
8
  import type { TypeMenuHeaderProps } from "./MenuHeaderTypes";
9
9
 
10
10
  /**
11
- * @link https://seeds.sproutsocial.com/components/menu-header/
11
+ * @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuheader
12
12
  *
13
13
  * @description MenuHeader is a container used to hold header content within a Menu.
14
14
  *
15
- * @see {@link https://seeds.sproutsocial.com/components/menu-footer/ | MenuFooter}
15
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menufooter MenuFooter}
16
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menusearchinput MenuSearchInput}
17
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menusearchtokeninput MenuSearchTokenInput}
16
18
  */
17
19
 
18
20
  const MenuHeader = ({
package/src/MenuLabel.tsx CHANGED
@@ -2,10 +2,40 @@ import React from "react";
2
2
  import { Label, type TypeLabelProps } from "@sproutsocial/seeds-react-label";
3
3
  import { useMenuToggleContext } from "./MenuContext";
4
4
 
5
- export const MenuLabel = ({ children, ...rest }: Partial<TypeLabelProps>) => {
5
+ export interface TypeMenuLabelProps extends Omit<TypeLabelProps, "htmlFor"> {
6
+ // The children and required types are redundant, but they power the MenuLabel PropTable.
7
+ children: React.ReactNode;
8
+ /** Whether making a selection in the associated menu is required. */
9
+ required?: boolean;
10
+ /** ID of the associated form element. This prop is never valid to pass into MenuLabel
11
+ * because MenuLabel passes its own htmlFor prop to the underlying Label component.*/
12
+ htmlFor?: never;
13
+ }
14
+
15
+ /**
16
+ * @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menulabel
17
+ *
18
+ * @description MenuLabel extends Label to create an accessible label for a Menu's toggle element.
19
+ * A MenuLabel will automatically be associated with the corresponding menuToggleElement,
20
+ * so an `htmlFor` prop is not necessary or allowed.
21
+ *
22
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menutogglebutton MenuToggleButton}
23
+ * @see {@link https://seeds.sproutsocial.com/components/label/ Label}
24
+ */
25
+ export const MenuLabel = ({
26
+ children,
27
+ required = false,
28
+ ...rest
29
+ }: TypeMenuLabelProps) => {
6
30
  const { getLabelProps } = useMenuToggleContext();
7
31
  return (
8
- <Label htmlFor="fallback_menu_label" {...getLabelProps?.()} {...rest}>
32
+ // This fallback id should never be used, but it is here to satisfy TypeScript since getLabelProps could be undefined.
33
+ <Label
34
+ htmlFor="fallback_menu_label"
35
+ required={required}
36
+ {...getLabelProps?.()}
37
+ {...rest}
38
+ >
9
39
  {children}
10
40
  </Label>
11
41
  );
@@ -1,6 +1,12 @@
1
- import React, { useCallback, useEffect } from "react";
1
+ import React, {
2
+ useCallback,
3
+ useEffect,
4
+ useLayoutEffect,
5
+ type RefObject,
6
+ } from "react";
2
7
  import styled from "styled-components";
3
8
  import { Popout, type TypePopoutProps } from "@sproutsocial/seeds-react-popout";
9
+ import { mergeRefs } from "@sproutsocial/seeds-react-utilities";
4
10
 
5
11
  import {
6
12
  MenuContentProvider,
@@ -12,10 +18,16 @@ import {
12
18
  import { MOTION_DURATION_FAST } from "@sproutsocial/seeds-motion/unitless";
13
19
 
14
20
  export interface TypeMenuRootOwnProps {
21
+ /** The element that is or contains an element that will toggle the menu when clicked.
22
+ * May contain labels, buttons, inputs or other content as needed. */
15
23
  menuToggleElement: React.ReactElement<any>;
24
+ /** Props to pass through to the underlying Popout.
25
+ * Any Popout prop is valid except those explicitly omitted. */
16
26
  popoutProps?: Partial<
17
27
  Omit<TypePopoutProps, "isOpen" | "setIsOpen" | "content" | "children">
18
28
  >;
29
+ /** The width of the Popout content.
30
+ * Defaults to 200px or the width of the toggle element, whichever is greater.*/
19
31
  width?: TypePopoutProps["width"];
20
32
  }
21
33
  export interface TypeMenuRootProps
@@ -102,16 +114,14 @@ export const MenuPopout = ({
102
114
  };
103
115
 
104
116
  /**
105
- * @link https://seeds.sproutsocial.com/components/menu-root/
106
- *
107
- * @description MenuRoot is a utility component used to handle {@link https://github.com/sproutsocial/seeds/blob/dev/seeds-react/seeds-react-menu/src/MenuContext.tsx | MenuContext}. This component should rarely, if ever, be used directly unless building a custom menu type.
117
+ * @description MenuRoot is a utility component used to handle React Context for our Menus. This component should rarely, if ever, be used directly unless building a custom menu type.
108
118
  */
109
119
 
110
120
  export const MenuRoot = ({
111
121
  children,
112
122
  menuToggleElement,
113
123
  popoutProps: { placement = "bottom", focusLockProps, ...popoutProps } = {},
114
- width = "300px",
124
+ width,
115
125
  ...contextProps
116
126
  }: TypeMenuRootProps) => {
117
127
  const {
@@ -121,17 +131,27 @@ export const MenuRoot = ({
121
131
  inputValue,
122
132
  hiddenItemsCount = 0,
123
133
  items,
134
+ getMenuProps,
124
135
  } = contextProps;
125
- const setIsOpen = useCallback(
126
- (newIsOpen: boolean) => {
127
- newIsOpen ? openMenu?.() : closeMenu?.();
128
- },
129
- [openMenu, closeMenu]
130
- );
136
+
137
+ const toggleElementRef = React.useRef<HTMLElement>(null);
138
+ const [finalWidth, setFinalWidth] = React.useState<typeof width>();
139
+
140
+ const min_width = 200;
141
+
142
+ useLayoutEffect(() => {
143
+ if (width) {
144
+ setFinalWidth(width);
145
+ } else if (toggleElementRef.current?.offsetWidth) {
146
+ const toggleWidth = toggleElementRef.current.offsetWidth;
147
+ setFinalWidth(Math.max(toggleWidth, min_width));
148
+ } else {
149
+ setFinalWidth(min_width);
150
+ }
151
+ }, [width, toggleElementRef.current?.offsetWidth]);
131
152
 
132
153
  useEffect(() => {
133
154
  if (!inputValue) return;
134
-
135
155
  if (items && hiddenItemsCount >= items.length && isOpen) {
136
156
  closeMenu?.();
137
157
  }
@@ -139,6 +159,9 @@ export const MenuRoot = ({
139
159
 
140
160
  const menuContext = useMenu(contextProps);
141
161
 
162
+ // Hack to suppress error: "downshift: You forgot to call the getMenuProps getter function on your component / element."
163
+ getMenuProps?.({}, { suppressRefError: true });
164
+
142
165
  return (
143
166
  <MenuPopout
144
167
  placement={placement}
@@ -150,27 +173,23 @@ export const MenuRoot = ({
150
173
  {children}
151
174
  </MenuContentProvider>
152
175
  }
176
+ width={finalWidth}
153
177
  {...popoutProps}
154
178
  >
155
179
  {(toggleProps) => (
156
- <MenuToggleProvider menuContext={{ ...menuContext, ...toggleProps }}>
180
+ <MenuToggleProvider
181
+ menuContext={{
182
+ ...menuContext,
183
+ ...toggleProps,
184
+ ref: mergeRefs<HTMLElement>(
185
+ toggleProps.ref,
186
+ toggleElementRef
187
+ ) as RefObject<HTMLElement>,
188
+ }}
189
+ >
157
190
  {menuToggleElement}
158
191
  </MenuToggleProvider>
159
192
  )}
160
193
  </MenuPopout>
161
194
  );
162
195
  };
163
-
164
- export const MenuRootNoPopout = ({
165
- children,
166
- menuToggleElement,
167
- ...contextProps
168
- }: TypeMenuRootProps) => {
169
- const menuContext = useMenu(contextProps);
170
-
171
- return (
172
- <MenuContentProvider menuContext={menuContext}>
173
- {children}
174
- </MenuContentProvider>
175
- );
176
- };
@@ -10,23 +10,17 @@ import {
10
10
  } from "../MenuContext";
11
11
 
12
12
  export interface TypeMenuSearchInputProps extends TypeInputProps {
13
- /* A function that can be passed to override the default filtering logic */
13
+ /** A function that can be passed to override the default filtering logic */
14
14
  getIsItemVisible?: TypeGetIsItemVisibleFn;
15
15
  }
16
16
 
17
17
  /**
18
- * <input
19
- * aria-activedescendant=""
20
- * aria-autocomplete="list"
21
- * aria-controls="downshift-:r1:-menu"
22
- * aria-expanded="true"
23
- * />
24
- */
25
-
26
- /**
27
- * @link https://seeds.sproutsocial.com/components/menu-header/
18
+ * @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menusearchinput
28
19
  *
29
20
  * @description MenuSearchInput is search input that can be added to the MenuHeader to filter the items.
21
+ *
22
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuheader MenuHeader}
23
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menusearchtokeninput MenuSearchTokenInput}
30
24
  */
31
25
  export const MenuSearchInput = ({
32
26
  getIsItemVisible,
@@ -14,14 +14,17 @@ import {
14
14
  } from "../MenuTokenInput";
15
15
 
16
16
  export interface TypeMenuSearchTokenInputProps extends TypeMenuTokenInputProps {
17
- /* A function that can be passed to override the default filtering logic */
17
+ /** A function that can be passed to override the default filtering logic */
18
18
  getIsItemVisible?: TypeGetIsItemVisibleFn;
19
19
  }
20
20
 
21
21
  /**
22
- * @link https://seeds.sproutsocial.com/components/menu-search-token-input/
22
+ * @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menusearchtokeninput
23
23
  *
24
- * @description MenuSearchTokenInput is search token input that can be added to the MenuHeader to filter the items.
24
+ * @description MenuSearchTokenInput is a token input that can be added to the MenuHeader to filter the items.
25
+ *
26
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuheader MenuHeader}
27
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menusearchinput MenuSearchInput}
25
28
  */
26
29
  export const MenuSearchTokenInput = ({
27
30
  getIsItemVisible,
@@ -1,15 +1,16 @@
1
- import React, { type ReactNode } from "react";
2
1
  import { Button, type TypeButtonProps } from "@sproutsocial/seeds-react-button";
3
2
  import { useMenuToggleContext } from "../MenuContext";
4
3
 
5
- export interface TypeMenuToggleButtonProps extends Partial<TypeButtonProps> {
6
- children: ReactNode;
7
- }
4
+ export interface TypeMenuToggleButtonProps extends TypeButtonProps {}
8
5
 
9
- export const MenuToggleButton = ({
10
- children,
11
- ...rest
12
- }: TypeMenuToggleButtonProps) => {
6
+ /**
7
+ * @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menutogglebutton
8
+ * @param props - MenuToggleButton accepts all the same props as Button.
9
+ * @description MenuToggleButton extends the Button component to create a toggle for a menu.
10
+ * @see {@link https://seeds.sproutsocial.com/components/button/ Button}
11
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menulabel MenuLabel}
12
+ */
13
+ export const MenuToggleButton = (props: TypeMenuToggleButtonProps) => {
13
14
  const { getToggleButtonProps, isListbox, getDropdownProps, ref, ariaProps } =
14
15
  useMenuToggleContext();
15
16
  return (
@@ -22,9 +23,7 @@ export const MenuToggleButton = ({
22
23
  ...ariaProps,
23
24
  ...(isListbox ? {} : { role: "button", "aria-haspopup": "menu" }),
24
25
  })}
25
- {...rest}
26
- >
27
- {children}
28
- </Button>
26
+ {...props}
27
+ />
29
28
  );
30
29
  };
@@ -26,13 +26,19 @@ const StyledTokenInputWrapper = styled.div`
26
26
  `;
27
27
 
28
28
  export interface TypeMenuTokenInputProps extends TypeTokenInputProps {
29
- /* A function that can be passed to override the default token props */
30
- getTokenProps?: (
31
- itemId: TypeInternalItemProps["id"]
32
- ) => Partial<TypeTokenSpec>;
29
+ /** A function that can be passed to override the default token props */
30
+ getTokenProps?: (itemId: string) => Partial<TypeTokenSpec>;
31
+ /** Specify the menu context to use. MenuToggleContext is the default.
32
+ * This prop is only needed for specialized use cases. */
33
33
  MenuContext?: typeof MenuToggleContext | typeof MenuContentContext;
34
34
  }
35
35
 
36
+ /**
37
+ * @description MenuTokenInput is the basis of the MenuSearchTokenInput and AutocompleteTokenInput components
38
+ *
39
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menusearchinput MenuSearchInput}
40
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menusearchtokeninput MenuSearchTokenInput}
41
+ */
36
42
  export const MenuTokenInput = ({
37
43
  inputProps = {},
38
44
  getTokenProps,
@@ -10,11 +10,12 @@ import type { TypeMultiSelectMenuProps } from "./MultiSelectMenuTypes";
10
10
  import type { TypeInternalItemProps } from "../types";
11
11
 
12
12
  /**
13
- * @link https://seeds.sproutsocial.com/components/multiselect-menu/
13
+ * @link https://seeds.sproutsocial.com/components/multi-select-menu/
14
14
  *
15
- * @description A MultiSelectMenu allows multiple {@link https://github.com/sproutsocial/seeds/tree/dev/seeds-react/seeds-react-menu/src/MenuItem | MenuItems} to be selected from a list or groups of lists.
15
+ * @description A MultiSelectMenu allows multiple {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuitem MenuItems} to be selected from a list or groups of lists.
16
16
  *
17
- * @see {@link https://seeds.sproutsocial.com/components/menu-group/ | MenuGroup}
17
+ * @see {@link https://seeds.sproutsocial.com/components/single-select-menu/ SingleSelectMenu}
18
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menugroup MenuGroup}
18
19
  */
19
20
 
20
21
  export const MultiSelectMenu = <
@@ -30,7 +30,7 @@ Feature: NestedMenu
30
30
 
31
31
  Scenario: User can select a child menu without closing the menu
32
32
  Given the NestedMenu is open
33
- When an menu item that triggers a child menu is clicked
33
+ When a menu item that triggers a child menu is clicked
34
34
  Then the menu will stay open
35
35
  And the menu will not use its default open/close behavior
36
36
 
@@ -75,7 +75,7 @@ Feature: NestedMenu
75
75
 
76
76
  Scenario: A Menu stays open when a menu item with a childMenuId is clicked
77
77
  Given the NestedMenu is open
78
- When an menu item that triggers a child menu is clicked
78
+ When a menu item that triggers a child menu is clicked
79
79
  Then the menu will stay open
80
80
  And the menu will not use its default open/close behavior
81
81
 
@@ -85,6 +85,9 @@ export const NestedMenu = <
85
85
  onIsOpenChange: onNestedIsOpenChange,
86
86
  };
87
87
 
88
+ // Hack to suppress error: "downshift: You forgot to call the getMenuProps getter function on your component / element."
89
+ rootMenuContextProps.getMenuProps?.({}, { suppressRefError: true });
90
+
88
91
  /**
89
92
  * Handling the state of the NestedMenu content
90
93
  */
@@ -27,13 +27,16 @@ export interface TypeNestedMenuHeaderProps extends TypeMenuHeaderProps {
27
27
  }
28
28
 
29
29
  export interface TypeNestedMenuItemProps extends TypeMenuItemProps {
30
+ /** The id of the menu to be displayed when this item is selected. */
30
31
  childMenuId?: string;
31
32
  }
32
33
 
33
34
  export interface TypeNestedMenuProps<
34
35
  I extends TypeMenuItemProps = TypeNestedMenuItemProps
35
36
  > extends Omit<TypeActionMenuBaseProps, "MenuRootComponent"> {
37
+ /** The id of the menu to display when the NestedMenu is opened. */
36
38
  initialMenuId: string;
39
+ /** An optional callback to fire when the back button is clicked.*/
37
40
  onBackButtonClick?: (menuId: string) => void;
38
41
  /** Sets the default localized label for the back arrow in all child menus.
39
42
  * This label can be overridden by including backArrowLabel in a menu's menuHeaderProps. */