Jelajahi Sumber

feat: Table support ellipsis and update word-break style #1318

shijia.me 2 tahun lalu
induk
melakukan
030f547317

+ 233 - 0
content/show/table/index-en-US.md

@@ -2581,6 +2581,238 @@ function App() {
 render(App);
 ```
 
+### Column Ellipsis
+
+Use `ellipsis` to make cells automatically clipped. v2.34.0 support.
+
+```jsx live=true noInline=true dir="column"
+import React from 'react';
+import { Table } from '@douyinfe/semi-ui';
+import { IconMore } from '@douyinfe/semi-icons';
+
+function App() {
+    const columns = [
+        {
+            title: 'Title',
+            dataIndex: 'name',
+            fixed: true,
+            width: 250,
+            filters: [
+                {
+                    text: 'Semi Design',
+                    value: 'Semi Design',
+                },
+                {
+                    text: 'Semi Pro',
+                    value: 'Semi Pro',
+                },
+            ],
+            onFilter: (value, record) => record.name.includes(value),
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+            ellipsis: true,
+        },
+        {
+            title: 'Owner',
+            dataIndex: 'owner',
+            width: 200,
+            ellipsis: true,
+            filters: [
+                {
+                    text: 'Semi Design',
+                    value: 'Semi Design',
+                },
+                {
+                    text: 'Semi Pro',
+                    value: 'Semi Pro',
+                },
+            ],
+            onFilter: (value, record) => record.name.includes(value),
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+        },
+        {
+            title: 'Size',
+            dataIndex: 'size',
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+            ellipsis: true,
+        },
+        {
+            title: 'Update time',
+            dataIndex: 'updateTime',
+            width: 200,
+            ellipsis: true,
+        },
+        {
+            title: '',
+            dataIndex: 'operate',
+            fixed: 'right',
+            align: 'center',
+            width: 100,
+            render: () => {
+                return <IconMore />;
+            },
+        },
+    ];
+    const data = [
+        {
+            key: '1',
+            name: 'Maintained by the Douyin front-end and UED teams, an easy-to-customize modern design system that helps designers and developers create high-quality products.',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png',
+            size: '2M',
+            owner: 'Pengzhi Jiang Pengzhi Jiang Pengzhi Jiang Pengzhi Jiang',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'grey',
+        },
+        {
+            key: '2',
+            name: 'Semi is designed based on FA architecture, and the main logic is extracted as Foundation package, which is easy to migrate to other frameworks',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '2M',
+            owner: 'Xuan Hao Xuan Hao Xuan Hao Xuan Hao Xuan Hao Xuan Hao',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'red',
+        },
+        {
+            key: '3',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            name: 'Maintained by the Douyin front-end and UED teams, an easy-to-customize modern design system that helps designers and developers create high-quality products.',
+            size: '34KB',
+            owner: 'Pengzhi Jiang Pengzhi Jiang Pengzhi Jiang Pengzhi Jiang',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'light-blue',
+        },
+        {
+            key: '4',
+            name: 'Semi is designed based on FA architecture, and the main logic is extracted as Foundation package, which is easy to migrate to other frameworks',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '34KB',
+            owner: 'Xuan Hao Xuan Hao Xuan Hao Xuan Hao Xuan Hao Xuan Hao',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'light-blue',
+        },
+    ];
+
+    return <Table scroll={{ x: 1200 }} columns={columns} dataSource={data} pagination={false} />;
+}
+
+render(App);
+```
+
+Set `ellipsis.showTitle` to false to hide the default native HTML title. With `column.render` you can customize the content prompt.
+
+```jsx live=true noInline=true dir="column"
+import React from 'react';
+import { Table, Typography } from '@douyinfe/semi-ui';
+import { IconMore } from '@douyinfe/semi-icons';
+
+function App() {
+    const columns = [
+        {
+            title: 'Title',
+            dataIndex: 'name',
+            fixed: true,
+            width: 250,
+            filters: [
+                {
+                    text: 'Semi Design',
+                    value: 'Semi Design',
+                },
+                {
+                    text: 'Semi Pro',
+                    value: 'Semi Pro',
+                },
+            ],
+            onFilter: (value, record) => record.name.includes(value),
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+            ellipsis: { showTitle: false },
+            render: (text) => <Typography.Text ellipsis={{ showTooltip: true }}>{text}</Typography.Text>,
+        },
+        {
+            title: 'Owner',
+            dataIndex: 'owner',
+            width: 200,
+            filters: [
+                {
+                    text: 'Semi Design',
+                    value: 'Semi Design',
+                },
+                {
+                    text: 'Semi Pro',
+                    value: 'Semi Pro',
+                },
+            ],
+            onFilter: (value, record) => record.name.includes(value),
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+            ellipsis: { showTitle: false },
+            render: (text) => <Typography.Text ellipsis={{ showTooltip: true }}>{text}</Typography.Text>,
+        },
+        {
+            title: 'Size',
+            dataIndex: 'size',
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+            ellipsis: true,
+        },
+        {
+            title: 'Update time',
+            dataIndex: 'updateTime',
+            width: 200,
+            ellipsis: true,
+        },
+        {
+            title: '',
+            dataIndex: 'operate',
+            fixed: 'right',
+            align: 'center',
+            width: 100,
+            render: () => {
+                return <IconMore />;
+            },
+        },
+    ];
+    const data = [
+        {
+            key: '1',
+            name: 'Maintained by the Douyin front-end and UED teams, an easy-to-customize modern design system that helps designers and developers create high-quality products.',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png',
+            size: '2M',
+            owner: 'Pengzhi Jiang Pengzhi Jiang Pengzhi Jiang Pengzhi Jiang',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'grey',
+        },
+        {
+            key: '2',
+            name: 'Semi is designed based on FA architecture, and the main logic is extracted as Foundation package, which is easy to migrate to other frameworks',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '2M',
+            owner: 'Xuan Hao Xuan Hao Xuan Hao Xuan Hao Xuan Hao Xuan Hao',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'red',
+        },
+        {
+            key: '3',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            name: 'Maintained by the Douyin front-end and UED teams, an easy-to-customize modern design system that helps designers and developers create high-quality products.',
+            size: '34KB',
+            owner: 'Pengzhi Jiang Pengzhi Jiang Pengzhi Jiang Pengzhi Jiang',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'light-blue',
+        },
+        {
+            key: '4',
+            name: 'Semi is designed based on FA architecture, and the main logic is extracted as Foundation package, which is easy to migrate to other frameworks',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '34KB',
+            owner: 'Xuan Hao Xuan Hao Xuan Hao Xuan Hao Xuan Hao Xuan Hao',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'light-blue',
+        },
+    ];
+
+    return <Table scroll={{ x: 1200 }} columns={columns} dataSource={data} pagination={false} />;
+}
+
+render(App);
+```
+
 ### Resizable Column
 
 Version > = 0.15.0
@@ -4752,6 +4984,7 @@ import { Table } from '@douyinfe/semi-ui';
 | defaultFilteredValue | Default value of the filter, the filter state of the external control column with a value of the screened value array | any[] |  | **2.5.0** |
 | defaultSortOrder | The default value of sortOrder, one of 'ascend'\|'descend'\|false | boolean\| string | false | **1.31.0** |
 | direction | RTL, LTR direction, the default value is equal to ConfigProvider direction, you can configure the direction of the Table separately here | 'ltr' \| 'rtl' |  | **2.31.0** |
+| ellipsis | Ellipsis Text, table-layout will automatically switch to fixed after it is turned on | boolean\| { showTitle: boolean } | false | **2.34.0** |
 | filterChildrenRecord | Whether the child data needs to be filtered locally. If this function is enabled, if the child meets the filtering criteria, the parent will retain it even if it does not meet the criteria. | boolean |  | **0.29.0** |
 | filterDropdown | You can customize the filter menu. This function is only responsible for rendering the layer and needs to write a variety of interactions. | ReactNode |  |
 | filterDropdownProps | Props passing to Dropdown, see more in [Dropdown API](/en-US/show/dropdown#Dropdown) | object |  |

+ 233 - 0
content/show/table/index.md

@@ -2579,6 +2579,238 @@ function App() {
 render(App);
 ```
 
+### 单元格缩略
+
+使用 `ellipsis` 可以让单元格自动实现缩略效果。v2.34.0 支持。
+
+```jsx live=true noInline=true dir="column"
+import React from 'react';
+import { Table } from '@douyinfe/semi-ui';
+import { IconMore } from '@douyinfe/semi-icons';
+
+function App() {
+    const columns = [
+        {
+            title: '标题',
+            dataIndex: 'name',
+            fixed: true,
+            width: 250,
+            filters: [
+                {
+                    text: 'Semi Design 设计稿',
+                    value: 'Semi Design 设计稿',
+                },
+                {
+                    text: 'Semi Pro 设计稿',
+                    value: 'Semi Pro 设计稿',
+                },
+            ],
+            onFilter: (value, record) => record.name.includes(value),
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+            ellipsis: true,
+        },
+        {
+            title: '所有者',
+            dataIndex: 'owner',
+            width: 200,
+            ellipsis: true,
+            filters: [
+                {
+                    text: 'Semi Design 设计稿',
+                    value: 'Semi Design 设计稿',
+                },
+                {
+                    text: 'Semi Pro 设计稿',
+                    value: 'Semi Pro 设计稿',
+                },
+            ],
+            onFilter: (value, record) => record.name.includes(value),
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+        },
+        {
+            title: '大小',
+            dataIndex: 'size',
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+            ellipsis: true,
+        },
+        {
+            title: '更新日期',
+            dataIndex: 'updateTime',
+            width: 200,
+            ellipsis: true,
+        },
+        {
+            title: '',
+            dataIndex: 'operate',
+            fixed: 'right',
+            align: 'center',
+            width: 100,
+            render: () => {
+                return <IconMore />;
+            },
+        },
+    ];
+    const data = [
+        {
+            key: '1',
+            name: 'Semi is designed based on FA architecture, and the main logic is extracted as Foundation package, which is easy to migrate to other frameworks',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png',
+            size: '2M',
+            owner: 'Pengzhi Jiang Pengzhi Jiang Pengzhi Jiang Pengzhi Jiang',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'grey',
+        },
+        {
+            key: '2',
+            name: '由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '2M',
+            owner: '郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'red',
+        },
+        {
+            key: '3',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            name: 'Semi is designed based on FA architecture, and the main logic is extracted as Foundation package, which is easy to migrate to other frameworks',
+            size: '34KB',
+            owner: 'Pengzhi Jiang Pengzhi Jiang Pengzhi Jiang Pengzhi Jiang',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'light-blue',
+        },
+        {
+            key: '4',
+            name: '由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '34KB',
+            owner: '郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'light-blue',
+        },
+    ];
+
+    return <Table scroll={{ x: 1200 }} columns={columns} dataSource={data} pagination={false} />;
+}
+
+render(App);
+```
+
+设置 `ellipsis.showTitle` 为 false 可以隐藏默认原生的 HTML title。 配合 `column.render` 可以自定义内容提示。
+
+```jsx live=true noInline=true dir="column"
+import React from 'react';
+import { Table, Typography } from '@douyinfe/semi-ui';
+import { IconMore } from '@douyinfe/semi-icons';
+
+function App() {
+    const columns = [
+        {
+            title: '标题',
+            dataIndex: 'name',
+            fixed: true,
+            width: 250,
+            filters: [
+                {
+                    text: 'Semi Design 设计稿',
+                    value: 'Semi Design 设计稿',
+                },
+                {
+                    text: 'Semi Pro 设计稿',
+                    value: 'Semi Pro 设计稿',
+                },
+            ],
+            onFilter: (value, record) => record.name.includes(value),
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+            ellipsis: { showTitle: false },
+            render: (text) => <Typography.Text ellipsis={{ showTooltip: true }}>{text}</Typography.Text>,
+        },
+        {
+            title: '所有者',
+            dataIndex: 'owner',
+            width: 200,
+            filters: [
+                {
+                    text: 'Semi Design 设计稿',
+                    value: 'Semi Design 设计稿',
+                },
+                {
+                    text: 'Semi Pro 设计稿',
+                    value: 'Semi Pro 设计稿',
+                },
+            ],
+            onFilter: (value, record) => record.name.includes(value),
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+            ellipsis: { showTitle: false },
+            render: (text) => <Typography.Text ellipsis={{ showTooltip: true }}>{text}</Typography.Text>,
+        },
+        {
+            title: '大小',
+            dataIndex: 'size',
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+            ellipsis: true,
+        },
+        {
+            title: '更新日期',
+            dataIndex: 'updateTime',
+            width: 200,
+            ellipsis: true,
+        },
+        {
+            title: '',
+            dataIndex: 'operate',
+            fixed: 'right',
+            align: 'center',
+            width: 100,
+            render: () => {
+                return <IconMore />;
+            },
+        },
+    ];
+    const data = [
+        {
+            key: '1',
+            name: 'Semi is designed based on FA architecture, and the main logic is extracted as Foundation package, which is easy to migrate to other frameworks',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png',
+            size: '2M',
+            owner: 'Pengzhi Jiang Pengzhi Jiang Pengzhi Jiang Pengzhi Jiang',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'grey',
+        },
+        {
+            key: '2',
+            name: '由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '2M',
+            owner: '郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣郝宣',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'red',
+        },
+        {
+            key: '3',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            name: 'Semi is designed based on FA architecture, and the main logic is extracted as Foundation package, which is easy to migrate to other frameworks',
+            size: '34KB',
+            owner: 'Pengzhi Jiang',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'light-blue',
+        },
+        {
+            key: '4',
+            name: '由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '34KB',
+            owner: '郝宣',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'light-blue',
+        },
+    ];
+
+    return <Table scroll={{ x: 1200 }} columns={columns} dataSource={data} pagination={false} />;
+}
+
+render(App);
+```
+
 ### 可伸缩列
 
 版本 >= 0.15.0
@@ -4758,6 +4990,7 @@ import { Table } from '@douyinfe/semi-ui';
 | dataIndex | 列数据在数据项中对应的 key,使用排序或筛选时必传 | string |  |
 | defaultFilteredValue | 筛选的默认值,值为已筛选的 value 数组 | any[] |  | **2.5.0** |
 | defaultSortOrder | 排序的默认值,可设置为 'ascend'\|'descend'\|false | boolean\| string | false | **1.31.0** |
+| ellipsis | 文本缩略,开启后 table-layout 会自动切换为 fixed | boolean\| { showTitle: boolean } | false | **2.34.0** |
 | filterChildrenRecord | 是否需要对子级数据进行本地过滤,开启该功能后如果子级符合过滤标准,父级即使不符合仍然会保留 | boolean |  | **0.29.0** |
 | filterDropdown | 可以自定义筛选菜单,此函数只负责渲染图层,需要自行编写各种交互 | ReactNode |  |
 | filterDropdownProps | 透传给 Dropdown 的属性,详情点击[Dropdown API](/zh-CN/show/dropdown#Dropdown) | object |  |

+ 28 - 0
cypress/integration/table.spec.js

@@ -143,4 +143,32 @@ describe('table', () => {
         cy.get('.semi-table-row-head .semi-checkbox-checked');
         cy.get('.semi-checkbox-checked').should('have.length', 4);
     });
+
+    it('normal table ellipsis title', () => {
+        cy.visit('http://localhost:6006/iframe.html?id=table--ellipsis-normal-table&args=&viewMode=story');
+        cy.get('.semi-table-row-head-title').eq(0).should('have.attr', 'title');
+        cy.get('.semi-table-row-head-title').eq(1).should('have.attr', 'title');
+        cy.get('.semi-table-row-head-title').eq(2).should('have.attr', 'title');
+        cy.get('.semi-table-row-head-ellipsis').eq(3).should('have.attr', 'title');
+    });
+
+    it('fixed table ellipsis title', () => {
+        cy.visit('http://localhost:6006/iframe.html?id=table--ellipsis-fixed-table&args=&viewMode=story');
+        cy.get('.semi-table-row-head-title').eq(0).should('have.attr', 'title');
+        cy.get('.semi-table-row-head-title').eq(1).should('have.attr', 'title');
+        cy.get('.semi-table-row-head-title').eq(2).should('have.attr', 'title');
+        cy.get('.semi-table-row-head-ellipsis').eq(3).should('have.attr', 'title');
+    });
+
+    it('fixed table ellipsis showTitle false', () => {
+        cy.visit('http://localhost:6006/iframe.html?id=table--show-title-table&args=&viewMode=story');
+        cy.get('.semi-table-row-head-title').eq(0).should('not.have.attr', 'title');
+        cy.get('.semi-table-row-head-title').eq(1).should('not.have.attr', 'title');
+        cy.get('.semi-table-row-head-title').eq(2).should('not.have.attr', 'title');
+        cy.get('.semi-table-row-head-ellipsis').eq(3).should('not.have.attr', 'title');
+        cy.get('.semi-table-row-cell').eq(0).should('not.have.attr', 'title');
+        cy.get('.semi-table-row-cell').eq(1).should('not.have.attr', 'title');
+        cy.get('.semi-table-row-cell').eq(2).should('not.have.attr', 'title');
+        cy.get('.semi-table-row-cell').eq(3).should('not.have.attr', 'title');
+    });
 });

