MUI自定义Tooltip点击内部单选按钮后关闭的问题求助
问题描述
在React应用中使用自定义MUI Tooltip组件时遇到问题:Tooltip内包含一组单选按钮,每次点击单选按钮时Tooltip都会关闭,但希望它保持打开状态以便用户进行多次选择。尝试在handleChange函数中使用event.stopPropagation()阻止事件冒泡,首次点击有效,但多次点击后Tooltip仍会关闭。
原组件代码
import React from 'react'; import styled from '@emotion/styled'; import { Box, FormControlLabel, Grid, Radio, RadioGroup, Tooltip, TooltipProps, Typography, tooltipClasses,} from '@mui/material'; const CustomWidthTooltip = styled(({ className, ...props }: TooltipProps) => ( <Tooltip {...props} classes={{ popper: className }} /> ))({ [`& .${tooltipClasses.tooltip}`]: { maxWidth: 750, maxHeight: 250, overflowY: 'auto', border: '1px solid #dadde9', borderRadius: 10, backgroundColor: 'white', boxShadow: '10px 10px 20px rgba(0, 0, 0, 0.5)', '&::-webkit-scrollbar': { width: '0.5em', }, '&::-webkit-scrollbar-thumb': { backgroundColor: 'grey', }, '&::-webkit-scrollbar-track': { backgroundColor: 'white', }, }, }); interface ShipModelProps { handleCellClick: () => void; howManyToShip: number; } const ShipModel = ({ handleCellClick, howManyToShip }: ShipModelProps) => { const [selectedValue, setSelectedValue] = React.useState('Ocean'); const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { event.stopPropagation(); setSelectedValue(event.target.value); }; const tooltipContent = ( <Box component={'div'} className="text-black flex flex-col items-center" width={300}> <h1 className="text-lg font-bold">Ship Model</h1> <Box component={'div'}> <h4 className="text-sm opacity-50">Shipment Type</h4> <RadioGroup aria-label="ship-model" value={selectedValue} onChange={handleChange}> <Grid container spacing={2}> <Grid item xs={6}> <FormControlLabel value="Ocean" control={<Radio />} label={<Typography variant="body2">Ocean</Typography>} /> <FormControlLabel value="Air" control={<Radio />} label={<Typography variant="body2">Air</Typography>} /> </Grid> <Grid item xs={6}> <FormControlLabel value="Ocean Express" control={<Radio />} label={<Typography variant="body2">Ocean Express</Typography>} /> <FormControlLabel value="Air Express" control={<Radio />} label={<Typography variant="body2">Air Express</Typography>} /> </Grid> </Grid> </RadioGroup> </Box> <Box component={'div'} className="border-t-2" width={'100%'}> <h4 className="text-sm opacity-50">Optional</h4> <FormControlLabel control={<Radio />} label={<Typography variant="body2">Optional</Typography>} /> </Box> </Box> ); return ( <CustomWidthTooltip title={tooltipContent} onClick={handleCellClick}> <Box component={'div'}> {howManyToShip} </Box> </CustomWidthTooltip> ); }; export default ShipModel;
解决方案
要实现点击单选按钮时Tooltip保持打开的效果,可通过以下两种关键修改达成:
1. 启用Tooltip的interactive属性
MUI Tooltip提供了interactive属性,设置为true后,点击Tooltip内部元素时不会自动关闭Tooltip,这是官方推荐的解决方案:
<CustomWidthTooltip title={tooltipContent} onClick={handleCellClick} interactive={true} // 添加此属性 > <Box component={'div'}> {howManyToShip} </Box> </CustomWidthTooltip>
2. 阻止Tooltip内容容器的事件冒泡
仅依赖interactive可能不足以覆盖所有场景(比如点击单选按钮的标签区域),给Tooltip内容的最外层容器添加onClick事件阻止冒泡,确保内部所有点击事件都不会传递到Tooltip:
const tooltipContent = ( <Box component={'div'} className="text-black flex flex-col items-center" width={300} onClick={(e) => e.stopPropagation()} // 添加此事件 > {/* 原有内容 */} </Box> );
完整修改后的组件
import React from 'react'; import styled from '@emotion/styled'; import { Box, FormControlLabel, Grid, Radio, RadioGroup, Tooltip, TooltipProps, Typography, tooltipClasses,} from '@mui/material'; const CustomWidthTooltip = styled(({ className, ...props }: TooltipProps) => ( <Tooltip {...props} classes={{ popper: className }} /> ))({ [`& .${tooltipClasses.tooltip}`]: { maxWidth: 750, maxHeight: 250, overflowY: 'auto', border: '1px solid #dadde9', borderRadius: 10, backgroundColor: 'white', boxShadow: '10px 10px 20px rgba(0, 0, 0, 0.5)', '&::-webkit-scrollbar': { width: '0.5em', }, '&::-webkit-scrollbar-thumb': { backgroundColor: 'grey', }, '&::-webkit-scrollbar-track': { backgroundColor: 'white', }, }, }); interface ShipModelProps { handleCellClick: () => void; howManyToShip: number; } const ShipModel = ({ handleCellClick, howManyToShip }: ShipModelProps) => { const [selectedValue, setSelectedValue] = React.useState('Ocean'); const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { setSelectedValue(event.target.value); }; const tooltipContent = ( <Box component={'div'} className="text-black flex flex-col items-center" width={300} onClick={(e) => e.stopPropagation()} > <h1 className="text-lg font-bold">Ship Model</h1> <Box component={'div'}> <h4 className="text-sm opacity-50">Shipment Type</h4> <RadioGroup aria-label="ship-model" value={selectedValue} onChange={handleChange}> <Grid container spacing={2}> <Grid item xs={6}> <FormControlLabel value="Ocean" control={<Radio />} label={<Typography variant="body2">Ocean</Typography>} /> <FormControlLabel value="Air" control={<Radio />} label={<Typography variant="body2">Air</Typography>} /> </Grid> <Grid item xs={6}> <FormControlLabel value="Ocean Express" control={<Radio />} label={<Typography variant="body2">Ocean Express</Typography>} /> <FormControlLabel value="Air Express" control={<Radio />} label={<Typography variant="body2">Air Express</Typography>} /> </Grid> </Grid> </RadioGroup> </Box> <Box component={'div'} className="border-t-2" width={'100%'}> <h4 className="text-sm opacity-50">Optional</h4> <FormControlLabel control={<Radio />} label={<Typography variant="body2">Optional</Typography>} /> </Box> </Box> ); return ( <CustomWidthTooltip title={tooltipContent} onClick={handleCellClick} interactive={true} > <Box component={'div'}> {howManyToShip} </Box> </CustomWidthTooltip> ); }; export default ShipModel;
内容的提问来源于stack exchange,提问作者Roni Jack Vituli
相关产品推荐
相关产品推荐

