瀏覽代碼

Merge pull request #2753 from yatbfm/feat/upload-filename-tooltip

feat: add filename tooltip when the filename is too long
SudoUser 5 月之前
父節點
當前提交
092b530040

+ 54 - 0
content/input/upload/index-en-US.md

@@ -32,6 +32,59 @@ import { IconUpload } from '@douyinfe/semi-icons';
     </Upload>
 );
 ```
+### File name too long ellipsis
+
+Customize the file name tooltip using the `showTooltip` property
+
+When the type is `boolean`, control whether to show the tooltip
+
+```jsx live=true width=48%
+import React from 'react';
+import { Upload, Button } from '@douyinfe/semi-ui';
+
+() => {
+    const action = 'https://api.semi.design/upload';
+    const button = (
+        <Button icon={<IconUpload />} theme="light">
+            Click upload
+        </Button>
+    );
+    return (
+        <>
+            <Upload action={action} showTooltip={false}>
+                {button}
+            </Upload>
+        </>
+    );
+}
+```
+
+When the type is `object`, you can customize the tooltip style.
+
+```jsx live=true width=48%
+import React from 'react';
+import { Upload, Button, Tooltip } from '@douyinfe/semi-ui';
+
+() => {
+    const action = 'https://api.semi.design/upload';
+    const button = (
+        <Button icon={<IconUpload />} theme="light">
+            Click upload
+        </Button>
+    );
+    return (
+        <>
+            <Upload action={action} showTooltip={{ 
+                renderTooltip: (content, children) => {
+                    return <Tooltip content={content} position="bottom">{children}</Tooltip>
+                } 
+            }}>
+                {button}
+            </Upload>
+        </>
+    );
+}
+```
 
 ### Add prompt text
 
@@ -1404,6 +1457,7 @@ import { IconUpload } from '@douyinfe/semi-icons';
 |showPicInfo| Whether to display picture information, only valid in photo wall mode | boolean| false | 2.2.0 |
 |showReplace | When the upload is successful, whether to display the replace button inside the fileCard | boolean | false | 1.21.0 |
 |showRetry | When uploading fails, whether to display the retry button inside the fileCard | boolean | true | 1.0.0 |
+|showTooltip | When the file name is too long, whether to display the tooltip and related configurations: type, the component that carries the floating layer content, supports Tooltip \| Popover; opts, other properties that need to be passed to the floating layer component; renderTooltip, custom rendering of the popup layer component | boolean \| {type: 'tooltip' \| 'popover', opts: object, renderTooltip: (content: ReactNode, children: ReactNode) => ReactNode} | true |  |
 |showUploadList | Whether to display the file list | boolean | true | |
 |style | Style | CSSProperties | | |
 |transformFile | After selecting the file, the callback function before uploading the file can be used to customize the conversion processing of the file | (file:[File](https://developer.mozilla.org/zh-CN/docs/Web/API/File)) => FileItem | | 1.0.0 |

+ 55 - 0
content/input/upload/index.md

@@ -35,6 +35,60 @@ import { IconUpload } from '@douyinfe/semi-icons';
 };
 ```
 
+### 文件名超长省略
+
+通过 `showTooltip` 属性,自定义设置文件名弹出提示
+
+当类型为 `boolean` 时,控制是否弹出提示
+
+```jsx live=true width=48%
+import React from 'react';
+import { Upload, Button } from '@douyinfe/semi-ui';
+
+() => {
+    const action = 'https://api.semi.design/upload';
+    const button = (
+        <Button icon={<IconUpload />} theme="light">
+            点击上传
+        </Button>
+    );
+    return (
+        <>
+            <Upload action={action} showTooltip={false}>
+                {button}
+            </Upload>
+        </>
+    );
+}
+```
+
+当类型为 `object` 时,可以自定义弹出样式
+
+```jsx live=true width=48%
+import React from 'react';
+import { Upload, Button, Tooltip } from '@douyinfe/semi-ui';
+
+() => {
+    const action = 'https://api.semi.design/upload';
+    const button = (
+        <Button icon={<IconUpload />} theme="light">
+            点击上传
+        </Button>
+    );
+    return (
+        <>
+            <Upload action={action} showTooltip={{ 
+                renderTooltip: (content, children) => {
+                    return <Tooltip content={content} position="bottom">{children}</Tooltip>
+                } 
+            }}>
+                {button}
+            </Upload>
+        </>
+    );
+}
+```
+
 ### 添加提示文本
 
 通过 `prompt` 插槽,设置自定义提示文本  
@@ -1413,6 +1467,7 @@ import { IconUpload } from '@douyinfe/semi-icons';
 |showPicInfo| 是否显示图片信息,只在照片墙模式下有效| boolean| false | 2.2.0 |
 |showReplace | 上传成功时,是否展示在 fileCard 内部展示替换按钮 | boolean | false |  |
 |showRetry | 上传失败时,是否展示在 fileCard 内部展示重试按钮 | boolean | true |  |