+ 6 - 2
packages/semi-foundation/table/foundation.ts

@@ -58,7 +58,8 @@ export interface BaseColumnProps<RecordType> {
     sorter?: BaseSorter<RecordType>;
     title?: any;
     useFullRender?: boolean;
-    width?: string | number
+    width?: string | number;
+    ellipsis?: BaseEllipsis
 }
 
 export interface TableAdapter<RecordType> extends DefaultAdapter {
@@ -103,7 +104,8 @@ export interface TableAdapter<RecordType> extends DefaultAdapter {
     getNormalizeColumns: () => (columns: BaseColumnProps<RecordType>[], children: any) => BaseColumnProps<RecordType>[];
     getHandleColumns: () => (queries: BaseColumnProps<RecordType>[], cachedColumns: BaseColumnProps<RecordType>[]) => BaseColumnProps<RecordType>[];
     getMergePagination: () => (pagination: BasePagination) => BasePagination;
-    setBodyHasScrollbar: (bodyHasScrollBar: boolean) => void
+    setBodyHasScrollbar: (bodyHasScrollBar: boolean) => void;
+    getTableLayout: () => 'fixed' | 'auto'
 }
 
 class TableFoundation<RecordType> extends BaseFoundation<TableAdapter<RecordType>> {
@@ -1257,4 +1259,6 @@ export interface BaseChangeInfoSorter<RecordType> {
 
 export type BaseIncludeGroupRecord<RecordType> = RecordType | { groupKey: string };
 
+export type BaseEllipsis = boolean | { showTitle: boolean };
+
 export default TableFoundation;

+ 25 - 5
packages/semi-foundation/table/table.scss

@@ -83,6 +83,11 @@ $module: #{$prefix}-table;
         }
     }
 
+    &-operate-wrapper {
+        display: flex;
+        justify-content: flex-start;
+    }
+
     &-body {
         overflow: auto;
         width: 100%;
@@ -115,8 +120,9 @@ $module: #{$prefix}-table;
                 padding-top: $spacing-table_row_head-paddingY;
                 padding-bottom: $spacing-table_row_head-paddingY;
                 vertical-align: middle;
-                word-break: break-all;
-                word-wrap: break-word;
+                overflow-wrap: break-word;
+                // word-break: break-all;
+                // word-wrap: break-word;
                 position: relative;
 
                 &.#{$module}-cell-fixed {
@@ -177,6 +183,14 @@ $module: #{$prefix}-table;
                     display: inline-flex;
                     align-items: center;
                 }
+
+                &-ellipsis {
+                    @include text-overflow-hidden;
+
+                    .#{$module}-row-head-title {
+                        @include text-overflow-hidden;
+                    }
+                }
             }
 
             .react-resizable {
@@ -241,8 +255,9 @@ $module: #{$prefix}-table;
 
             & > .#{$module}-row-cell {
                 display: table-cell;
-                word-wrap: break-word;
-                word-break: break-all;
+                overflow-wrap: break-word;
+                // word-wrap: break-word;
+                // word-break: break-all;
                 border-left: none;
                 border-right: none;
                 border-bottom: $width-table_base_border $border-table_base-borderStyle $color-table-border-default;
@@ -254,6 +269,10 @@ $module: #{$prefix}-table;
                 &.resizing {
                     border-right: $width-table_resizer_border solid $color-table_resizer-bg-default;
                 }
+
+                &-ellipsis {
+                    @include text-overflow-hidden;
+                }
             }
             &.#{$module}-row {
                 &-expand {
@@ -401,9 +420,10 @@ $module: #{$prefix}-table;
             text-align: center;
 
             &-wrapper {
-                display: inline-flex;
+                display: flex;
                 align-items: center;
                 cursor: pointer;
+                overflow: hidden;
             }
 
             &-up,

+ 6 - 0
packages/semi-foundation/table/utils.ts

@@ -18,6 +18,7 @@ import {
 import { strings, numbers } from './constants';
 import isNullOrUndefined from '../utils/isNullOrUndefined';
 import Logger from '../utils/Logger';
+import type { BaseEllipsis } from './foundation';
 
 
 export function equalWith(value: any, other: any, customizer?: (...args: any[]) => boolean) {
@@ -479,4 +480,9 @@ export function getRTLAlign(align: typeof strings.ALIGNS[number], direction?: 'l
         }
     }
     return align;
+}
+
+export function shouldShowEllipsisTitle(ellipsis: BaseEllipsis) {
+    const shouldShowTitle = ellipsis === true || get(ellipsis, 'showTitle', true);
+    return shouldShowTitle;
 }

+ 4 - 2
packages/semi-ui/table/Body/index.tsx

@@ -48,6 +48,7 @@ import {
 } from '../interface';
 
 export interface BodyProps extends BaseProps {
+    tableLayout?: 'fixed' | 'auto';
     anyColumnFixed?: boolean;
     columns?: ColumnProps[];
     dataSource?: Record<string, any>[];
@@ -405,7 +406,7 @@ class Body extends BaseComponent<BodyProps, BodyState> {
     };
 
     renderVirtualizedBody = (direction?: Direction) => {
-        const { scroll, prefixCls, virtualized, anyColumnFixed, columns } = this.props;
+        const { scroll, prefixCls, virtualized, columns } = this.props;
         const { virtualizedData } = this.state;
         const { getCellWidths } = this.context;
         const cellWidths = getCellWidths(columns);
@@ -745,6 +746,7 @@ class Body extends BaseComponent<BodyProps, BodyState> {
             onScroll,
             groups,
             expandedRowRender,
+            tableLayout,
         } = this.props;
 
         const x = get(scroll, 'x');
@@ -795,7 +797,7 @@ class Body extends BaseComponent<BodyProps, BodyState> {
                     aria-colcount={columns && columns.length}
                     style={tableStyle}
                     className={classnames(prefixCls, {
-                        [`${prefixCls}-fixed`]: anyColumnFixed,
+                        [`${prefixCls}-fixed`]: tableLayout === 'fixed',
                     })}
                 >
                     {colgroup}

+ 7 - 7
packages/semi-ui/table/HeadTable.tsx

@@ -6,11 +6,10 @@ import classnames from 'classnames';
 
 import ColGroup from './ColGroup';
 import TableHeader from './TableHeader';
-import { Fixed, TableComponents, Scroll, BodyScrollEvent, ColumnProps, OnHeaderRow } from './interface';
+import { Fixed, TableComponents, Scroll, BodyScrollEvent, ColumnProps, OnHeaderRow, Sticky } from './interface';
 
 export interface HeadTableProps {
-    [x: string]: any;
-    anyColumnFixed?: boolean;
+    tableLayout?: 'fixed' | 'auto';
     bodyHasScrollBar?: boolean;
     columns?: ColumnProps[];
     components?: TableComponents;
@@ -23,7 +22,8 @@ export interface HeadTableProps {
     selectedRowKeysSet: Set<any>;
     showHeader?: boolean;
     onDidUpdate?: (ref: React.MutableRefObject<any>) => void;
-    onHeaderRow?: OnHeaderRow<any>
+    onHeaderRow?: OnHeaderRow<any>;
+    sticky?: Sticky
 }
 
 /**
@@ -31,7 +31,7 @@ export interface HeadTableProps {
  */
 class HeadTable extends React.PureComponent<HeadTableProps> {
     static propTypes = {
-        anyColumnFixed: PropTypes.bool,
+        tableLayout: PropTypes.string,
         bodyHasScrollBar: PropTypes.bool,
         columns: PropTypes.array,
         components: PropTypes.object,
@@ -69,7 +69,7 @@ class HeadTable extends React.PureComponent<HeadTableProps> {
             components,
             onDidUpdate,
             showHeader,
-            anyColumnFixed,
+            tableLayout,
             bodyHasScrollBar,
             sticky
         } = this.props;
@@ -116,7 +116,7 @@ class HeadTable extends React.PureComponent<HeadTableProps> {
                 <Table
                     style={tableStyle}
                     className={classnames(prefixCls, {
-                        [`${prefixCls}-fixed`]: anyColumnFixed,
+                        [`${prefixCls}-fixed`]: tableLayout === 'fixed',
                     })}
                 >
                     {colgroup}

+ 39 - 6
packages/semi-ui/table/Table.tsx

@@ -33,7 +33,8 @@ import {
     isAnyFixedRight,
     assignColumnKeys,
     flattenColumns,
-    getAllDisabledRowKeys
+    getAllDisabledRowKeys,
+    shouldShowEllipsisTitle
 } from '@douyinfe/semi-foundation/table/utils';
 import Store from '@douyinfe/semi-foundation/utils/Store';
 import TableFoundation, { TableAdapter, BasePageData, BaseRowKeyType, BaseHeadWidth } from '@douyinfe/semi-foundation/table/foundation';
@@ -286,6 +287,16 @@ class Table<RecordType extends Record<string, any>> extends BaseComponent<Normal
 
                 return false;
             },
+            getTableLayout: () => {
+                let isFixed = false;
+                const { flattenColumns } = this.state;
+
+                if (Array.isArray(flattenColumns)) {
+                    isFixed = flattenColumns.some(column => (Boolean(column.ellipsis) || Boolean(column.fixed)));
+                }
+
+                return isFixed ? 'fixed' : 'auto';
+            },
             setHeadWidths: (headWidths: Array<BaseHeadWidth>, index = 0) => {
                 if (!equalWith(this.state.headWidths[index], headWidths)) {
                     // The map call depends on the last state
@@ -962,7 +973,9 @@ class Table<RecordType extends Record<string, any>> extends BaseComponent<Normal
       * @param {*} column
       */
     addFnsInColumn = (column: ColumnProps = {}) => {
+        const { prefixCls } = this.props;
         if (column && (column.sorter || column.filters || column.useFullRender)) {
+            let hasSorterOrFilter = false;
             const { dataIndex, title: rawTitle, useFullRender } = column;
             const curQuery = this.foundation.getQuery(dataIndex);
             const titleMap: ColumnTitleProps = {};
@@ -976,7 +989,16 @@ class Table<RecordType extends Record<string, any>> extends BaseComponent<Normal
             const stateSortOrder = get(curQuery, 'sortOrder');
             const defaultSortOrder = get(curQuery, 'defaultSortOrder', false);
             const sortOrder = this.foundation.isSortOrderValid(stateSortOrder) ? stateSortOrder : defaultSortOrder;
-            const TitleNode = typeof rawTitle !== 'function' && <React.Fragment key={strings.DEFAULT_KEY_COLUMN_TITLE}>{rawTitle as React.ReactNode}</React.Fragment>;
+            const showEllipsisTitle = shouldShowEllipsisTitle(column.ellipsis);
+            const TitleNode = typeof rawTitle !== 'function' && (
+                <span
+                    className={`${prefixCls}-row-head-title`}
+                    key={strings.DEFAULT_KEY_COLUMN_TITLE}
+                    title={showEllipsisTitle && typeof rawTitle === 'string' ? rawTitle : undefined}
+                >
+                    {rawTitle as React.ReactNode}
+                </span>
+            );
             if (typeof column.sorter === 'function' || column.sorter === true) {
                 // In order to increase the click hot area of ​​sorting, when sorting is required & useFullRender is false,
                 // both the title and sorting areas are used as the click hot area for sorting。
@@ -989,6 +1011,7 @@ class Table<RecordType extends Record<string, any>> extends BaseComponent<Normal
                     />
                 );
                 useFullRender && (titleMap.sorter = sorter);
+                hasSorterOrFilter = true;
                 titleArr.push(sorter);
             } else {
                 titleArr.push(TitleNode);
@@ -1003,17 +1026,25 @@ class Table<RecordType extends Record<string, any>> extends BaseComponent<Normal
                         key={strings.DEFAULT_KEY_COLUMN_FILTER}
                         {...curQuery}
                         filteredValue={filteredValue}
-                        onFilterDropdownVisibleChange={(visible: boolean) => this.foundation.toggleShowFilter(dataIndex, visible)}
+                        onFilterDropdownVisibleChange={(visible: boolean) =>
+                            this.foundation.toggleShowFilter(dataIndex, visible)
+                        }
                         onSelect={(data: OnSelectData) => this.foundation.handleFilterSelect(dataIndex, data)}
                     />
                 );
                 useFullRender && (titleMap.filter = filter);
+                hasSorterOrFilter = true;
                 titleArr.push(filter);
             }
 
             const newTitle =
-                typeof rawTitle === 'function' ?
-                    () => rawTitle(titleMap) : titleArr;
+                typeof rawTitle === 'function' ? (
+                    () => rawTitle(titleMap)
+                ) : hasSorterOrFilter ? (
+                    <div className={`${prefixCls}-operate-wrapper`}>{titleArr}</div>
+                ) : (
+                    titleArr
+                );
 
             column = { ...column, title: newTitle };
         }
@@ -1145,12 +1176,13 @@ class Table<RecordType extends Record<string, any>> extends BaseComponent<Normal
             sticky,
         } = props;
         const selectedRowKeysSet = get(rowSelection, 'selectedRowKeysSet', new Set());
+        const tableLayout = this.adapter.getTableLayout();
 
         const headTable =
             fixed || useFixedHeader ? (
                 <HeadTable
                     key="head"
-                    anyColumnFixed={anyColumnFixed}
+                    tableLayout={tableLayout}
                     ref={headerRef}
                     columns={filteredColumns}
                     prefixCls={prefixCls}
@@ -1178,6 +1210,7 @@ class Table<RecordType extends Record<string, any>> extends BaseComponent<Normal
                 handleWheel={this.handleWheel}
                 handleBodyScroll={this.handleBodyScroll}
                 anyColumnFixed={anyColumnFixed}
+                tableLayout={tableLayout}
                 includeHeader={includeHeader}
                 showHeader={showHeader}
                 scroll={scroll}

+ 13 - 2
packages/semi-ui/table/TableCell.tsx

@@ -7,7 +7,7 @@ import { get, noop, set, omit, isEqual, merge } from 'lodash';
 
 import { cssClasses, numbers } from '@douyinfe/semi-foundation/table/constants';
 import TableCellFoundation, { TableCellAdapter } from '@douyinfe/semi-foundation/table/cellFoundation';
-import { isSelectionColumn, isExpandedColumn, getRTLAlign } from '@douyinfe/semi-foundation/table/utils';
+import { isSelectionColumn, isExpandedColumn, getRTLAlign, shouldShowEllipsisTitle } from '@douyinfe/semi-foundation/table/utils';
 
 import BaseComponent, { BaseProps } from '../_base/baseComponent';
 import Context, { TableContextProps } from './table-context';
@@ -325,7 +325,7 @@ export default class TableCell extends BaseComponent<TableCellProps, Record<stri
         } = this.props;
         const { direction } = this.context;
         const isRTL = direction === 'rtl';
-        const { className } = column;
+        const { className, ellipsis } = column;
         const fixedLeftFlag = fixedLeft || typeof fixedLeft === 'number';
         const fixedRightFlag = fixedRight || typeof fixedRight === 'number';
         const { tdProps, customCellProps } = this.getTdProps();
@@ -334,6 +334,15 @@ export default class TableCell extends BaseComponent<TableCellProps, Record<stri
         let { text } = renderTextResult;
         const { indentText, rowSpan, colSpan, realExpandIcon, tdProps: newTdProps } = renderTextResult;
 
+        let title: string;
+
+        const shouldShowTitle = shouldShowEllipsisTitle(ellipsis);
+        if (shouldShowTitle) {
+            if (typeof text === 'string') {
+                title = text;
+            }
+        }
+
         if (rowSpan === 0 || colSpan === 0) {
             return null;
         }
@@ -367,6 +376,7 @@ export default class TableCell extends BaseComponent<TableCellProps, Record<stri
                 [`${prefixCls}-cell-fixed-left-last`]: isFixedLeftLast,
                 [`${prefixCls}-cell-fixed-right`]: isFixedRight,
                 [`${prefixCls}-cell-fixed-right-first`]: isFixedRightFirst,
+                [`${prefixCls}-row-cell-ellipsis`]: ellipsis,
             }
         );
 
@@ -376,6 +386,7 @@ export default class TableCell extends BaseComponent<TableCellProps, Record<stri
                 aria-colindex={colIndex + 1}
                 className={columnCls}
                 onClick={this.handleClick}
+                title={title}
                 {...newTdProps}
                 ref={this.setRef}
             >

+ 12 - 3
packages/semi-ui/table/TableHeader.tsx

@@ -1,9 +1,11 @@
 /* eslint-disable max-len */
 import React, { ReactNode } from 'react';
-import BaseComponent, { BaseProps } from '../_base/baseComponent';
+import { noop, isFunction, get } from 'lodash';
 import PropTypes from 'prop-types';
+
+import BaseComponent, { BaseProps } from '../_base/baseComponent';
 import { strings, cssClasses } from '@douyinfe/semi-foundation/table/constants';
-import { noop, isFunction } from 'lodash';
+import { shouldShowEllipsisTitle } from '@douyinfe/semi-foundation/table/utils';
 import TableHeaderRow from './TableHeaderRow';
 import { Fixed, TableComponents, OnHeaderRow } from './interface';
 
@@ -61,6 +63,12 @@ function parseHeaderRows(columns: any[]) {
 
             currentColIndex += colSpan;
 
+            const ellipsis = column?.ellipsis;
+            const shouldShowTitle = shouldShowEllipsisTitle(ellipsis);
+            if (shouldShowTitle && typeof cell.children === 'string') {
+                cell.title = cell.children;
+            }
+
             return colSpan;
         });
 
@@ -177,7 +185,8 @@ export interface TableHeaderCell {
     hasSubColumns?: boolean;
     rowSpan?: number;
     colSpan?: number;
-    colEnd?: number
+    colEnd?: number;
+    title?: string
 }
 
 export default React.forwardRef<HTMLDivElement, Omit<TableHeaderProps, 'forwardedRef'>>((props, ref) => <TableHeader {...props} forwardedRef={ref} />);

+ 1 - 0
packages/semi-ui/table/TableHeaderRow.tsx

@@ -148,6 +148,7 @@ export default class TableHeaderRow extends BaseComponent<TableHeaderRowProps, R
                     [`${prefixCls}-cell-fixed-left-last`]: fixedLeftLast,
                     [`${prefixCls}-cell-fixed-right`]: fixedRight,
                     [`${prefixCls}-cell-fixed-right-first`]: fixedRightFirst,
+                    [`${prefixCls}-row-head-ellipsis`]: column.ellipsis,
                 }
             );
 

+ 101 - 0
packages/semi-ui/table/_story/v2/FeatEllipsis/fixedTable.tsx

@@ -0,0 +1,101 @@
+import React from 'react';
+import { Table } from '@douyinfe/semi-ui';
+
+App.storyName = 'ellipsis - fixed table';
+/**
+ * test with cypress
+ */
+export default function App() {
+    const columns = [
+        {
+            title: '标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题',
+            dataIndex: 'name',
+            fixed: true,
+            width: 300,
+            filters: [
+                {
+                    text: 'Semi Design 设计稿',
+                    value: 'Semi Design 设计稿',
+                },
+                {
+                    text: 'Semi Pro 设计稿',
+                    value: 'Semi Pro 设计稿',
+                },
+            ],
+            onFilter: (value, record) => record.name.includes(value),
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+            ellipsis: true,
+        },
+        {
+            title: '所有者',
+            dataIndex: 'owner',
+            width: 300,
+            ellipsis: true,
+            filters: [
+                {
+                    text: 'Semi Design 设计稿',
+                    value: 'Semi Design 设计稿',
+                },
+                {
+                    text: 'Semi Pro 设计稿',
+                    value: 'Semi Pro 设计稿',
+                },
+            ],
+            onFilter: (value, record) => record.name.includes(value),
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+        },
+        {
+            title: '大小大小大小大小大小大小大小大小大小大小大小大小大小大小',
+            dataIndex: 'size',
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+            ellipsis: true,
+        },
+        {
+            title: '更新日期',
+            dataIndex: 'updateTime',
+            width: 300,
+            fixed: 'right',
+            ellipsis: true,
+        },
+    ];
+    const data = [
+        {
+            key: '1',
+            name: 'Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png',
+            size: '2M',
+            owner: 'Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'grey',
+        },
+        {
+            key: '2',
+            name: 'Semi is designed based on FA architecture, and the main logic is extracted as Foundation package, which is easy to migrate to other frameworks',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '2M',
+            owner: 'Semi is designed based on FA architecture, and the main logic is extracted as Foundation package, which is easy to migrate to other frameworks',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'red',
+        },
+        {
+            key: '3',
+            name: '由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '34KB',
+            owner: 'LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件 LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件 LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'light-blue',
+        },
+        {
+            key: '4',
+            name: '由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '34KB',
+            owner: 'LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件 LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件 LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'light-blue',
+        },
+    ];
+
+    return <Table style={{ width: 1000 }} scroll={{ x: 1200 }} columns={columns} dataSource={data} pagination={false} />;
+}

+ 3 - 0
packages/semi-ui/table/_story/v2/FeatEllipsis/index.ts

@@ -0,0 +1,3 @@
+export { default as EllipsisFixedTable } from './fixedTable';
+export { default as EllipsisNormalTable } from './normalTable';
+export { default as ShowTitleTable } from './showTitle';

+ 107 - 0
packages/semi-ui/table/_story/v2/FeatEllipsis/normalTable.tsx

@@ -0,0 +1,107 @@
+import React from 'react';
+import { Table, Space } from '@douyinfe/semi-ui';
+
+App.storyName = 'ellipsis - normal table';
+/**
+ * test with cypress
+ */
+export default function App() {
+    const columns = [
+        {
+            title: '标题标题标题标题标题标题标题标题',
+            dataIndex: 'name',
+            ellipsis: true,
+            filters: [
+                {
+                    text: 'Semi Design 设计稿',
+                    value: 'Semi Design 设计稿',
+                },
+                {
+                    text: 'Semi Pro 设计稿',
+                    value: 'Semi Pro 设计稿',
+                },
+            ],
+            onFilter: (value, record) => record.name.includes(value),
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+        },
+        {
+            title: '所有者',
+            dataIndex: 'owner',
+            ellipsis: true,
+            filters: [
+                {
+                    text: 'Semi Design 设计稿',
+                    value: 'Semi Design 设计稿',
+                },
+                {
+                    text: 'Semi Pro 设计稿',
+                    value: 'Semi Pro 设计稿',
+                },
+            ],
+            onFilter: (value, record) => record.name.includes(value),
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+        },
+        {
+            title: '大小大小大小大小大小大小大小大小大小大小大小大小大小大小',
+            dataIndex: 'size',
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+            ellipsis: true,
+        },
+        {
+            title: '更新日期',
+            dataIndex: 'updateTime',
+            ellipsis: true,
+        },
+    ];
+    const data = [
+        {
+            key: '1',
+            name: 'Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png',
+            size: '2M',
+            owner: 'Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'grey',
+        },
+        {
+            key: '2',
+            name: 'Semi is designed based on FA architecture, and the main logic is extracted as Foundation package, which is easy to migrate to other frameworks',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '2M',
+            owner: 'Semi is designed based on FA architecture, and the main logic is extracted as Foundation package, which is easy to migrate to other frameworks',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'red',
+        },
+        {
+            key: '3',
+            name: '由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '34KB',
+            owner: 'LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件 LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件 LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'light-blue',
+        },
+        {
+            key: '4',
+            name: '由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '34KB',
+            owner: 'LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件 LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件 LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'light-blue',
+        },
+    ];
+
+    return (
+        <Space vertical align='start'>
+            <div>
+                <h4>宽度 800</h4>
+                <Table style={{ width: 800 }} columns={columns} dataSource={data} pagination={false} />
+            </div>
+            <div>
+                <h4>无宽度</h4>
+                <Table columns={columns} dataSource={data} pagination={false} />
+            </div>
+        </Space>
+    );
+}

+ 105 - 0
packages/semi-ui/table/_story/v2/FeatEllipsis/showTitle.tsx

@@ -0,0 +1,105 @@
+import React from 'react';
+import { Table, Typography } from '@douyinfe/semi-ui';
+import { ColumnProps } from '../../../interface';
+
+App.storyName = 'ellipsis - showTitle';
+/**
+ * test with cypress
+ */
+export default function App() {
+    const columns: ColumnProps[] = [
+        {
+            title: '标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题',
+            dataIndex: 'name',
+            fixed: true,
+            width: 300,
+            filters: [
+                {
+                    text: 'Semi Design 设计稿',
+                    value: 'Semi Design 设计稿',
+                },
+                {
+                    text: 'Semi Pro 设计稿',
+                    value: 'Semi Pro 设计稿',
+                },
+            ],
+            onFilter: (value, record) => record.name.includes(value),
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+            render: (text) => <Typography.Text ellipsis={{ showTooltip: true }}>{text}</Typography.Text>,
+            ellipsis: { showTitle: false },
+        },
+        {
+            title: '所有者',
+            dataIndex: 'owner',
+            width: 300,
+            filters: [
+                {
+                    text: 'Semi Design 设计稿',
+                    value: 'Semi Design 设计稿',
+                },
+                {
+                    text: 'Semi Pro 设计稿',
+                    value: 'Semi Pro 设计稿',
+                },
+            ],
+            onFilter: (value, record) => record.name.includes(value),
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+            render: (text) => <Typography.Text ellipsis={{ showTooltip: true }}>{text}</Typography.Text>,
+            ellipsis: { showTitle: false },
+        },
+        {
+            title: '大小大小大小大小大小大小大小大小大小大小大小大小大小大小',
+            dataIndex: 'size',
+            sorter: (a, b) => (a.name.length - b.name.length > 0 ? 1 : -1),
+            render: (text) => <Typography.Text ellipsis={{ showTooltip: true }}>{text}</Typography.Text>,
+            ellipsis: { showTitle: false },
+        },
+        {
+            title: '更新日期',
+            dataIndex: 'updateTime',
+            width: 300,
+            fixed: 'right' as const,
+            ellipsis: { showTitle: false },
+        },
+    ];
+    const data = [
+        {
+            key: '1',
+            name: 'Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png',
+            size: '2M',
+            owner: 'Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'grey',
+        },
+        {
+            key: '2',
+            name: 'Semi is designed based on FA architecture, and the main logic is extracted as Foundation package, which is easy to migrate to other frameworks',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '2M',
+            owner: 'Semi is designed based on FA architecture, and the main logic is extracted as Foundation package, which is easy to migrate to other frameworks',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'red',
+        },
+        {
+            key: '3',
+            name: '由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '34KB',
+            owner: 'LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件 LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件 LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'light-blue',
+        },
+        {
+            key: '4',
+            name: '由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '34KB',
+            owner: 'LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件 LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件 LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'light-blue',
+        },
+    ];
+
+    return <Table style={{ width: 1000 }} scroll={{ x: 1200 }} columns={columns} dataSource={data} pagination={false} />;
+}

+ 60 - 0
packages/semi-ui/table/_story/v2/FeatWordBreak/fixedTable.jsx

@@ -0,0 +1,60 @@
+import React from 'react';
+import { Table } from '@douyinfe/semi-ui';
+
+App.storyName = 'word break - fixed table';
+export default function App() {
+    const columns = [
+        {
+            title: '标题',
+            dataIndex: 'name',
+            fixed: true,
+            width: 300,
+        },
+        {
+            title: '所有者',
+            dataIndex: 'owner',
+            width: 300,
+        },
+        {
+            title: '大小',
+            dataIndex: 'size',
+        },
+        {
+            title: '更新日期',
+            dataIndex: 'updateTime',
+            width: 300,
+            fixed: 'right',
+        },
+    ];
+    const data = [
+        {
+            key: '1',
+            name: 'Maintained by the Douyin front-end and UED teams, an easy-to-customize modern design system that helps designers and developers create high-quality products.',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png',
+            size: '2M',
+            owner: 'Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'grey',
+        },
+        {
+            key: '2',
+            name: 'Semi is designed based on FA architecture, and the main logic is extracted as Foundation package, which is easy to migrate to other frameworks',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '2M',
+            owner: 'Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'red',
+        },
+        {
+            key: '3',
+            name: 'Semi uses a variety of methods such as unit testing to ensure the stability and quality of components, and the code coverage rate reaches 90%',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '34KB',
+            owner: 'Zoey Edwards Zoey Edwards Zoey Edwards Zoey Edwards Zoey Edwards Zoey Edwards Zoey Edwards Zoey Edwards Zoey Edwards',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'light-blue',
+        },
+    ];
+
+    return <Table style={{ width: 1000 }} scroll={{ x: 1200 }} columns={columns} dataSource={data} pagination={false} />;
+}

+ 2 - 0
packages/semi-ui/table/_story/v2/FeatWordBreak/index.ts

@@ -0,0 +1,2 @@
+export { default as WordBreakFixedTable } from './fixedTable';
+export { default as WordBreakNormalTable } from './normalTable';

+ 77 - 0
packages/semi-ui/table/_story/v2/FeatWordBreak/normalTable.tsx

@@ -0,0 +1,77 @@
+import React from 'react';
+import { Table, Space } from '@douyinfe/semi-ui';
+
+App.storyName = 'word break - normal table';
+export default function App() {
+    const columns = [
+        {
+            title: '标题',
+            dataIndex: 'name',
+            width: 300,
+        },
+        {
+            title: '所有者',
+            dataIndex: 'owner',
+        },
+        {
+            title: '大小',
+            dataIndex: 'size',
+        },
+        {
+            title: '更新日期',
+            dataIndex: 'updateTime',
+            width: 300,
+        },
+    ];
+    const data = [
+        {
+            key: '1',
+            name: 'Maintained by the Douyin front-end and UED teams, an easy-to-customize modern design system that helps designers and developers create high-quality products.',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png',
+            size: '2M',
+            owner: 'Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'grey',
+        },
+        {
+            key: '2',
+            name: 'Semi is designed based on FA architecture, and the main logic is extracted as Foundation package, which is easy to migrate to other frameworks',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '2M',
+            owner: 'Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi_Jiang_Pengzhi',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'red',
+        },
+        {
+            key: '3',
+            name: '由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '34KB',
+            owner: 'LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件 LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件 LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'light-blue',
+        },
+        {
+            key: '4',
+            name: '由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。由抖音前端与 UED 团队维护,易于定制的现代化设计系统,帮助设计师与开发者打造高质量产品。',
+            nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
+            size: '34KB',
+            owner: 'LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件 LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件 LiveCode 允许你使用在线代码编辑器即时演示你的 UI 组件',
+            updateTime: '2020-02-02 05:13',
+            avatarBg: 'light-blue',
+        },
+    ];
+
+    return (
+        <Space vertical align='start'>
+            <div>
+                <h4>宽度 800</h4>
+                <Table style={{ width: 800 }} columns={columns} dataSource={data} pagination={false} />
+            </div>
+            <div>
+                <h4>无宽度</h4>
+                <Table columns={columns} dataSource={data} pagination={false} />
+            </div>
+        </Space>
+    );
+}

+ 10 - 42
packages/semi-ui/table/_story/v2/columnAlign.tsx

@@ -1,56 +1,24 @@
 import React from 'react';
-import { Table, Avatar, Space } from '../../../index';
-import { ColumnProps, Direction } from '../../../table/interface';
+import { Table } from '@douyinfe/semi-ui';
 
-export default function App(props: { direction?: Direction }) {
-    const { direction } = props;
-    const columns: ColumnProps[] = [
+export default function App() {
+    const columns = [
         {
-            title: '标题 align left + fixed left',
+            title: '标题',
             dataIndex: 'name',
-            render: (text, record, index) => {
-                return (
-                    <Space spacing={12}>
-                        <Avatar
-                            size="small"
-                            shape="square"
-                            src={record.nameIconSrc}
-                        ></Avatar>
-                        {text}
-                    </Space>
-                );
-            },
-            align: 'left',
-            fixed: 'left',
-            width: 300
         },
         {
-            title: '大小 align center',
+            title: '大小',
             dataIndex: 'size',
-            align: 'center',
-            width: 200,
         },
         {
-            title: '所有者 align right',
+            title: '所有者',
             dataIndex: 'owner',
-            render: (text, record, index) => {
-                return (
-                    <Space spacing={4}>
-                        <Avatar size="small" color={record.avatarBg}>
-                            {typeof text === 'string' && text.slice(0, 1)}
-                        </Avatar>
-                        {text}
-                    </Space>
-                );
-            },
-            align: 'right',
         },
         {
-            title: '更新日期 align default + fixed right',
+            title: '更新日期',
             dataIndex: 'updateTime',
-            width: 200,
-            fixed: 'right',
-        }
+        },
     ];
     const data = [
         {
@@ -82,5 +50,5 @@ export default function App(props: { direction?: Direction }) {
         },
     ];
 
-    return <Table direction={direction} bordered columns={columns} dataSource={data} scroll={{ y: 300, x: 1200 }} pagination={false} />;
-}
+    return <Table columns={columns} dataSource={data} pagination={false} />;
+}

+ 3 - 1
packages/semi-ui/table/_story/v2/index.js

@@ -14,4 +14,6 @@ export { default as stickyHeaderTable } from './stickyHeader';
 export { default as Fixed1188 } from './Fixed1188';
 export { default as EmptyFilters } from './emptyFilters';
 export { default as fixedResizableWithForm } from './fixedResizableWithForm';
-export { default as zebra } from './zebra';
+export { default as zebra } from './zebra';
+export { WordBreakNormalTable, WordBreakFixedTable } from './FeatWordBreak';
+export { EllipsisNormalTable, EllipsisFixedTable, ShowTitleTable } from './FeatEllipsis';

+ 4 - 2
packages/semi-ui/table/interface.ts

@@ -19,7 +19,8 @@ import {
     BaseSorter,
     BaseFilter,
     BaseChangeInfoFilter,
-    BaseIncludeGroupRecord
+    BaseIncludeGroupRecord,
+    BaseEllipsis
 } from '@douyinfe/semi-foundation/table/foundation';
 import { ScrollDirection, CSSDirection } from 'react-window';
 
@@ -104,7 +105,8 @@ export interface ColumnProps<RecordType extends Record<string, any> = any> {
     onCell?: OnCell<RecordType>;
     onFilter?: OnFilter<RecordType>;
     onFilterDropdownVisibleChange?: OnFilterDropdownVisibleChange;
-    onHeaderCell?: OnHeaderCell<RecordType>
+    onHeaderCell?: OnHeaderCell<RecordType>;
+    ellipsis?: BaseEllipsis
 }
 
 export type Align = BaseAlign;