Переглянути джерело

fix: Modify the implementation of slashes & support dropdownProps settings

zhangyumei.0319 1 рік тому
батько
коміт
b092971f02

+ 41 - 2
content/navigation/tabs/index-en-US.md

@@ -18,7 +18,7 @@ import { Tabs, TabPane } from '@douyinfe/semi-ui';
 
 ### Basic Usage
 
-Tbs supports three types of styles: `line`, `button`, and `card`. By default, the first tab is selected.
+Tbs supports three types of styles: `line`, `button`, `card`, and `slash`. By default, the first tab is selected.
 
 Tabs supports two declare ways, and the rendering process of the two is different:
 
@@ -168,6 +168,44 @@ class TabDemo extends React.Component {
 }
 ```
 
+```jsx live=true
+import React from 'react';
+import { Tabs } from '@douyinfe/semi-ui';
+
+class TabDemo extends React.Component {
+    constructor() {
+        super();
+        this.state = { key: '1' };
+        this.onTabClick = this.onTabClick.bind(this);
+    }
+
+    onTabClick(key, type) {
+        this.setState({ [type]: key });
+    }
+
+    render() {
+        // eslint-disable-next-line react/jsx-key
+        const contentList = [<div>Document</div>, <div>Quick Start</div>, <div>Help</div>];
+        const tabList = [
+            { tab: 'Document', itemKey: '1' },
+            { tab: 'Quick Start', itemKey: '2' },
+            { tab: 'Help', itemKey: '3' },
+        ];
+        return (
+            <Tabs
+                type="slash"
+                tabList={tabList}
+                onChange={key => {
+                    this.onTabClick(key, 'key');
+                }}
+            >
+                {contentList[this.state.key - 1]}
+            </Tabs>
+        );
+    }
+}
+```
+
 ### With Icon
 
 ```jsx live=true
