refactor: Improve Ellipsis component and usage (#2603)

* refactor: Improve Ellipsis component and usage

- Modify Ellipsis component to use children instead of text prop
- Add support for multi-line and single-line ellipsis with styled-components
- Update KnowledgeContent to use new Ellipsis component structure
- Enhance ClickableSpan styling for better text truncation

* fix: Improve text wrapping in Ellipsis component

Add overflow-wrap: break-word to ensure long words are properly truncated in multi-line ellipsis

* refactor: Improve link and tooltip rendering in KnowledgeContent

- Wrap links with ClickableSpan for better interaction and styling
- Adjust Tooltip and Ellipsis placement for improved readability
- Remove unnecessary inline styling for links in ItemInfo

---------

Co-authored-by: lizhixuan <zhixuan.li@banosuperapp.com>
This commit is contained in:
MyPrototypeWhat 2025-03-02 20:43:56 +08:00 committed by GitHub
parent 687f140a5c
commit ad39d8774d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 41 additions and 29 deletions

View File

@ -1,26 +1,35 @@
import React from 'react' import type { HTMLAttributes } from 'react'
import styled from 'styled-components' import styled, { css } from 'styled-components'
type Props = { type Props = {
text: string | number
maxLine?: number maxLine?: number
} & React.HTMLAttributes<HTMLDivElement> } & HTMLAttributes<HTMLDivElement>
const Ellipsis = (props: Props) => { const Ellipsis = (props: Props) => {
const { text, maxLine = 1, ...rest } = props const { maxLine = 1, children, ...rest } = props
return ( return (
<EllipsisContainer maxLine={maxLine} {...rest}> <EllipsisContainer $maxLine={maxLine} {...rest}>
{text} {children}
</EllipsisContainer> </EllipsisContainer>
) )
} }
const EllipsisContainer = styled.div<{ maxLine: number }>` const multiLineEllipsis = css<{ $maxLine: number }>`
display: -webkit-box; display: -webkit-box;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
text-overflow: ellipsis; -webkit-line-clamp: ${({ $maxLine }) => $maxLine};
overflow-wrap: break-word;
`
const singleLineEllipsis = css`
display: block;
white-space: nowrap;
`
const EllipsisContainer = styled.div<{ $maxLine: number }>`
overflow: hidden; overflow: hidden;
-webkit-line-clamp: ${({ maxLine }) => maxLine}; text-overflow: ellipsis;
${({ $maxLine }) => ($maxLine > 1 ? multiLineEllipsis : singleLineEllipsis)}
` `
export default Ellipsis export default Ellipsis

View File

@ -263,9 +263,9 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
<ItemInfo> <ItemInfo>
<FileIcon /> <FileIcon />
<ClickableSpan onClick={() => window.api.file.openPath(file.path)}> <ClickableSpan onClick={() => window.api.file.openPath(file.path)}>
<Tooltip title={file.origin_name}> <Ellipsis>
<Ellipsis text={file.origin_name} /> <Tooltip title={file.origin_name}>{file.origin_name}</Tooltip>
</Tooltip> </Ellipsis>
</ClickableSpan> </ClickableSpan>
</ItemInfo> </ItemInfo>
<FlexAlignCenter> <FlexAlignCenter>
@ -295,9 +295,9 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
<ItemInfo> <ItemInfo>
<FolderOutlined /> <FolderOutlined />
<ClickableSpan onClick={() => window.api.file.openPath(item.content as string)}> <ClickableSpan onClick={() => window.api.file.openPath(item.content as string)}>
<Tooltip title={item.content as string}> <Ellipsis>
<Ellipsis text={item.content as string} /> <Tooltip title={item.content as string}>{item.content as string}</Tooltip>
</Tooltip> </Ellipsis>
</ClickableSpan> </ClickableSpan>
</ItemInfo> </ItemInfo>
<FlexAlignCenter> <FlexAlignCenter>
@ -353,11 +353,15 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
] ]
}} }}
trigger={['contextMenu']}> trigger={['contextMenu']}>
<a href={item.content as string} target="_blank" rel="noopener noreferrer"> <ClickableSpan>
<Tooltip title={item.content as string}> <Tooltip title={item.content as string}>
<Ellipsis text={item.remark || (item.content as string)} /> <Ellipsis>
</Tooltip> <a href={item.content as string} target="_blank" rel="noopener noreferrer">
{item.remark || (item.content as string)}
</a> </a>
</Ellipsis>
</Tooltip>
</ClickableSpan>
</Dropdown> </Dropdown>
</ItemInfo> </ItemInfo>
<FlexAlignCenter> <FlexAlignCenter>
@ -386,11 +390,15 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
<ItemContent> <ItemContent>
<ItemInfo> <ItemInfo>
<GlobalOutlined /> <GlobalOutlined />
<a href={item.content as string} target="_blank" rel="noopener noreferrer"> <ClickableSpan>
<Tooltip title={item.content as string}> <Tooltip title={item.content as string}>
<Ellipsis text={item.content as string} /> <Ellipsis>
</Tooltip> <a href={item.content as string} target="_blank" rel="noopener noreferrer">
{item.content as string}
</a> </a>
</Ellipsis>
</Tooltip>
</ClickableSpan>
</ItemInfo> </ItemInfo>
<FlexAlignCenter> <FlexAlignCenter>
{item.uniqueId && <Button type="text" icon={<RefreshIcon />} onClick={() => refreshItem(item)} />} {item.uniqueId && <Button type="text" icon={<RefreshIcon />} onClick={() => refreshItem(item)} />}
@ -530,13 +538,6 @@ const ItemInfo = styled.div`
align-items: center; align-items: center;
gap: 8px; gap: 8px;
flex: 1; flex: 1;
a {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 600px;
}
` `
const IndexSection = styled.div` const IndexSection = styled.div`
@ -570,6 +571,8 @@ const FlexAlignCenter = styled.div`
const ClickableSpan = styled.span` const ClickableSpan = styled.span`
cursor: pointer; cursor: pointer;
flex: 1;
width: 0;
` `
const FileIcon = styled(FileTextOutlined)` const FileIcon = styled(FileTextOutlined)`