Select: Memoize custom styles (#43070)

This commit is contained in:
Torkel Ödegaard 2021-12-15 13:33:35 +01:00 committed by GitHub
parent 566907e617
commit 6724c42e84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 24 deletions

View File

@ -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<T>({
const reactSelectRef = useRef<{ controlRef: HTMLElement }>(null);
const [closeToBottom, setCloseToBottom] = useState<boolean>(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<T>({
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}

View File

@ -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]);
}