@@ -274,7 +312,7 @@ function Demo() {
 
 ### Vertical mode
 
-Support two positions: `tabPosition='left|top'`
+When `type` is `line`, `card`, or `button`, horizontal and vertical modes are supported, `tabPosition='left|top'`,default is top. When `type` is `slash`, only horizontal mode is supported.
 
 ```jsx live=true
 import React from 'react';
@@ -703,6 +741,7 @@ class App extends React.Component {
 | activeKey | The itemKey value of the currently active tab page | string | None |
 | className | class name | string | None |
 | collapsible | collapsed Tabs, **>=1.1.0** | boolean | false |
+| dropdownProps | In collapsible mode, It is used to transparently transmit parameters to the Dropdown component of the drop-down menu, support since 2.65.0 | DropDownProps | { start: DropdownProps, end: DropdownProps } |
 | visibleTabsStyle | Overall scrolling area style **>=2.61.0** | style: CSSProperties | None |
 | contentStyle | The outer style object of the content area | CSSProperties | None |
 | defaultActiveKey | Initialize the key value of the selected tab page | string | '1' |

+ 42 - 3
content/navigation/tabs/index.md

@@ -17,7 +17,7 @@ import { Tabs, TabPane } from '@douyinfe/semi-ui';
 
 ### 基本用法
 
-标签栏支持三种样式的显示:线条式,按钮式,卡片式。默认选中第一项。  
+标签栏支持三种样式的显示:线条式,按钮式,卡片式,斜线式。默认选中第一项。  
 标签页支持两种传入方式,两者渲染流程上有所区别:
 
 -   通过 `tabList` 传入标签页对象的数组,当使用 `tabList` 时每次只渲染当前传入的节点
@@ -153,6 +153,44 @@ class TabDemo extends React.Component {
 }
 ```
 
+```jsx live=true
+import React from 'react';
+import { Tabs } from '@douyinfe/semi-ui';
+
+class TabDemo extends React.Component {
+    constructor() {
+        super();
+        this.state = { key: '1' };
+        this.onTabClick = this.onTabClick.bind(this);
+    }
+
+    onTabClick(key, type) {
+        this.setState({ [type]: key });
+    }
+
+    render() {
+        // eslint-disable-next-line react/jsx-key
+        const contentList = [<div>文档</div>, <div>快速起步</div>, <div>帮助</div>];
+        const tabList = [
+            { tab: '文档', itemKey: '1' },
+            { tab: '快速起步', itemKey: '2' },
+            { tab: '帮助', itemKey: '3' },
+        ];
+        return (
+            <Tabs
+                type="slash"
+                tabList={tabList}
+                onChange={key => {
+                    this.onTabClick(key, 'key');
+                }}
+            >
+                {contentList[this.state.key - 1]}
+            </Tabs>
+        );
+    }
+}
+```
+
 ### 带图标的
 
 有图标的标签栏。
@@ -257,7 +295,7 @@ function Demo() {
 
 ### 垂直的标签栏
 
-支持水平和垂直两种模式, `tabPosition='left|top'`
+`type` 为 `line`, `card`, `button` 支持水平和垂直两种模式,`tabPosition='left|top'`, 默认为 `top`。`type` 为 `slash` 仅支持水平模式,无需设置。
 
 ```jsx live=true
 import React from 'react';
@@ -720,6 +758,7 @@ class App extends React.Component {
 | arrowPosition | 折叠模式下,左右切换箭头渲染位置 **>=2.61.0** | "start" "end" "both" | 无 |
 | className | 类名 | string | 无 |
 | collapsible | 折叠的 Tabs,**>=1.1.0** | boolean | false |
+| dropdownProps | 用于在折叠模式下透传参数到下拉菜单的 Dropdown 组件 | { start: DropdownProps, end: DropdownProps } | 无 |
 | visibleTabsStyle | 整体滚动区域 Style **>=2.61.0** | style: CSSProperties | 无 |
 | contentStyle | 内容区域外层样式对象 | CSSProperties | 无 |
 | defaultActiveKey | 初始化选中的 tab 页的 key 值 | string | '1' |
@@ -736,7 +775,7 @@ class App extends React.Component {
 | tabList | 标签页对象组成的数组,该对象支持 itemKey(对应 activeKey,tab(标签页文字)及 icon(标签页图标) | TabPane[] | 无 |
 | tabPaneMotion | 是否使用动画切换 tabs | boolean | true |
 | tabPosition | tab 的位置,支持`top`(水平), `left`(垂直) | string | `top` |
-| type | 标签栏的样式,可选`line`、 `card`、 `button` | string | `line` |
+| type | 标签栏的样式,可选`line`、 `card`、 `button`、`slash` | string | `line` |
 | onChange | 切换 tab 页时的回调函数 | function(activeKey: string) | 无 |
 | onTabClick | 单击事件 | function(key: string, e: Event) | 无 |
 | onTabClose | 关闭 tab 页时的回调函数 **>=2.1.0** | function(tabKey: string) | 无 |

+ 11 - 3
packages/semi-foundation/tabs/tabs.scss

@@ -608,10 +608,18 @@ $ignoreIcon: '.#{$prefix}-icon-checkbox_tick, .#{$prefix}-icon-radio, .#{$prefix
                 margin-right: $spacing-tabs_bar_slash-marginRight;
 
                 &:after {  
-                    content: "/";
-                    font-weight:  $font-tabs_tab_slash_line-fontWeight;
+                    content: "";
                     margin-left: $spacing-tabs_bar_slash_line_marginLeft;
-                    color: $color-tabs_tab_slash_line;
+                    display: inline-block;
+                    height: $height-tabs_tab_slash_line;
+                    width: $width-tabs_tab_slash_line;
+                    margin-top: $spacing-tabs_bar_slash_line_marginTop;
+                    margin-bottom: $spacing-tabs_bar_slash_line_marginBottom;
+                    vertical-align: bottom;
+                    // Get diagonal slash
+                    background: linear-gradient(to bottom right, transparent 0%, 
+                        transparent calc(50% - 1px), $color-tabs_tab_slash_line 50%,
+                        transparent calc(50% + 1px), transparent 100%);
                 }
             }
         }

+ 6 - 2
packages/semi-foundation/tabs/variables.scss

@@ -65,8 +65,7 @@ $color-tabs_tab-pane_arrow_disabled-bg-hover:  transparent;
 $color-tabs_tab-pane_arrow_disabled-text-default: var(--semi-color-disabled-text);
 $color-tabs_tab-pane_arrow_disabled-text-hover:  var(--semi-color-disabled-text);
 
-$color-tabs_tab_slash_line: var(--semi-color-text-2); //斜线式页签分割线字体颜色
-$font-tabs_tab_slash_line-fontWeight: $font-weight-regular; //斜线式页签分割线字重
+$color-tabs_tab_slash_line: var(--semi-color-text-2); //斜线式页签分割线颜色
 
 $font-tabs_tab-fontWeight: $font-weight-regular; // 页签文本字重 - 默认
 $font-tabs_tab_active-fontWeight: $font-weight-bold; // 页签文本字重 - 选中
@@ -82,6 +81,9 @@ $width-tabs-outline-offset: -2px; // 聚焦轮廓偏移宽度
 $width-tabs_bar_line-outline-offset: -1px; // 线条式页签聚焦轮廓偏移宽度
 $width-tabs_tab-pane_arrow-border:0px; // 滚动折叠箭头边框宽度
 
+$width-tabs_tab_slash_line: 8px; // 斜线式页签分割线宽度
+$height-tabs_tab_slash_line: 14px; // 斜线式页签分割线高度
+
 $height-tabs_bar_extra_large: 50px; // 大尺寸页签高度
 $font-tabs_bar_extra_large-lineHeight: $height-tabs_bar_extra_large; // 大尺寸页签文字行高
 
@@ -125,6 +127,8 @@ $spacing-tabs_bar_slash_tab-paddingY: 12px; // 斜线式页签上下内边距
 $spacing-tabs_bar_slash_tab-paddingX: 0px; // 斜线式页签水平内边距
 $spacing-tabs_bar_slash-marginRight: 16px; // 斜线式页签右侧外边距
 $spacing-tabs_bar_slash_line_marginLeft: 16px; // 斜线式页签斜线左侧外边距
+$spacing-tabs_bar_slash_line_marginTop: 3px; // 斜线式页签斜线顶部外边距
+$spacing-tabs_bar_slash_line_marginBottom: 3px; // 斜线式页签斜线底部外边距
 
 $spacing-tabs_content-paddingY: 5px; // 页签内容区垂直方向内边距
 $spacing-tabs_content-paddingX: 0; // 页签内容区水平方向内边距

+ 4 - 1
packages/semi-ui/tabs/TabBar.tsx

@@ -161,7 +161,7 @@ class TabBar extends React.Component<TabBarProps, TabBarState> {
                 </div>
             );
         }
-        const { dropdownClassName, dropdownStyle, showRestInDropdown } = this.props;
+        const { dropdownClassName, dropdownStyle, showRestInDropdown, dropdownProps } = this.props;
         const { rePosKey } = this.state;
         const disabled = !items.length;
         const menu = (
@@ -197,6 +197,8 @@ class TabBar extends React.Component<TabBarProps, TabBarState> {
             [`${cssClasses.TABS_BAR}-dropdown`]: true,
         });
 
+        const customDropdownProps = dropdownProps?.[pos] ?? {};
+
         return (
             <>
                 {showRestInDropdown ? (
@@ -211,6 +213,7 @@ class TabBar extends React.Component<TabBarProps, TabBarState> {
                         style={dropdownStyle}
                         trigger={'hover'}
                         disableFocusListener // prevent the panel from popping up again after clicking
+                        {...customDropdownProps}
                     >
                         {button}
                     </Dropdown>

+ 7 - 9
packages/semi-ui/tabs/_story/tabs.stories.jsx

@@ -366,7 +366,7 @@ Level2Card.story = {
 export const SlashTab = () => {
   return (
   <>
-    <Tabs defaultActiveKey="1" type="slash" >
+    <Tabs defaultActiveKey="1" type="slash">
       <TabPane tab="文档" itemKey="1">文档</TabPane>
       <TabPane tab="快速起步" itemKey="2" disabled>快速起步</TabPane>
       <TabPane tab="帮助" itemKey="3">帮助</TabPane>
@@ -376,16 +376,14 @@ export const SlashTab = () => {
     <br />
     <br />
     <Tabs defaultActiveKey="1" type="slash">
-    <TabPane tab="文档" itemKey="1">文档</TabPane>
-      <TabPane tab="快速起步" itemKey="2" disabled>快速起步</TabPane>
-      <TabPane tab="帮助" itemKey="3">帮助</TabPane>
-      <TabPane tab="关于" itemKey="4">关于</TabPane>
-      <TabPane tab="资源工具" itemKey="5">资源工具</TabPane>
+      <TabPane tab={<span><IconFile />文档</span>} itemKey="1">文档</TabPane>
+      <TabPane tab={<span><IconGlobe />快速起步</span>} itemKey="2" disabled>快速起步</TabPane>
+      <TabPane tab={<span><IconHelpCircle />帮助</span>} itemKey="3">帮助</TabPane>
     </Tabs>
     <br />
-    <Tabs style={{ width: '400px'}} type="slash" collapsible>
-          {['文档', "快速起步", "帮助", "关于", "资源工具"].map((i, index) => (
-              <TabPane tab={`tab-${index}`} itemKey={i} key={i} >
+    <Tabs style={{ width: '400px'}} type="slash" collapsible dropdownProps={{ start: { showTick: false}, end: { showTick: false}}}>
+          {['文档', "快速起步", "帮助", "关于", "资源工具", "主页"].map((i, index) => (
+              <TabPane tab={i} itemKey={i} key={i} >
                   Content of card tab {i}
               </TabPane>
           ))}

+ 4 - 1
packages/semi-ui/tabs/index.tsx

@@ -56,6 +56,7 @@ class Tabs extends BaseComponent<TabsProps, TabsState> {
         more: PropTypes.oneOfType([PropTypes.number, PropTypes.object]),
         arrowPosition: PropTypes.string,
         renderArrow: PropTypes.func,
+        dropdownProps: PropTypes.object,
     };
     static __SemiComponentName__ = "Tabs";
     static defaultProps: TabsProps = getDefaultPropsFromGlobalConfig(Tabs.__SemiComponentName__, {
@@ -265,6 +266,7 @@ class Tabs extends BaseComponent<TabsProps, TabsState> {
             visibleTabsStyle,
             arrowPosition,
             renderArrow,
+            dropdownProps,
             ...restProps
         } = this.props;
         const { panes, activeKey } = this.state;
@@ -296,7 +298,8 @@ class Tabs extends BaseComponent<TabsProps, TabsState> {
             onVisibleTabsChange,
             visibleTabsStyle,
             arrowPosition,
-            renderArrow
+            renderArrow,
+            dropdownProps,
         } as TabBarProps;
 
         const tabBar = renderTabBar ? renderTabBar(tabBarProps, TabBar) : <TabBar {...tabBarProps} />;

+ 8 - 3
packages/semi-ui/tabs/interface.ts

@@ -16,6 +16,10 @@ export interface PlainTab {
     closable?: boolean
 }
 
+interface TabsDropDownProps {
+    start: DropdownProps;
+    end: DropdownProps
+}
 
 export interface TabsProps {
     activeKey?: string;
@@ -45,7 +49,8 @@ export interface TabsProps {
     onVisibleTabsChange?: TabBarProps["onVisibleTabsChange"];
     visibleTabsStyle?: TabBarProps['visibleTabsStyle'];
     arrowPosition?: TabBarProps['arrowPosition'];
-    renderArrow?: TabBarProps['renderArrow']
+    renderArrow?: TabBarProps['renderArrow'];
+    dropdownProps?: TabsDropDownProps
 }
 
 export interface TabBarProps {
@@ -69,8 +74,8 @@ export interface TabBarProps {
     onVisibleTabsChange?: (visibleState: Map<string, boolean>) => void;
     visibleTabsStyle?: CSSProperties;
     arrowPosition?: OverflowListProps['overflowRenderDirection'];
-    renderArrow?: (items: OverflowItem[], pos: "start"|"end", handleArrowClick: () => void, defaultNode: ReactNode) => ReactNode
-
+    renderArrow?: (items: OverflowItem[], pos: "start"|"end", handleArrowClick: () => void, defaultNode: ReactNode) => ReactNode;
+    dropdownProps?: TabsDropDownProps
 }
 
 export interface TabPaneProps {