+|showTooltip | 文件名超长时,是否展示 tooltip 及相关配置: type,浮层内容承载的组件,支持 Tooltip \| Popover;opts,其他需要透传给浮层组件的属性; renderTooltip,自定义渲染弹出层组件 | boolean \| {type: 'tooltip' \| 'popover', opts: object, renderTooltip: (content: ReactNode, children: ReactNode) => ReactNode} | true |  |
 |showUploadList | 是否显示文件列表 | boolean | true |  |
 |style | 样式 | CSSProperties |  |  |
 |transformFile | 选中文件后,上传文件前的回调函数,可用于对文件进行自定义转换处理 | (file:[File](https://developer.mozilla.org/zh-CN/docs/Web/API/File)) => FileItem |  |  |

+ 9 - 5
packages/semi-ui/upload/fileCard.tsx

@@ -15,6 +15,7 @@ import Tooltip from '../tooltip/index';
 import Spin from '../spin/index';
 import { isElement } from '../_base/reactUtils';
 import { RenderFileItemProps } from './interface';
+import Typography, { ShowTooltip } from '../typography';
 
 const prefixCls = cssClasses.PREFIX;
 
@@ -48,7 +49,8 @@ export interface FileCardProps extends RenderFileItemProps {
     className?: string;
     style?: CSSProperties;
     picWidth?: string | number;
-    picHeight?: string | number
+    picHeight?: string | number;
+    showTooltip?: boolean | ShowTooltip
 }
 
 export interface FileCardState {
@@ -77,7 +79,8 @@ class FileCard extends BaseComponent<FileCardProps, FileCardState> {
         style: PropTypes.object,
         url: PropTypes.string,
         validateMessage: PropTypes.node,
-        index: PropTypes.number
+        index: PropTypes.number,
+        showTooltip: PropTypes.oneOfType([PropTypes.bool, PropTypes.object])
     };
 
     static defaultProps = {
@@ -87,6 +90,7 @@ class FileCard extends BaseComponent<FileCardProps, FileCardState> {
         onRetry: (): void => undefined,
         preview: false,
         size: '',
+        showTooltip: true,
     };
 
     constructor(props: FileCardProps) {
@@ -227,7 +231,7 @@ class FileCard extends BaseComponent<FileCardProps, FileCardState> {
     }
 
     renderFile(locale: Locale["Upload"]) {
-        const { name, size, percent, url, showRetry: propsShowRetry, showReplace: propsShowReplace, preview, previewFile, status, style, onPreviewClick, renderFileOperation } = this.props;
+        const { name, size, percent, url, showRetry: propsShowRetry, showReplace: propsShowReplace, preview, previewFile, status, style, onPreviewClick, renderFileOperation, showTooltip } = this.props;
         const { fallbackPreview } = this.state;
         const fileCardCls = cls({
             [`${prefixCls}-file-card`]: true,
@@ -258,9 +262,9 @@ class FileCard extends BaseComponent<FileCardProps, FileCardState> {
                 </div>
                 <div className={`${infoCls}-main`}>
                     <div className={`${infoCls}-main-text`}>
-                        <span className={`${infoCls}-name`}>
+                        <Typography.Text className={`${infoCls}-name`} ellipsis={{ showTooltip }}>
                             {name}
-                        </span>
+                        </Typography.Text>
                         <span>
                             <span className={`${infoCls}-size`}>{fileSize}</span>
                             {showReplace && (

+ 8 - 2
packages/semi-ui/upload/index.tsx

@@ -31,6 +31,7 @@ import type {
     FileItemStatus
 } from '@douyinfe/semi-foundation/upload/foundation';
 import type { ValidateStatus } from '../_base/baseComponent';
+import { ShowTooltip } from '../typography';
 
 const prefixCls = cssClasses.PREFIX;
 
@@ -119,7 +120,8 @@ export interface UploadProps {
     uploadTrigger?: 'auto' | 'custom';
     validateMessage?: ReactNode;
     validateStatus?: ValidateStatus;
-    withCredentials?: boolean
+    withCredentials?: boolean;
+    showTooltip?: boolean | ShowTooltip
 }
 
 export interface UploadState {
@@ -200,6 +202,7 @@ class Upload extends BaseComponent<UploadProps, UploadState> {
         validateMessage: PropTypes.node,
         validateStatus: PropTypes.oneOf<UploadProps['validateStatus']>(strings.VALIDATE_STATUS),
         withCredentials: PropTypes.bool,
+        showTooltip: PropTypes.oneOfType([PropTypes.bool, PropTypes.object])
     };
 
     static defaultProps: Partial<UploadProps> = {
@@ -232,6 +235,7 @@ class Upload extends BaseComponent<UploadProps, UploadState> {
         showUploadList: true,
         uploadTrigger: 'auto' as const,
         withCredentials: false,
+        showTooltip: true,
     };
 
     static FileCard = FileCard;
@@ -424,6 +428,7 @@ class Upload extends BaseComponent<UploadProps, UploadState> {
             onPreviewClick,
             picWidth,
             picHeight,
+            showTooltip,
         } = this.props;
         const onRemove = (): void => this.remove(file);
         const onRetry = (): void => {
@@ -455,7 +460,8 @@ class Upload extends BaseComponent<UploadProps, UploadState> {
                     ? (): void => this.foundation.handlePreviewClick(file)
                     : undefined,
             picWidth,
-            picHeight
+            picHeight,
+            showTooltip,
         };
 
         if (status === strings.FILE_STATUS_UPLOAD_FAIL && !validateMessage) {