mirror of
https://github.com/labring/sealos.git
synced 2026-08-31 02:06:00 +08:00
fix(applaunchpad): constrain route service menu height (#7037)
* fix(applaunchpad): constrain route service menu height * fix(applaunchpad): let route service menu escape modal clipping * fix(applaunchpad): render route service menu in portal
This commit is contained in:
@@ -10,9 +10,10 @@ import {
|
||||
useDisclosure,
|
||||
useOutsideClick,
|
||||
MenuButton,
|
||||
Flex
|
||||
Flex,
|
||||
Portal
|
||||
} from '@chakra-ui/react';
|
||||
import type { BoxProps, ButtonProps } from '@chakra-ui/react';
|
||||
import type { BoxProps, ButtonProps, MenuListProps, MenuProps } from '@chakra-ui/react';
|
||||
import { ChevronDownIcon } from '@chakra-ui/icons';
|
||||
|
||||
interface Props extends ButtonProps {
|
||||
@@ -27,6 +28,9 @@ interface Props extends ButtonProps {
|
||||
onchange?: (val: string) => void;
|
||||
isInvalid?: boolean;
|
||||
boxStyle?: BoxProps;
|
||||
menuProps?: Omit<MenuProps, 'children'>;
|
||||
menuListProps?: MenuListProps;
|
||||
menuListPortal?: boolean;
|
||||
}
|
||||
|
||||
const MySelect = (
|
||||
@@ -39,6 +43,9 @@ const MySelect = (
|
||||
onchange,
|
||||
isInvalid,
|
||||
boxStyle,
|
||||
menuProps,
|
||||
menuListProps,
|
||||
menuListPortal,
|
||||
...props
|
||||
}: Props,
|
||||
selectRef: any
|
||||
@@ -50,6 +57,7 @@ const MySelect = (
|
||||
useOutsideClick({
|
||||
ref: SelectRef,
|
||||
handler: () => {
|
||||
if (menuListPortal) return;
|
||||
onClose();
|
||||
}
|
||||
});
|
||||
@@ -65,8 +73,56 @@ const MySelect = (
|
||||
return foundItem;
|
||||
}, [list, value]);
|
||||
|
||||
const menuList = (
|
||||
<MenuList
|
||||
minW={(() => {
|
||||
const w = ref.current?.clientWidth;
|
||||
if (w) {
|
||||
return `${w}px !important`;
|
||||
}
|
||||
return Array.isArray(width)
|
||||
? width.map((item) => `${item} !important`)
|
||||
: `${width} !important`;
|
||||
})()}
|
||||
p={'6px'}
|
||||
borderRadius={'base'}
|
||||
border={'1px solid #E8EBF0'}
|
||||
boxShadow={
|
||||
'0px 4px 10px 0px rgba(19, 51, 107, 0.10), 0px 0px 1px 0px rgba(19, 51, 107, 0.10)'
|
||||
}
|
||||
zIndex={99}
|
||||
overflow={'overlay'}
|
||||
maxH={'300px'}
|
||||
{...menuListProps}
|
||||
>
|
||||
{list.map((item) => (
|
||||
<MenuItem
|
||||
key={item.value}
|
||||
{...(value === item.value
|
||||
? {
|
||||
color: 'brightBlue.600'
|
||||
}
|
||||
: {})}
|
||||
borderRadius={'4px'}
|
||||
_hover={{
|
||||
bg: 'rgba(17, 24, 36, 0.05)',
|
||||
color: 'brightBlue.600'
|
||||
}}
|
||||
p={'6px'}
|
||||
onClick={() => {
|
||||
if (onchange && value !== item.value) {
|
||||
onchange(item.value);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Box>{item.label}</Box>
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuList>
|
||||
);
|
||||
|
||||
return (
|
||||
<Menu autoSelect={false} isOpen={isOpen} onOpen={onOpen} onClose={onClose}>
|
||||
<Menu autoSelect={false} isOpen={isOpen} onOpen={onOpen} onClose={onClose} {...menuProps}>
|
||||
<Box
|
||||
ref={SelectRef}
|
||||
position={'relative'}
|
||||
@@ -111,50 +167,7 @@ const MySelect = (
|
||||
<Flex justifyContent={'flex-start'}>{activeMenu ? activeMenu.label : placeholder}</Flex>
|
||||
</MenuButton>
|
||||
|
||||
<MenuList
|
||||
minW={(() => {
|
||||
const w = ref.current?.clientWidth;
|
||||
if (w) {
|
||||
return `${w}px !important`;
|
||||
}
|
||||
return Array.isArray(width)
|
||||
? width.map((item) => `${item} !important`)
|
||||
: `${width} !important`;
|
||||
})()}
|
||||
p={'6px'}
|
||||
borderRadius={'base'}
|
||||
border={'1px solid #E8EBF0'}
|
||||
boxShadow={
|
||||
'0px 4px 10px 0px rgba(19, 51, 107, 0.10), 0px 0px 1px 0px rgba(19, 51, 107, 0.10)'
|
||||
}
|
||||
zIndex={99}
|
||||
overflow={'overlay'}
|
||||
maxH={'300px'}
|
||||
>
|
||||
{list.map((item) => (
|
||||
<MenuItem
|
||||
key={item.value}
|
||||
{...(value === item.value
|
||||
? {
|
||||
color: 'brightBlue.600'
|
||||
}
|
||||
: {})}
|
||||
borderRadius={'4px'}
|
||||
_hover={{
|
||||
bg: 'rgba(17, 24, 36, 0.05)',
|
||||
color: 'brightBlue.600'
|
||||
}}
|
||||
p={'6px'}
|
||||
onClick={() => {
|
||||
if (onchange && value !== item.value) {
|
||||
onchange(item.value);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Box>{item.label}</Box>
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuList>
|
||||
{menuListPortal ? <Portal>{menuList}</Portal> : menuList}
|
||||
</Box>
|
||||
</Menu>
|
||||
);
|
||||
|
||||
@@ -25,7 +25,7 @@ const routeRuleFieldGapPx = 19;
|
||||
const routeRuleFieldWidth = `${routeRuleFieldWidthPx}px`;
|
||||
const routeRuleFieldGap = `${routeRuleFieldGapPx}px`;
|
||||
const routeRuleContentWidth = `${routeRuleFieldWidthPx * 2 + routeRuleFieldGapPx}px`;
|
||||
const routeRuleSelectDropdownGap = '8px';
|
||||
const routeRuleBackendSelectMenuMaxH = '220px';
|
||||
const routeRulesScrollbarWidth = '6px';
|
||||
|
||||
type RouteRulesForm = {
|
||||
@@ -346,15 +346,20 @@ export default function RouteRulesModal({
|
||||
routes?.[index]?.servicePort || defaultServicePort
|
||||
)}
|
||||
list={backendServiceOptions}
|
||||
boxStyle={{
|
||||
sx: {
|
||||
'& [aria-haspopup="menu"][aria-expanded="true"] + .chakra-menu__menu-list':
|
||||
{
|
||||
position: 'static',
|
||||
transform: 'none !important',
|
||||
mt: routeRuleSelectDropdownGap
|
||||
}
|
||||
}
|
||||
menuProps={{
|
||||
strategy: 'fixed',
|
||||
gutter: 8,
|
||||
flip: true,
|
||||
preventOverflow: true,
|
||||
boundary: 'clippingParents'
|
||||
}}
|
||||
menuListPortal
|
||||
menuListProps={{
|
||||
zIndex: 1500,
|
||||
maxH: routeRuleBackendSelectMenuMaxH,
|
||||
overflowY: 'auto',
|
||||
overflowX: 'hidden',
|
||||
overscrollBehavior: 'contain'
|
||||
}}
|
||||
onchange={(val: string) => {
|
||||
const backendService = parseBackendServiceValue(val);
|
||||
|
||||
Reference in New Issue
Block a user