diff --git a/packages/grafana-ui/src/components/Select/SelectBase.tsx b/packages/grafana-ui/src/components/Select/SelectBase.tsx index c6e22c66e85..bcc267afdb0 100644 --- a/packages/grafana-ui/src/components/Select/SelectBase.tsx +++ b/packages/grafana-ui/src/components/Select/SelectBase.tsx @@ -6,7 +6,7 @@ import { default as AsyncCreatable } from 'react-select/async-creatable'; import { Icon } from '../Icon/Icon'; import { Spinner } from '../Spinner/Spinner'; -import resetSelectStyles from './resetSelectStyles'; +import { useCustomSelectStyles } from './resetSelectStyles'; import { SelectMenu, SelectMenuOptions } from './SelectMenu'; import { IndicatorsContainer } from './IndicatorsContainer'; import { ValueContainer } from './ValueContainer'; @@ -147,6 +147,7 @@ export function SelectBase({ const reactSelectRef = useRef<{ controlRef: HTMLElement }>(null); const [closeToBottom, setCloseToBottom] = useState(false); + const selectStyles = useCustomSelectStyles(theme, width); // Infer the menu position for asynchronously loaded options. menuPlacement="auto" doesn't work when the menu is // automatically opened when the component is created (it happens in SegmentSelect by setting menuIsOpen={true}). @@ -339,29 +340,7 @@ export function SelectBase({ SelectContainer, ...components, }} - styles={{ - ...resetSelectStyles(theme), - menuPortal: (base: any) => ({ - ...base, - zIndex: theme.zIndex.portal, - }), - //These are required for the menu positioning to function - menu: ({ top, bottom, position }: any) => ({ - top, - bottom, - position, - minWidth: '100%', - zIndex: theme.zIndex.dropdown, - }), - container: () => ({ - width: width ? theme.spacing(width) : '100%', - display: width === 'auto' ? 'inline-flex' : 'flex', - }), - option: (provided: any, state: any) => ({ - ...provided, - opacity: state.isDisabled ? 0.5 : 1, - }), - }} + styles={selectStyles} className={className} {...commonSelectProps} {...creatableProps} diff --git a/packages/grafana-ui/src/components/Select/resetSelectStyles.ts b/packages/grafana-ui/src/components/Select/resetSelectStyles.ts index edcc3b52b97..9c90d1d701e 100644 --- a/packages/grafana-ui/src/components/Select/resetSelectStyles.ts +++ b/packages/grafana-ui/src/components/Select/resetSelectStyles.ts @@ -1,4 +1,5 @@ import { GrafanaTheme2 } from '@grafana/data'; +import { useMemo } from 'react'; import { CSSObjectWithLabel } from 'react-select'; export default function resetSelectStyles(theme: GrafanaTheme2) { @@ -40,3 +41,37 @@ export default function resetSelectStyles(theme: GrafanaTheme2) { valueContainer: () => ({}), }; } + +export function useCustomSelectStyles(theme: GrafanaTheme2, width: number | string | undefined) { + return useMemo(() => { + return { + ...resetSelectStyles(theme), + menuPortal: (base: any) => { + // Would like to correct top position when menu is placed bottom, but have props are not sent to this style function. + // Only state is. https://github.com/JedWatson/react-select/blob/master/packages/react-select/src/components/Menu.tsx#L605 + return { + ...base, + zIndex: theme.zIndex.portal, + }; + }, + //These are required for the menu positioning to function + menu: ({ top, bottom, position }: any) => { + return { + top, + bottom, + position, + minWidth: '100%', + zIndex: theme.zIndex.dropdown, + }; + }, + container: () => ({ + width: width ? theme.spacing(width) : '100%', + display: width === 'auto' ? 'inline-flex' : 'flex', + }), + option: (provided: any, state: any) => ({ + ...provided, + opacity: state.isDisabled ? 0.5 : 1, + }), + }; + }, [theme, width]); +}