Commit b4a5a76d by siigure Committed by GitHub

feat: tooltip (#7087)

* feat: tooltip

* fix: 优化 tooltip 展示逻辑并修复 header UI 布局

* fix: 优化名称 tooltip 溢出展示

* submodule

---------

Co-authored-by: archer <545436317@qq.com>
parent d38bf227
......@@ -10,3 +10,4 @@ description: 'FastGPT V4.15.0-beta5 Release Notes'
## ⚙️ Improvements
1. HTML output now automatically switches to preview mode after generation, reducing the need to open the preview manually.
2. Improved long-name display for apps, datasets, files, and folders: names are truncated when they exceed the available width, and the full name is shown when hovering over the name.
......@@ -10,3 +10,4 @@ description: 'FastGPT V4.15.0-beta5 更新说明'
## ⚙️ 优化
1. HTML 输出后自动切换为预览,减少手动打开预览的操作。
2. 优化应用、知识库、文件和文件夹等长名称展示:超出宽度时自动省略,并在 hover 名称时展示完整内容。
......@@ -130,39 +130,11 @@
"content/guide/workspace/team/team_roles_permissions.en.mdx": "2026-05-07T15:06:40+08:00",
"content/guide/workspace/team/team_roles_permissions.mdx": "2026-05-07T15:06:40+08:00",
"content/openapi/app.en.mdx": "2026-05-29T19:31:16+08:00",
"content/openapi/app.mdx": "2026-05-29T19:31:16+08:00",
"content/openapi/chat.en.mdx": "2026-05-29T19:31:16+08:00",
"content/openapi/chat.mdx": "2026-05-29T19:31:16+08:00",
"content/openapi/dataset.en.mdx": "2026-05-29T19:31:16+08:00",
"content/openapi/dataset.mdx": "2026-05-29T19:31:16+08:00",
"content/openapi/index.en.mdx": "2026-04-26T21:08:47+08:00",
"content/openapi/index.mdx": "2026-04-26T21:08:47+08:00",
"content/openapi/intro.en.mdx": "2026-05-29T21:03:14+08:00",
"content/openapi/intro.mdx": "2026-05-29T21:03:14+08:00",
"content/openapi/share.en.mdx": "2026-04-26T21:08:47+08:00",
"content/openapi/share.mdx": "2026-04-26T21:08:47+08:00",
"content/plugin/index.en.mdx": "2026-06-04T16:10:15+08:00",
"content/plugin/index.mdx": "2026-06-04T16:10:15+08:00",
"content/plugin/intro.en.mdx": "2026-06-09T16:03:58+08:00",
"content/plugin/intro.mdx": "2026-06-09T16:03:58+08:00",
"content/plugin/model-presets.en.mdx": "2026-06-04T16:10:15+08:00",
"content/plugin/model-presets.mdx": "2026-06-04T16:10:15+08:00",
"content/plugin/system-tool-development.en.mdx": "2026-06-09T16:03:58+08:00",
"content/plugin/system-tool-development.mdx": "2026-06-09T16:03:58+08:00",
"content/self-host/config/env.en.mdx": "2026-06-10T19:02:59+08:00",
"content/self-host/config/env.mdx": "2026-06-10T19:02:59+08:00",
"content/self-host/config/json.en.mdx": "2026-05-25T11:21:30+08:00",
"content/self-host/config/json.mdx": "2026-05-25T11:21:30+08:00",
"content/self-host/config/model/intro.en.mdx": "2026-06-04T16:10:15+08:00",
"content/self-host/config/model/intro.mdx": "2026-06-04T16:10:15+08:00",
"content/self-host/config/model/minimax.en.mdx": "2026-06-03T10:40:17+08:00",
"content/self-host/config/model/minimax.mdx": "2026-06-03T10:40:17+08:00",
"content/self-host/config/model/siliconCloud.en.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/config/model/siliconCloud.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/config/object-storage.en.mdx": "2026-05-21T11:24:48+08:00",
"content/self-host/config/object-storage.mdx": "2026-05-21T11:24:48+08:00",
"content/self-host/config/signoz.en.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/config/signoz.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/custom-models/bge-rerank.en.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/custom-models/bge-rerank.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/custom-models/chatglm2-m3e.en.mdx": "2026-04-26T21:08:47+08:00",
......@@ -193,8 +165,8 @@
"content/self-host/migration/docker_db.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/migration/docker_mongo.en.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/migration/docker_mongo.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/troubleshooting/attention.en.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/troubleshooting/attention.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/troubleshooting/attention.en.mdx": "2026-06-12T12:19:25+08:00",
"content/self-host/troubleshooting/attention.mdx": "2026-06-12T12:19:25+08:00",
"content/self-host/troubleshooting/faq.en.mdx": "2026-05-12T18:16:10+08:00",
"content/self-host/troubleshooting/faq.mdx": "2026-05-12T18:16:10+08:00",
"content/self-host/troubleshooting/methods.en.mdx": "2026-04-26T21:08:47+08:00",
......
import React from 'react';
import { Tooltip, type TooltipProps } from '@chakra-ui/react';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { Tooltip, type TooltipProps, useMergeRefs } from '@chakra-ui/react';
interface Props extends TooltipProps {}
const defaultTooltipProps = {
className: 'chakra-tooltip',
bg: 'white',
arrowShadowColor: 'rgba(0,0,0,0.05)',
hasArrow: true,
arrowSize: 12,
offset: [-15, 15] as [number, number],
color: 'myGray.800',
px: 4,
py: 2,
borderRadius: '8px',
whiteSpace: 'pre-wrap',
boxShadow: '1px 1px 10px rgba(0,0,0,0.2)'
} satisfies Omit<TooltipProps, 'children'>;
interface Props extends TooltipProps {
/**
* 仅当触发元素横向内容溢出时展示 Tooltip,用于替代外部按字数估算的判断。
*/
showOnlyWhenOverflow?: boolean;
}
/**
* 为“仅溢出时展示”模式注入测量 ref,并保留原子元素上的 ref 与 hover/focus 事件。
* 普通 Tooltip 不走这段逻辑,避免全局 tooltip 都承担 DOM 测量成本。
*/
const useOverflowTooltipTrigger = ({
children,
enabled
}: {
children: React.ReactNode;
enabled: boolean;
}) => {
const triggerRef = useRef<HTMLElement | null>(null);
const [isOverflow, setIsOverflow] = useState(false);
const checkOverflow = useCallback(() => {
if (!enabled) {
setIsOverflow(false);
return;
}
const target = triggerRef.current;
if (!target) {
setIsOverflow(false);
return;
}
setIsOverflow(
target.scrollWidth > target.clientWidth || target.scrollHeight > target.clientHeight
);
}, [enabled]);
useEffect(() => {
if (!enabled) return;
const frame = window.requestAnimationFrame(checkOverflow);
const target = triggerRef.current;
if (!target) {
return () => window.cancelAnimationFrame(frame);
}
const observer =
typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(checkOverflow);
observer?.observe(target);
window.addEventListener('resize', checkOverflow);
return () => {
window.cancelAnimationFrame(frame);
observer?.disconnect();
window.removeEventListener('resize', checkOverflow);
};
}, [checkOverflow, children, enabled]);
const setTriggerRef = useCallback(
(node: HTMLElement | null) => {
triggerRef.current = node;
checkOverflow();
},
[checkOverflow]
);
const triggerElement = React.isValidElement(children) ? children : null;
const childOriginRef = triggerElement
? ((triggerElement as any).ref as React.Ref<HTMLElement> | undefined)
: undefined;
const triggerElementProps = triggerElement?.props as
| {
onMouseEnter?: React.MouseEventHandler;
onFocus?: React.FocusEventHandler;
}
| undefined;
const mergedRef = useMergeRefs(childOriginRef, setTriggerRef);
if (!enabled) {
return {
isOverflow: false,
triggerChildren: children
};
}
return {
isOverflow,
triggerChildren: triggerElement ? (
React.cloneElement(triggerElement as React.ReactElement<any>, {
ref: mergedRef,
onMouseEnter: (event: React.MouseEvent) => {
checkOverflow();
triggerElementProps?.onMouseEnter?.(event);
},
onFocus: (event: React.FocusEvent) => {
checkOverflow();
triggerElementProps?.onFocus?.(event);
}
})
) : (
<span
ref={setTriggerRef}
style={{ display: 'inline-block', maxWidth: '100%' }}
onMouseEnter={checkOverflow}
onFocus={checkOverflow}
>
{children}
</span>
)
};
};
const MyTooltip = ({
children,
shouldWrapChildren = true,
showOnlyWhenOverflow = false,
isDisabled,
...props
}: Props) => {
const { isOverflow, triggerChildren } = useOverflowTooltipTrigger({
children,
enabled: showOnlyWhenOverflow
});
const finalChildren = showOnlyWhenOverflow ? triggerChildren : children;
const finalShouldWrapChildren = showOnlyWhenOverflow ? false : shouldWrapChildren;
const finalIsDisabled = isDisabled || (showOnlyWhenOverflow && !isOverflow);
const MyTooltip = ({ children, shouldWrapChildren = true, ...props }: Props) => {
return (
<Tooltip
className="chakra-tooltip"
bg={'white'}
arrowShadowColor={'rgba(0,0,0,0.05)'}
hasArrow
arrowSize={12}
offset={[-15, 15]}
color={'myGray.800'}
px={4}
py={2}
borderRadius={'8px'}
whiteSpace={'pre-wrap'}
boxShadow={'1px 1px 10px rgba(0,0,0,0.2)'}
shouldWrapChildren={shouldWrapChildren}
{...defaultTooltipProps}
shouldWrapChildren={finalShouldWrapChildren}
isDisabled={finalIsDisabled}
{...props}
>
{children}
{finalChildren}
</Tooltip>
);
};
......
Subproject commit 0f49c306a09ba34ea427643dd81d7939cd80985f
Subproject commit cd209c713a0263acb08492738c2c4265d8dc37b9
......@@ -110,9 +110,6 @@ const FolderPath = (props: {
}
};
const shouldTruncate = !isLast && item.parentName.length > 10;
const displayName = shouldTruncate ? `${item.parentName.slice(0, 10)}...` : item.parentName;
const pathBox = (
<Box
fontSize={['xs', fontSize || 'sm']}
......@@ -133,13 +130,15 @@ const FolderPath = (props: {
})}
{...(isLast && !forbidLastClick && clickStyles)}
>
{displayName}
{item.parentName}
</Box>
);
return (
<Flex key={item.parentId || index} alignItems={'center'}>
{shouldTruncate ? <MyTooltip label={item.parentName}>{pathBox}</MyTooltip> : pathBox}
<MyTooltip label={item.parentName} showOnlyWhenOverflow>
{pathBox}
</MyTooltip>
{!isLast && <MyIcon name={'common/line'} color={'myGray.500'} mx={1} width={'5px'} />}
</Flex>
);
......
......@@ -29,6 +29,7 @@ import FolderPath from '@/components/common/folder/Path';
import EmptyTip from '@fastgpt/web/components/common/EmptyTip';
import QuickCreateDatasetModal from '@/pageComponents/app/detail/components/QuickCreateDatasetModal';
import { useUserStore } from '@/web/support/user/useUserStore';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
// Dataset selection modal component
export const DatasetSelectModal = ({
......@@ -306,14 +307,29 @@ export const DatasetSelectModal = ({
</Box>
{/* Avatar */}
<Avatar src={item.avatar} w={7} h={7} borderRadius="sm" ml={3} mr={2.5} />
<Avatar
src={item.avatar}
w={7}
h={7}
borderRadius="sm"
ml={3}
mr={2.5}
flexShrink={0}
/>
{/* Name and type */}
<Box flex={1} minW={0}>
<Box fontSize="sm" color={'myGray.900'} lineHeight={1}>
{item.name}
</Box>
<Box fontSize="xs" color="myGray.500">
<MyTooltip label={item.name} showOnlyWhenOverflow>
<Box
fontSize="sm"
color={'myGray.900'}
lineHeight={1.2}
className="textEllipsis"
>
{item.name}
</Box>
</MyTooltip>
<Box fontSize="xs" color="myGray.500" className="textEllipsis">
{item.type === DatasetTypeEnum.folder ? (
<>{t('common:Folder')}</>
) : (
......@@ -408,9 +424,20 @@ export const DatasetSelectModal = ({
cursor="pointer"
alignItems="center"
>
<Avatar src={item.avatar} w={6} h={6} borderRadius="sm" mr={3} />
<Box flex={1} minW={0}>
<Box fontSize="sm">{item.name}</Box>
<Avatar
src={item.avatar}
w={6}
h={6}
borderRadius="sm"
mr={3}
flexShrink={0}
/>
<Box flex={1} minW={0} mr={2}>
<MyTooltip label={item.name} showOnlyWhenOverflow>
<Box fontSize="sm" className="textEllipsis" lineHeight={1.2}>
{item.name}
</Box>
</MyTooltip>
</Box>
<IconButton
aria-label="Remove"
......@@ -418,6 +445,7 @@ export const DatasetSelectModal = ({
size="xs"
variant="ghost"
color="black"
flexShrink={0}
_hover={{ bg: 'myGray.200' }}
onClick={() =>
setSelectedDatasets((prev) =>
......
......@@ -51,36 +51,35 @@ const RawSourceBox = ({
teamId,
teamToken
});
const displaySourceName = sourceName || t('common:unknow_source');
return (
<MyTooltip
label={canPreview ? t('file:click_to_view_raw_source') : ''}
shouldWrapChildren={false}
<Box
color={'myGray.900'}
fontWeight={'medium'}
display={'inline-flex'}
whiteSpace={'nowrap'}
{...(canPreview
? {
cursor: 'pointer',
textDecoration: 'underline',
onClick: read
}
: {})}
{...props}
>
<Box
color={'myGray.900'}
fontWeight={'medium'}
display={'inline-flex'}
whiteSpace={'nowrap'}
{...(canPreview
? {
cursor: 'pointer',
textDecoration: 'underline',
onClick: read
}
: {})}
{...props}
>
<MyIcon name={icon as any} w={['1rem', '1.25rem']} mr={2} />
<MyIcon name={icon as any} w={['1rem', '1.25rem']} mr={2} flexShrink={0} />
<MyTooltip label={displaySourceName} showOnlyWhenOverflow>
<Box
maxW={['200px', '300px']}
className={props.className ?? 'textEllipsis'}
wordBreak={'break-all'}
minW={0}
>
{sourceName || t('common:unknow_source')}
{displaySourceName}
</Box>
</Box>
</MyTooltip>
</MyTooltip>
</Box>
);
};
......
......@@ -27,6 +27,7 @@ import type { SimpleAppSnapshotType } from './useSnapshots';
import ExportConfigPopover from '@/pageComponents/app/detail/ExportConfigPopover';
import { ChatSidebarPaneEnum } from '@/pageComponents/chat/constants';
import type { Form2WorkflowFnType } from './type';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
const AppCard = ({
appForm,
......@@ -91,16 +92,18 @@ const AppCard = ({
<Flex alignItems={'center'} justifyContent={'space-between'} mb={5}>
<Flex alignItems={'center'} flex={1} minW={0}>
<Avatar src={appDetail.avatar} borderRadius={'md'} w={'28px'} h={'28px'} />
<Box
ml={3}
fontWeight={'bold'}
fontSize={'lg'}
color={'myGray.900'}
flex={1}
noOfLines={1}
>
{appDetail.name}
</Box>
<MyTooltip label={appDetail.name} showOnlyWhenOverflow>
<Box
ml={3}
fontWeight={'bold'}
fontSize={'lg'}
color={'myGray.900'}
flex={1}
noOfLines={1}
>
{appDetail.name}
</Box>
</MyTooltip>
</Flex>
{/* Right Action Icons */}
......
......@@ -132,7 +132,7 @@ const ExportConfigPopover = ({
<MyPopover
placement={'right-start'}
offset={[0, 0]}
hasArrow={false}
hasArrow={true}
trigger={'hover'}
flip={false}
zIndex={2000}
......
......@@ -12,6 +12,7 @@ import MyPopover from '@fastgpt/web/components/common/MyPopover';
import MyBox from '@fastgpt/web/components/common/MyBox';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { WorkflowUtilsContext } from './context/workflowUtilsContext';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
const ImportSettings = dynamic(() => import('./Flow/ImportSettings'));
const ExportConfigPopover = dynamic(
......@@ -165,11 +166,15 @@ const AppCard = ({ showSaveStatus, isSaved }: { showSaveStatus: boolean; isSaved
const Render = useMemo(() => {
return (
<HStack flex={1} justifyContent={'space-between'}>
<HStack>
<Avatar src={appDetail.avatar} w={'1.75rem'} borderRadius={'md'} />
<Box>
<HStack spacing={1}>
<Box color={'myGray.900'}>{appDetail.name}</Box>
<HStack minW={0}>
<Avatar src={appDetail.avatar} w={'1.75rem'} borderRadius={'md'} flexShrink={0} />
<Box minW={0}>
<HStack spacing={1} minW={0}>
<MyTooltip label={appDetail.name} showOnlyWhenOverflow>
<Box color={'myGray.900'} maxW={['45vw', '280px']} className="textEllipsis">
{appDetail.name}
</Box>
</MyTooltip>
</HStack>
{showSaveStatus && (
<Flex alignItems={'center'} fontSize={'mini'} lineHeight={1}>
......@@ -199,6 +204,7 @@ const AppCard = ({ showSaveStatus, isSaved }: { showSaveStatus: boolean; isSaved
icon={<MyIcon name={'common/select'} w={'18px'} color={'myGray.500'} />}
w={'34px'}
h={'34px'}
flexShrink={0}
bg={'white'}
border={'1px solid'}
borderColor={'myGray.250'}
......
......@@ -48,16 +48,18 @@ const QuoteItem = ({
>
<Flex gap={2} alignItems={'center'} pb={'8px'}>
<Box alignItems={'center'} fontSize={'10px'} fontWeight={500} display={'inline-flex'}>
<Flex gap={1}>
<Flex gap={1} minW={0}>
<MyIcon name={icon as any} flexShrink={0} w={'12px'} />
<Box
className={'textEllipsis'}
wordBreak={'break-all'}
flex={'1 0 0'}
color={'myGray.900'}
>
{sourceName}
</Box>
<MyTooltip label={sourceName} showOnlyWhenOverflow>
<Box
className={'textEllipsis'}
wordBreak={'break-all'}
flex={'1 0 0'}
color={'myGray.900'}
>
{sourceName}
</Box>
</MyTooltip>
</Flex>
</Box>
</Flex>
......
......@@ -15,6 +15,7 @@ import {
import { getQuoteDataList } from '@/web/core/chat/record/api';
import { useSystem } from '@fastgpt/web/hooks/useSystem';
import FillRowTabs from '@fastgpt/web/components/common/Tabs/FillRowTabs';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
type MobileQuoteTab = 'detail' | 'source';
......@@ -177,9 +178,11 @@ const QuoteReader = ({
onClick={() => openCollectionQuote(item)}
>
<MyIcon name={item.icon as any} flexShrink={0} w={'16px'} />
<Box className={'textEllipsis'} minW={0}>
{item.sourceName}
</Box>
<MyTooltip label={item.sourceName} showOnlyWhenOverflow>
<Box className={'textEllipsis'} minW={0}>
{item.sourceName}
</Box>
</MyTooltip>
</Flex>
))}
</Flex>
......
......@@ -198,7 +198,7 @@ const CollectionCard = () => {
parentId: targetId
});
getData(pageNum);
} catch (error) {}
} catch {}
}
});
......@@ -261,18 +261,29 @@ const CollectionCard = () => {
}}
>
<Td minW={'150px'} maxW={['200px', '300px']} draggable py={2}>
<HStack>
<HStack minW={0}>
<HStack onClick={(e) => e.stopPropagation()}>
<Checkbox
isChecked={isSelected(collection)}
onChange={(e) => toggleSelect(collection)}
onChange={() => toggleSelect(collection)}
/>
</HStack>
<Box>
<Flex alignItems={'center'}>
<MyIcon name={collection.icon as any} w={'1.25rem'} mr={2} />
<MyTooltip label={t('common:click_drag_tip')} shouldWrapChildren={false}>
<Box color={'myGray.900'} fontWeight={'500'} className="textEllipsis">
<Box minW={0} flex={1}>
<Flex alignItems={'center'} minW={0}>
<MyIcon
name={collection.icon as any}
w={'1.25rem'}
mr={2}
flexShrink={0}
/>
<MyTooltip label={collection.name} showOnlyWhenOverflow>
<Box
color={'myGray.900'}
fontWeight={'500'}
className="textEllipsis"
minW={0}
flex={'0 1 auto'}
>
{collection.name}
</Box>
</MyTooltip>
......
import React, { useCallback, useMemo } from 'react';
import React, { useCallback } from 'react';
import { useTranslation } from 'next-i18next';
import { Box, Flex, IconButton, useTheme, Progress } from '@chakra-ui/react';
import { Box, Flex, IconButton, useTheme } from '@chakra-ui/react';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { useRouter } from 'next/router';
import { useContextSelector } from 'use-context-selector';
......@@ -8,6 +8,7 @@ import { DatasetPageContext } from '@/web/core/dataset/context/datasetPageContex
import LightRowTabs from '@fastgpt/web/components/common/Tabs/LightRowTabs';
import { useSystem } from '@fastgpt/web/hooks/useSystem';
import FolderPath from '@/components/common/folder/Path';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
export enum TabEnum {
dataCard = 'dataCard',
......@@ -23,10 +24,7 @@ const NavBar = ({ currentTab }: { currentTab: TabEnum }) => {
const router = useRouter();
const query = router.query;
const { isPc } = useSystem();
const { datasetDetail, rebuildingCount, paths } = useContextSelector(
DatasetPageContext,
(v) => v
);
const { datasetDetail, paths } = useContextSelector(DatasetPageContext, (v) => v);
const tabList = [
{
......@@ -92,9 +90,17 @@ const NavBar = ({ currentTab }: { currentTab: TabEnum }) => {
aria-label={''}
_hover={'none'}
/>
<Box fontWeight={500} color={'myGray.600'} fontSize={'sm'}>
{datasetDetail.name}
</Box>
<MyTooltip label={datasetDetail.name} showOnlyWhenOverflow>
<Box
fontWeight={500}
color={'myGray.600'}
fontSize={'sm'}
maxW={['45vw', '280px']}
className="textEllipsis"
>
{datasetDetail.name}
</Box>
</MyTooltip>
</Flex>
</>
) : (
......
......@@ -17,6 +17,7 @@ import { useContextSelector } from 'use-context-selector';
import { DatasetPageContext } from '../context/datasetPageContext';
import EmptyTip from '@fastgpt/web/components/common/EmptyTip';
import type { ParentIdType } from '@fastgpt/global/common/parentFolder/type';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
const SelectCollections = ({
datasetId,
......@@ -187,14 +188,16 @@ const SelectCollections = ({
result = [...selectedDatasetCollectionIds, item._id];
}
setSelectedDatasetCollectionIds(result);
onChange && onChange({ parentId, collectionIds: result });
onChange?.({ parentId, collectionIds: result });
}
}}
>
<Flex alignItems={'center'} h={'38px'}>
<MyIcon name={item.icon as any} w={'18px'} />
<Box ml={3} fontSize={'sm'} className="textEllipsis">
{item.name}
<Flex alignItems={'center'} h={'38px'} minW={0}>
<MyIcon name={item.icon as any} w={'18px'} flexShrink={0} />
<Box ml={3} fontSize={'sm'} minW={0} flex={1}>
<MyTooltip label={item.name} showOnlyWhenOverflow>
<Box className="textEllipsis">{item.name}</Box>
</MyTooltip>
</Box>
</Flex>
</Card>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment