diff --git a/packages/components/inputs/async-select-input/README.md b/packages/components/inputs/async-select-input/README.md
index 7d7800bee0..789ce1a549 100644
--- a/packages/components/inputs/async-select-input/README.md
+++ b/packages/components/inputs/async-select-input/README.md
@@ -82,7 +82,7 @@ export default Example;
| `isSearchable` | `AsyncProps['isSearchable']` | | `true` | Whether to enable search functionality
[Props from React select was used](https://react-select.com/props) |
| `maxMenuHeight` | `AsyncProps['maxMenuHeight']` | | | Maximum height of the menu before scrolling
[Props from React select was used](https://react-select.com/props) |
| `menuPortalTarget` | `AsyncProps['menuPortalTarget']` | | | Dom element to portal the select menu to
[Props from React select was used](https://react-select.com/props) |
-| `menuPortalZIndex` | `number` | | `1` | z-index value for the menu portal |
+| `menuPortalZIndex` | `number` | | `1` | z-index value for the menu portal
Use in conjunction with `menuPortalTarget` |
| `menuShouldBlockScroll` | `AsyncProps['menuShouldBlockScroll']` | | | whether the menu should block scroll while open
[Props from React select was used](https://react-select.com/props) |
| `closeMenuOnSelect` | `AsyncProps['closeMenuOnSelect']` | | | Whether the menu should close after a value is selected. Defaults to `true`.
[Props from React select was used](https://react-select.com/props) |
| `name` | `AsyncProps['name']` | | | Name of the HTML Input (optional - without this, no input will be rendered)
[Props from React select was used](https://react-select.com/props) |
diff --git a/packages/components/inputs/async-select-input/src/async-select-input.story.js b/packages/components/inputs/async-select-input/src/async-select-input.story.js
index 6c7be8406a..3a997ed066 100644
--- a/packages/components/inputs/async-select-input/src/async-select-input.story.js
+++ b/packages/components/inputs/async-select-input/src/async-select-input.story.js
@@ -10,7 +10,10 @@ import {
number,
} from '@storybook/addon-knobs/react';
import Constraints from '@commercetools-uikit/constraints';
+import Spacings from '@commercetools-uikit/spacings';
import Section from '../../../../../docs/.storybook/decorators/section';
+import NeighbouringStackingContext from '../../../../../docs/.storybook/decorators/neighbouring-stacking-context';
+import { addMenuPortalProps } from '../../../../../docs/.storybook/utils';
import Readme from '../README.md';
import AsyncSelectInput from './async-select-input';
import * as icons from '../../../icons';
@@ -71,7 +74,7 @@ class SelectStory extends Component {
key={`${isMulti}-${defaultOptions}`}
defaultValue={isMulti ? [] : undefined}
render={(value, onChange) => (
-
+
+
)}
/>
diff --git a/packages/components/inputs/async-select-input/src/async-select-input.tsx b/packages/components/inputs/async-select-input/src/async-select-input.tsx
index 5efff1f311..c3591607d1 100644
--- a/packages/components/inputs/async-select-input/src/async-select-input.tsx
+++ b/packages/components/inputs/async-select-input/src/async-select-input.tsx
@@ -19,6 +19,7 @@ import {
customComponentsWithIcons,
messages,
createSelectStyles,
+ warnIfMenuPortalPropsAreMissing,
} from '@commercetools-uikit/select-utils';
import { useTheme } from '@commercetools-uikit/design-system';
@@ -196,6 +197,8 @@ export type TAsyncSelectInputProps = {
menuPortalTarget?: ReactSelectAsyncProps['menuPortalTarget'];
/**
* z-index value for the menu portal
+ *
+ * Use in conjunction with `menuPortalTarget`
*/
menuPortalZIndex: number;
/**
@@ -318,6 +321,12 @@ const AsyncSelectInput = (props: TAsyncSelectInputProps) => {
);
}
+ warnIfMenuPortalPropsAreMissing({
+ menuPortalZIndex: props.menuPortalZIndex,
+ menuPortalTarget: props.menuPortalTarget,
+ componentName: 'AsyncSelectInput',
+ });
+
const placeholder =
props.placeholder || intl.formatMessage(messages.placeholder);
diff --git a/packages/components/inputs/creatable-select-input/README.md b/packages/components/inputs/creatable-select-input/README.md
index 7c1052a7b5..592e3fcd28 100644
--- a/packages/components/inputs/creatable-select-input/README.md
+++ b/packages/components/inputs/creatable-select-input/README.md
@@ -77,7 +77,7 @@ export default Example;
| `isSearchable` | `CreatableProps['isSearchable']` | | `true` | Whether to enable search functionality
[Props from React select was used](https://react-select.com/props#creatable-props) |
| `maxMenuHeight` | `CreatableProps['maxMenuHeight']` | | | Maximum height of the menu before scrolling
[Props from React select was used](https://react-select.com/props#creatable-props) |
| `menuPortalTarget` | `CreatableProps['menuPortalTarget']` | | | Dom element to portal the select menu to
[Props from React select was used](https://react-select.com/props#creatable-props) |
-| `menuPortalZIndex` | `number` | | `1` | z-index value for the menu portal |
+| `menuPortalZIndex` | `number` | | `1` | z-index value for the menu portal
Use in conjunction with `menuPortalTarget` |
| `menuShouldBlockScroll` | `CreatableProps['menuShouldBlockScroll']` | | | whether the menu should block scroll while open
[Props from React select was used](https://react-select.com/props#creatable-props) |
| `closeMenuOnSelect` | `CreatableProps['closeMenuOnSelect']` | | | Whether the menu should close after a value is selected. Defaults to `true`.
[Props from React select was used](https://react-select.com/props#creatable-props) |
| `name` | `CreatableProps['name']` | | | Name of the HTML Input (optional - without this, no input will be rendered)
[Props from React select was used](https://react-select.com/props#creatable-props) |
diff --git a/packages/components/inputs/creatable-select-input/src/creatable-select-input.story.js b/packages/components/inputs/creatable-select-input/src/creatable-select-input.story.js
index c79d3be2c1..df4dff3ac4 100644
--- a/packages/components/inputs/creatable-select-input/src/creatable-select-input.story.js
+++ b/packages/components/inputs/creatable-select-input/src/creatable-select-input.story.js
@@ -13,6 +13,8 @@ import Constraints from '@commercetools-uikit/constraints';
import Spacings from '@commercetools-uikit/spacings';
import LinkTo from '@storybook/addon-links/react';
import Section from '../../../../../docs/.storybook/decorators/section';
+import NeighbouringStackingContext from '../../../../../docs/.storybook/decorators/neighbouring-stacking-context';
+import { addMenuPortalProps } from '../../../../../docs/.storybook/utils';
import Readme from '../README.md';
import CreatableSelectInput from './creatable-select-input';
import * as icons from '../../../icons';
@@ -103,53 +105,57 @@ storiesOf('Components|Inputs/SelectInputs', module)
key={isMulti}
defaultValue={isMulti ? [] : undefined}
render={(value, onChange) => (
-
{
- action('onChange')(event, ...args);
- onChange(event.target.value);
- }}
- onFocus={action('onFocus')}
- onInputChange={action('onInputChange')}
- options={options}
- placeholder={text('placeholder', 'Select..')}
- tabIndex={text('tabIndex', '0')}
- tabSelectsValue={boolean('tabSelectsValue', true)}
- value={value}
- // Creatable props
- allowCreateWhileLoading={boolean(
- 'allowCreateWhileLoading',
- false
- )}
- createOptionPosition={select(
- 'createOptionPosition',
- ['first', 'last'],
- 'last'
- )}
- showOptionGroupDivider={showOptionGroupDivider}
- iconLeft={iconLeft ? createElement(iconLeft) : undefined}
- />
+
+ {
+ action('onChange')(event, ...args);
+ onChange(event.target.value);
+ }}
+ onFocus={action('onFocus')}
+ onInputChange={action('onInputChange')}
+ options={options}
+ placeholder={text('placeholder', 'Select..')}
+ tabIndex={text('tabIndex', '0')}
+ tabSelectsValue={boolean('tabSelectsValue', true)}
+ value={value}
+ // Creatable props
+ allowCreateWhileLoading={boolean(
+ 'allowCreateWhileLoading',
+ false
+ )}
+ createOptionPosition={select(
+ 'createOptionPosition',
+ ['first', 'last'],
+ 'last'
+ )}
+ showOptionGroupDivider={showOptionGroupDivider}
+ iconLeft={iconLeft ? createElement(iconLeft) : undefined}
+ {...addMenuPortalProps()}
+ />
+
+
)}
/>
diff --git a/packages/components/inputs/creatable-select-input/src/creatable-select-input.tsx b/packages/components/inputs/creatable-select-input/src/creatable-select-input.tsx
index dd94334c2c..059a35393f 100644
--- a/packages/components/inputs/creatable-select-input/src/creatable-select-input.tsx
+++ b/packages/components/inputs/creatable-select-input/src/creatable-select-input.tsx
@@ -204,6 +204,8 @@ export type TCreatableSelectInputProps = {
menuPortalTarget?: ReactSelectCreatableProps['menuPortalTarget'];
/**
* z-index value for the menu portal
+ *
+ * Use in conjunction with `menuPortalTarget`
*/
menuPortalZIndex: number;
/**
diff --git a/packages/components/inputs/money-input/README.md b/packages/components/inputs/money-input/README.md
index 2416cd6d48..68877f4988 100644
--- a/packages/components/inputs/money-input/README.md
+++ b/packages/components/inputs/money-input/README.md
@@ -66,7 +66,7 @@ export default Example;
| `isAutofocussed` | `boolean` | | | Focus the input on initial render |
| `onChange` | `Function`
[See signature.](#signature-onChange) | | | Called with the event of the input or dropdown when either the currency or the amount have changed. |
| `menuPortalTarget` | `ReactSelectProps['menuPortalTarget']` | | | Dom element to portal the currency select menu to
[Props from React select was used](https://react-select.com/props) |
-| `menuPortalZIndex` | `number` | | `1` | z-index value for the currency select menu portal |
+| `menuPortalZIndex` | `number` | | `1` | z-index value for the currency select menu portal
Use in conjunction with `menuPortalTarget` |
| `menuShouldBlockScroll` | `ReactSelectProps['menuShouldBlockScroll']` | | | whether the menu should block scroll while open
[Props from React select was used](https://react-select.com/props) |
| `hasError` | `boolean` | | | Indicates that input has errors |
| `hasWarning` | `boolean` | | | Control to indicate on the input if there are selected values that are potentially invalid |
diff --git a/packages/components/inputs/money-input/src/money-input.story.js b/packages/components/inputs/money-input/src/money-input.story.js
index 6d4d96ac0d..2e2ea0d9b7 100644
--- a/packages/components/inputs/money-input/src/money-input.story.js
+++ b/packages/components/inputs/money-input/src/money-input.story.js
@@ -10,7 +10,10 @@ import {
select,
} from '@storybook/addon-knobs/react';
import Constraints from '@commercetools-uikit/constraints';
+import Spacings from '@commercetools-uikit/spacings';
import Section from '../../../../../docs/.storybook/decorators/section';
+import NeighbouringStackingContext from '../../../../../docs/.storybook/decorators/neighbouring-stacking-context';
+import { addMenuPortalProps } from '../../../../../docs/.storybook/utils';
import Readme from '../README.md';
import MoneyInput from './money-input';
@@ -57,37 +60,41 @@ class MoneyInputStory extends Component {
return (
<>
- {
- action('onChange')(event);
+
+ {
+ action('onChange')(event);
- if (event.target.name.endsWith('.amount')) {
- this.setState({ amount: event.target.value });
- }
+ if (event.target.name.endsWith('.amount')) {
+ this.setState({ amount: event.target.value });
+ }
- if (event.target.name.endsWith('.currencyCode')) {
- this.setState({ currencyCode: event.target.value });
- }
- }}
- hasError={boolean('hasError', false)}
- hasWarning={boolean('hasWarning', false)}
- horizontalConstraint={select(
- 'horizontalConstraint',
- Constraints.getAcceptedMaxPropValues(3),
- 7
- )}
- hasHighPrecisionBadge={boolean('hasHighPrecisionBadge', false)}
- />
+ if (event.target.name.endsWith('.currencyCode')) {
+ this.setState({ currencyCode: event.target.value });
+ }
+ }}
+ hasError={boolean('hasError', false)}
+ hasWarning={boolean('hasWarning', false)}
+ horizontalConstraint={select(
+ 'horizontalConstraint',
+ Constraints.getAcceptedMaxPropValues(3),
+ 7
+ )}
+ hasHighPrecisionBadge={boolean('hasHighPrecisionBadge', false)}
+ {...addMenuPortalProps()}
+ />
+
+
diff --git a/packages/components/inputs/money-input/src/money-input.tsx b/packages/components/inputs/money-input/src/money-input.tsx
index 6df587c788..a5a02d0c4f 100644
--- a/packages/components/inputs/money-input/src/money-input.tsx
+++ b/packages/components/inputs/money-input/src/money-input.tsx
@@ -21,6 +21,7 @@ import Tooltip from '@commercetools-uikit/tooltip';
import {
DropdownIndicator,
createSelectStyles,
+ warnIfMenuPortalPropsAreMissing,
} from '@commercetools-uikit/select-utils';
import { FractionDigitsIcon } from '@commercetools-uikit/icons';
import Constraints from '@commercetools-uikit/constraints';
@@ -492,6 +493,8 @@ type TMoneyInputProps = {
menuPortalTarget?: ReactSelectProps['menuPortalTarget'];
/**
* z-index value for the currency select menu portal
+ *
+ * Use in conjunction with `menuPortalTarget`
*/
menuPortalZIndex?: number;
/**
@@ -561,6 +564,12 @@ const MoneyInput = (props: TMoneyInputProps) => {
);
}
+ warnIfMenuPortalPropsAreMissing({
+ menuPortalZIndex: props.menuPortalZIndex,
+ menuPortalTarget: props.menuPortalTarget,
+ componentName: 'MoneyInput',
+ });
+
const { onFocus } = props;
const handleAmountFocus = useCallback(() => {
if (onFocus)
diff --git a/packages/components/inputs/search-select-input/README.md b/packages/components/inputs/search-select-input/README.md
index 7c51cf2ddb..5e980e29f3 100644
--- a/packages/components/inputs/search-select-input/README.md
+++ b/packages/components/inputs/search-select-input/README.md
@@ -86,7 +86,7 @@ export default Example;
| `noOptionsMessage` | `AsyncProps['noOptionsMessage']` | | | Can be used to render a custom value when there are no options (either because of no search results, or all options have been used, or there were none in the first place). Gets called with `{ inputValue: String }`. `inputValue` will be an empty string when no search text is present.
[Props from React select was used](https://react-select.com/props) |
| `maxMenuHeight` | `AsyncProps['maxMenuHeight']` | | `220` | Maximum height of the menu before scrolling
[Props from React select was used](https://react-select.com/props) |
| `menuPortalTarget` | `AsyncProps['menuPortalTarget']` | | | Dom element to portal the select menu to
[Props from React select was used](https://react-select.com/props) |
-| `menuPortalZIndex` | `number` | | `1` | z-index value for the menu portal |
+| `menuPortalZIndex` | `number` | | `1` | z-index value for the menu portal
Use in conjunction with `menuPortalTarget` |
| `menuShouldBlockScroll` | `AsyncProps['menuShouldBlockScroll']` | | | whether the menu should block scroll while open
[Props from React select was used](https://react-select.com/props) |
| `closeMenuOnSelect` | `AsyncProps['closeMenuOnSelect']` | | | Whether the menu should close after a value is selected. Defaults to `true`.
[Props from React select was used](https://react-select.com/props) |
| `showOptionGroupDivider` | `boolean` | | | Determines if option groups will be separated by a divider |
diff --git a/packages/components/inputs/search-select-input/src/search-select-input.story.js b/packages/components/inputs/search-select-input/src/search-select-input.story.js
index 5316ee055b..f0850f1145 100644
--- a/packages/components/inputs/search-select-input/src/search-select-input.story.js
+++ b/packages/components/inputs/search-select-input/src/search-select-input.story.js
@@ -10,8 +10,11 @@ import {
number,
} from '@storybook/addon-knobs/react';
import Constraints from '@commercetools-uikit/constraints';
+import Spacings from '@commercetools-uikit/spacings';
import { SELECT_DROPDOWN_OPTION_TYPES } from '@commercetools-uikit/select-utils';
import Section from '../../../../../docs/.storybook/decorators/section';
+import NeighbouringStackingContext from '../../../../../docs/.storybook/decorators/neighbouring-stacking-context';
+import { addMenuPortalProps } from '../../../../../docs/.storybook/utils';
import SearchSelectInput from './search-select-input';
import Readme from '../README.md';
@@ -68,7 +71,7 @@ class SearchSelectInputStory extends Component {
key={`${isMulti}`}
defaultValue={isMulti ? [] : undefined}
render={(value, onChange) => (
-
+
+
In this example, our `loadOptions` function uses the data
@@ -125,7 +130,7 @@ class SearchSelectInputStory extends Component {
Data used:
{JSON.stringify(colourOptions, undefined, 2)}
-
+
)}
/>
diff --git a/packages/components/inputs/search-select-input/src/search-select-input.tsx b/packages/components/inputs/search-select-input/src/search-select-input.tsx
index 6faa0a5be6..a39e86bfe3 100644
--- a/packages/components/inputs/search-select-input/src/search-select-input.tsx
+++ b/packages/components/inputs/search-select-input/src/search-select-input.tsx
@@ -7,6 +7,7 @@ import { warning } from '@commercetools-uikit/utils';
import {
CustomSelectInputOption,
SearchIconDropdownIndicator,
+ warnIfMenuPortalPropsAreMissing,
} from '@commercetools-uikit/select-utils';
import messages from './messages';
import { SearchSelectInputWrapper } from './search-select-input.styles';
@@ -171,6 +172,8 @@ export type TSearchSelectInputProps = {
menuPortalTarget?: ReactSelectAsyncProps['menuPortalTarget'];
/**
* z-index value for the menu portal
+ *
+ * Use in conjunction with `menuPortalTarget`
*/
menuPortalZIndex: number;
/**
@@ -280,6 +283,12 @@ const SearchSelectInput = (props: TSearchSelectInputProps) => {
);
}
+ warnIfMenuPortalPropsAreMissing({
+ menuPortalZIndex: props.menuPortalZIndex,
+ menuPortalTarget: props.menuPortalTarget,
+ componentName: 'SearchSelectInput',
+ });
+
const noOptionsMessage =
props.noOptionsMessage ||
(() => intl.formatMessage(messages.noOptionsMessage));
diff --git a/packages/components/inputs/select-input/README.md b/packages/components/inputs/select-input/README.md
index 2cbd9bb176..11df9aeb57 100644
--- a/packages/components/inputs/select-input/README.md
+++ b/packages/components/inputs/select-input/README.md
@@ -84,7 +84,7 @@ export default Example;
| `isSearchable` | `ReactSelectProps['isSearchable']` | | | Whether to enable search functionality
[Props from React select was used](https://react-select.com/props) |
| `maxMenuHeight` | `ReactSelectProps['maxMenuHeight']` | | `220` | Maximum height of the menu before scrolling
[Props from React select was used](https://react-select.com/props) |
| `menuPortalTarget` | `ReactSelectProps['menuPortalTarget']` | | | Dom element to portal the select menu to
[Props from React select was used](https://react-select.com/props) |
-| `menuPortalZIndex` | `number` | | `1` | z-index value for the menu portal |
+| `menuPortalZIndex` | `number` | | `1` | z-index value for the menu portal
Use in conjunction with `menuPortalTarget` |
| `menuShouldBlockScroll` | `ReactSelectProps['menuShouldBlockScroll']` | | | whether the menu should block scroll while open
[Props from React select was used](https://react-select.com/props) |
| `closeMenuOnSelect` | `ReactSelectProps['closeMenuOnSelect']` | | | Whether the menu should close after a value is selected. Defaults to `true`.
[Props from React select was used](https://react-select.com/props) |
| `name` | `ReactSelectProps['name']` | | | Name of the HTML Input (optional - without this, no input will be rendered)
[Props from React select was used](https://react-select.com/props) |
diff --git a/packages/components/inputs/select-input/src/select-input.story.js b/packages/components/inputs/select-input/src/select-input.story.js
index 78d8a56505..49d734d262 100644
--- a/packages/components/inputs/select-input/src/select-input.story.js
+++ b/packages/components/inputs/select-input/src/select-input.story.js
@@ -13,6 +13,8 @@ import Constraints from '@commercetools-uikit/constraints';
import Spacings from '@commercetools-uikit/spacings';
import LinkTo from '@storybook/addon-links/react';
import Section from '../../../../../docs/.storybook/decorators/section';
+import NeighbouringStackingContext from '../../../../../docs/.storybook/decorators/neighbouring-stacking-context';
+import { addMenuPortalProps } from '../../../../../docs/.storybook/utils';
import Readme from '../README.md';
import SelectInput from './select-input';
import * as icons from '../../../icons';
@@ -106,47 +108,51 @@ storiesOf('Components|Inputs/SelectInputs', module)
key={isMulti}
defaultValue={isMulti ? [] : undefined}
render={(value, onChange) => (
- {
- action('onChange')(event, ...args);
- onChange(event.target.value);
- }}
- onFocus={action('onFocus')}
- onInputChange={action('onInputChange')}
- options={options}
- placeholder={text('placeholder', 'Select..')}
- tabIndex={text('tabIndex', '0')}
- tabSelectsValue={boolean('tabSelectsValue', true)}
- value={value}
- showOptionGroupDivider={showOptionGroupDivider}
- iconLeft={iconLeft ? createElement(iconLeft) : undefined}
- />
+
+ {
+ action('onChange')(event, ...args);
+ onChange(event.target.value);
+ }}
+ onFocus={action('onFocus')}
+ onInputChange={action('onInputChange')}
+ options={options}
+ placeholder={text('placeholder', 'Select..')}
+ tabIndex={text('tabIndex', '0')}
+ tabSelectsValue={boolean('tabSelectsValue', true)}
+ value={value}
+ showOptionGroupDivider={showOptionGroupDivider}
+ iconLeft={iconLeft ? createElement(iconLeft) : undefined}
+ {...addMenuPortalProps()}
+ />
+
+
)}
/>
diff --git a/packages/components/inputs/select-input/src/select-input.tsx b/packages/components/inputs/select-input/src/select-input.tsx
index a1f1c7c750..cfc5c7d60d 100644
--- a/packages/components/inputs/select-input/src/select-input.tsx
+++ b/packages/components/inputs/select-input/src/select-input.tsx
@@ -16,6 +16,7 @@ import {
customComponentsWithIcons,
createSelectStyles,
messages,
+ warnIfMenuPortalPropsAreMissing,
} from '@commercetools-uikit/select-utils';
import { filterDataAttributes } from '@commercetools-uikit/utils';
import { useTheme } from '@commercetools-uikit/design-system';
@@ -228,6 +229,8 @@ export type TSelectInputProps = {
menuPortalTarget?: ReactSelectProps['menuPortalTarget'];
/**
* z-index value for the menu portal
+ *
+ * Use in conjunction with `menuPortalTarget`
*/
menuPortalZIndex?: number;
/**
@@ -333,6 +336,12 @@ const SelectInput = (props: TSelectInputProps) => {
const intl = useIntl();
const { isNewTheme } = useTheme();
+ warnIfMenuPortalPropsAreMissing({
+ menuPortalZIndex: props.menuPortalZIndex,
+ menuPortalTarget: props.menuPortalTarget,
+ componentName: 'SelectInput',
+ });
+
const placeholder =
props.placeholder || intl.formatMessage(messages.placeholder);
// Options can be grouped as
diff --git a/packages/components/inputs/select-utils/src/index.ts b/packages/components/inputs/select-utils/src/index.ts
index b651354c85..23ebfd18bf 100644
--- a/packages/components/inputs/select-utils/src/index.ts
+++ b/packages/components/inputs/select-utils/src/index.ts
@@ -8,5 +8,6 @@ export * from './custom-styled-select-options';
export * from './export-types';
export { default as messages } from './messages';
export { default as createSelectStyles } from './create-select-styles';
+export { warnIfMenuPortalPropsAreMissing } from './warning';
export { default as version } from './version';
diff --git a/packages/components/inputs/select-utils/src/warning.ts b/packages/components/inputs/select-utils/src/warning.ts
new file mode 100644
index 0000000000..a18f056004
--- /dev/null
+++ b/packages/components/inputs/select-utils/src/warning.ts
@@ -0,0 +1,22 @@
+import { warning } from '@commercetools-uikit/utils';
+import { type Props as ReactSelectProps } from 'react-select';
+
+const getMessage = (componentName: string) =>
+ `${componentName}: use \`menuPortalZIndex\` in conjunction with \`menuPortalTarget\``;
+
+type TWarnIfMenuPortalPropsAreMissingProps = {
+ menuPortalZIndex?: number;
+ menuPortalTarget?: ReactSelectProps['menuPortalTarget'];
+ componentName: string;
+};
+
+export const warnIfMenuPortalPropsAreMissing = (
+ props: TWarnIfMenuPortalPropsAreMissingProps
+): void => {
+ if (
+ typeof props.menuPortalZIndex !== 'undefined' &&
+ props.menuPortalZIndex !== 1 // 1 is the value passed in default props
+ ) {
+ warning(props.menuPortalTarget, getMessage(props.componentName));
+ }
+};
diff --git a/packages/components/inputs/selectable-search-input/README.md b/packages/components/inputs/selectable-search-input/README.md
index 6d2acff7c3..b1e58258c3 100644
--- a/packages/components/inputs/selectable-search-input/README.md
+++ b/packages/components/inputs/selectable-search-input/README.md
@@ -77,7 +77,7 @@ export default Example;
| `isClearable` | `boolean` | | `true` | Indicates if the input should be cleared when the clear button is clicked.
Defaults to true. |
| `horizontalConstraint` | `union`
Possible values:
`10 , 11 , 12 , 13 , 14 , 15 , 16 , 'scale' , 'auto'` | | `'scale'` | Horizontal size limit of the input fields. |
| `options` | `union`
Possible values:
`TOption[] , TOptionObject[]` | ✅ | | Array of options that populate the select menu |
-| `menuPortalZIndex` | `number` | | `1` | z-index value for the menu portal |
+| `menuPortalZIndex` | `number` | | `1` | z-index value for the menu portal
Use in conjunction with `menuPortalTarget` |
| `menuPortalTarget` | `ReactSelectProps['menuPortalTarget']` | | | Dom element to portal the select menu to
[Props from React select was used](https://react-select.com/props) |
| `menuShouldBlockScroll` | `ReactSelectProps['menuShouldBlockScroll']` | | | whether the menu should block scroll while open
[Props from React select was used](https://react-select.com/props) |
| `onMenuInputChange` | `ReactSelectProps['onInputChange']` | | | Handle change events on the menu input
[Props from React select was used](https://react-select.com/props) |
diff --git a/packages/components/inputs/selectable-search-input/src/selectable-search-input.story.js b/packages/components/inputs/selectable-search-input/src/selectable-search-input.story.js
index 77993e4600..cbaae086e2 100644
--- a/packages/components/inputs/selectable-search-input/src/selectable-search-input.story.js
+++ b/packages/components/inputs/selectable-search-input/src/selectable-search-input.story.js
@@ -3,7 +3,10 @@ import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { withKnobs, boolean, text, select } from '@storybook/addon-knobs/react';
import Constraints from '@commercetools-uikit/constraints';
+import Spacings from '@commercetools-uikit/spacings';
import Section from '../../../../../docs/.storybook/decorators/section';
+import NeighbouringStackingContext from '../../../../../docs/.storybook/decorators/neighbouring-stacking-context';
+import { addMenuPortalProps } from '../../../../../docs/.storybook/utils';
import Readme from '../README.md';
import SelectableSearchInput from './selectable-search-input';
@@ -104,42 +107,46 @@ storiesOf('Components|Inputs', module)
null
)}
>
- {
- action('onChange')(event);
- if (event.target.name.endsWith('.textInput')) {
- setTextInputValue(event.target.value);
- }
- if (event.target.name.endsWith('.dropdown')) {
- setDropdownValue(event.target.value);
- }
- }}
- isAutofocussed={boolean('isAutofocussed', false)}
- isDisabled={boolean('isDisabled', false)}
- isReadOnly={boolean('isReadOnly', false)}
- isClearable={boolean('isClearable', true)}
- showSubmitButton={boolean('showSubmitButton', true)}
- hasError={boolean('hasError', false)}
- hasWarning={boolean('hasWarning', false)}
- placeholder={text('placeholder', 'Placeholder')}
- horizontalConstraint={select(
- 'horizontalConstraint',
- Constraints.getAcceptedMaxPropValues(10),
- 16
- )}
- menuHorizontalConstraint={select(
- 'menuHorizontalConstraint',
- Constraints.getAcceptedMaxPropValues(3, 5),
- 3
- )}
- options={options}
- onSubmit={(submitValues) => {
- alert(JSON.stringify(submitValues));
- }}
- />
+
+ {
+ action('onChange')(event);
+ if (event.target.name.endsWith('.textInput')) {
+ setTextInputValue(event.target.value);
+ }
+ if (event.target.name.endsWith('.dropdown')) {
+ setDropdownValue(event.target.value);
+ }
+ }}
+ isAutofocussed={boolean('isAutofocussed', false)}
+ isDisabled={boolean('isDisabled', false)}
+ isReadOnly={boolean('isReadOnly', false)}
+ isClearable={boolean('isClearable', true)}
+ showSubmitButton={boolean('showSubmitButton', true)}
+ hasError={boolean('hasError', false)}
+ hasWarning={boolean('hasWarning', false)}
+ placeholder={text('placeholder', 'Placeholder')}
+ horizontalConstraint={select(
+ 'horizontalConstraint',
+ Constraints.getAcceptedMaxPropValues(10),
+ 16
+ )}
+ menuHorizontalConstraint={select(
+ 'menuHorizontalConstraint',
+ Constraints.getAcceptedMaxPropValues(3, 5),
+ 3
+ )}
+ options={options}
+ onSubmit={(submitValues) => {
+ alert(JSON.stringify(submitValues));
+ }}
+ {...addMenuPortalProps()}
+ />
+
+
);
});
diff --git a/packages/components/inputs/selectable-search-input/src/selectable-search-input.tsx b/packages/components/inputs/selectable-search-input/src/selectable-search-input.tsx
index 1598f59568..e0506f6c03 100644
--- a/packages/components/inputs/selectable-search-input/src/selectable-search-input.tsx
+++ b/packages/components/inputs/selectable-search-input/src/selectable-search-input.tsx
@@ -18,6 +18,7 @@ import {
filterDataAttributes,
warning,
} from '@commercetools-uikit/utils';
+import { warnIfMenuPortalPropsAreMissing } from '@commercetools-uikit/select-utils';
import {
getClearIconButtonStyles,
getSearchIconButtonStyles,
@@ -150,6 +151,8 @@ export type TSelectableSearchInputProps = {
options: TOption[] | TOptionObject[];
/**
* z-index value for the menu portal
+ *
+ * Use in conjunction with `menuPortalTarget`
*/
menuPortalZIndex?: number;
/**
@@ -251,10 +254,16 @@ const SelectableSearchInput = (props: TSelectableSearchInputProps) => {
if (!props.isReadOnly) {
warning(
typeof props.onChange === 'function',
- 'TextInput: `onChange` is required when is not read only.'
+ 'SelectableSearchInput: `onChange` is required when is not read only.'
);
}
+ warnIfMenuPortalPropsAreMissing({
+ menuPortalZIndex: props.menuPortalZIndex,
+ menuPortalTarget: props.menuPortalTarget,
+ componentName: 'SelectableSearchInput',
+ });
+
const { onFocus, onBlur, name } = props;
const handleTextInputFocus = useCallback(() => {
if (onFocus) {