Use portaling for react-select

This commit is contained in:
IRBorisov 2023-11-29 13:07:55 +03:00
parent 6b8a428f9f
commit 4b77faf98b
6 changed files with 28 additions and 20 deletions

View File

@ -8,13 +8,13 @@ interface SelectMultiProps<
Option, Option,
Group extends GroupBase<Option> = GroupBase<Option> Group extends GroupBase<Option> = GroupBase<Option>
> >
extends Omit<Props<Option, true, Group>, 'theme'> { extends Omit<Props<Option, true, Group>, 'theme' | 'menuPortalTarget'> {
noPortal?: boolean
} }
function SelectMulti< function SelectMulti<Option, Group extends GroupBase<Option> = GroupBase<Option>> ({
Option, noPortal, ...restProps
Group extends GroupBase<Option> = GroupBase<Option> }: SelectMultiProps<Option, Group>) {
> (props: SelectMultiProps<Option, Group>) {
const { darkMode, colors } = useConceptTheme(); const { darkMode, colors } = useConceptTheme();
const themeColors = useMemo( const themeColors = useMemo(
() => !darkMode ? selectLightT : selectDarkT () => !darkMode ? selectLightT : selectDarkT
@ -27,7 +27,6 @@ function SelectMulti<
borderRadius: '0.25rem', borderRadius: '0.25rem',
cursor: isDisabled ? 'not-allowed' : 'pointer' cursor: isDisabled ? 'not-allowed' : 'pointer'
}), }),
option: (styles, { isSelected }) => ({ option: (styles, { isSelected }) => ({
...styles, ...styles,
backgroundColor: isSelected ? colors.bgSelected : styles.backgroundColor, backgroundColor: isSelected ? colors.bgSelected : styles.backgroundColor,
@ -35,6 +34,10 @@ function SelectMulti<
borderWidth: '1px', borderWidth: '1px',
borderColor: colors.border borderColor: colors.border
}), }),
menuPortal: (styles) => ({
...styles,
zIndex: 9999
}),
menuList: (styles) => ({ menuList: (styles) => ({
...styles, ...styles,
padding: '0px' padding: '0px'
@ -50,7 +53,7 @@ function SelectMulti<
}), [colors]); }), [colors]);
return ( return (
<Select <Select isMulti
noOptionsMessage={() => 'Список пуст'} noOptionsMessage={() => 'Список пуст'}
theme={theme => ({ theme={theme => ({
...theme, ...theme,
@ -60,9 +63,9 @@ function SelectMulti<
...themeColors ...themeColors
}, },
})} })}
isMulti menuPortalTarget={!noPortal ? document.body : null}
styles={adjustedStyles} styles={adjustedStyles}
{...props} {...restProps}
/> />
); );
} }

View File

@ -8,13 +8,13 @@ interface SelectSingleProps<
Option, Option,
Group extends GroupBase<Option> = GroupBase<Option> Group extends GroupBase<Option> = GroupBase<Option>
> >
extends Omit<Props<Option, false, Group>, 'theme'> { extends Omit<Props<Option, false, Group>, 'theme' | 'menuPortalTarget'> {
noPortal?: boolean
} }
function SelectSingle< function SelectSingle<Option, Group extends GroupBase<Option> = GroupBase<Option>> ({
Option, noPortal, ...restProps
Group extends GroupBase<Option> = GroupBase<Option> }: SelectSingleProps<Option, Group>) {
> (props: SelectSingleProps<Option, Group>) {
const { darkMode, colors } = useConceptTheme(); const { darkMode, colors } = useConceptTheme();
const themeColors = useMemo( const themeColors = useMemo(
() => !darkMode ? selectLightT : selectDarkT () => !darkMode ? selectLightT : selectDarkT
@ -27,6 +27,10 @@ function SelectSingle<
borderRadius: '0.25rem', borderRadius: '0.25rem',
cursor: isDisabled ? 'not-allowed' : 'pointer' cursor: isDisabled ? 'not-allowed' : 'pointer'
}), }),
menuPortal: (styles) => ({
...styles,
zIndex: 9999
}),
menuList: (styles) => ({ menuList: (styles) => ({
...styles, ...styles,
padding: '0px' padding: '0px'
@ -54,8 +58,9 @@ function SelectSingle<
...themeColors ...themeColors
}, },
})} })}
menuPortalTarget={!noPortal ? document.body : null}
styles={adjustedStyles} styles={adjustedStyles}
{...props} {...restProps}
/> />
); );
} }

View File

@ -16,9 +16,9 @@ interface ConstituentaTabProps {
function ConstituentaTab({state, partialUpdate}: ConstituentaTabProps) { function ConstituentaTab({state, partialUpdate}: ConstituentaTabProps) {
return ( return (
<div className='flex flex-col gap-3'> <div className='flex flex-col gap-3'>
<div className='flex justify-center w-full gap-6'> <div className='flex justify-center w-full gap-3 pr-2'>
<SelectSingle <SelectSingle
className='min-w-[15rem] self-center' className='min-w-[14rem] self-center'
options={SelectorCstType} options={SelectorCstType}
placeholder='Выберите тип' placeholder='Выберите тип'
value={{ value: state.cst_type, label: labelCstType(state.cst_type) }} value={{ value: state.cst_type, label: labelCstType(state.cst_type) }}

View File

@ -249,7 +249,7 @@ function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferen
<Label text='Отсылаемая словоформа'/> <Label text='Отсылаемая словоформа'/>
<SelectMulti <SelectMulti
placeholder='Выберите граммемы' placeholder='Выберите граммемы'
className='flex-grow h-full z-modal-top' className='flex-grow h-full'
menuPlacement='top' menuPlacement='top'
options={gramOptions} options={gramOptions}
value={selectedGrams} value={selectedGrams}

View File

@ -269,7 +269,7 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
/> />
</div> </div>
<SelectMulti <SelectMulti
className='z-modal-top min-w-[20rem] max-w-[20rem] h-full flex-grow' className='min-w-[20rem] max-w-[20rem] h-full flex-grow'
options={options} options={options}
placeholder='Выберите граммемы' placeholder='Выберите граммемы'

View File

@ -51,7 +51,7 @@ function DlgRenameCst({ hideWindow, initial, onRename }: DlgRenameCstProps) {
<div className='flex items-center gap-4 px-2 my-2 h-fit min-w-[25rem]'> <div className='flex items-center gap-4 px-2 my-2 h-fit min-w-[25rem]'>
<SelectSingle <SelectSingle
placeholder='Выберите тип' placeholder='Выберите тип'
className='min-w-[14rem] self-center z-modal-top' className='min-w-[14rem] self-center'
options={SelectorCstType} options={SelectorCstType}
value={{ value={{
value: cstData.cst_type, value: cstData.cst_type,