Browse Source

Tabs: add stretch attribute (#11476)

* Tabs: add stretch attribute

* Update tabs.scss
Jikkai Xiao 7 years ago
parent
commit
d1391e325c

+ 1 - 0
examples/docs/en-US/tabs.md

@@ -376,6 +376,7 @@ Only card type Tabs support addable & closeable.
 | editable  | whether Tab is addable and closable | boolean   | — |  false  |
 | value  | name of the selected tab  | string   |  —  |  name of first tab |
 | tab-position  | position of tabs | string   |  top/right/bottom/left  |  top |
+| stretch  | whether width of tab automatically fits its container | boolean   |  -  |  false |
 | before-leave | hook function before switching tab. If `false` is returned or a `Promise` is returned and then is rejected, switching will be prevented | function | — | — |
 
 ### Tabs Events

+ 1 - 0
examples/docs/es/tabs.md

@@ -376,6 +376,7 @@ Solo las pestañas de tipo tarjeta soportan adición y cierre.
 | editable     | si la Pestaña es añadible y cerrable | boolean | —                     | false                       |
 | value        | nombre de la pestaña seleccionada    | string  | —                     | nombre de la primer pestaña |
 | tab-position | posición de tabulación               | string  | top/right/bottom/left | top                         |
+| stretch      | whether width of tab automatically fits its container | boolean | - | false |
 | before-leave | función `hook` antes de cambiar de pestaña. Si se devuelve `false` o se devuelve una `Promise` y luego se rechaza, se evitará el cambio. | function | — | — |
 
 ### Eventos de Pestañas

+ 1 - 0
examples/docs/zh-CN/tabs.md

@@ -374,6 +374,7 @@
 | editable  | 标签是否同时可增加和关闭   | boolean   | — |  false  |
 | value  | 绑定值,选中选项卡的 name  | string   |  —  |  第一个选项卡的 name |
 | tab-position  | 选项卡所在位置 | string   |  top/right/bottom/left  |  top |
+| stretch  | 标签的宽度是否自撑开 | boolean   |  -  |  false |
 | before-leave | 切换标签之前的钩子,若返回 false 或者返回 Promise 且被 reject,则阻止切换。 | function | — | — |
 
 ### Tabs Events

+ 10 - 2
packages/tabs/src/tab-nav.vue

@@ -28,7 +28,8 @@
         type: Function,
         default: noop
       },
-      type: String
+      type: String,
+      stretch: Boolean
     },
 
     data() {
@@ -187,6 +188,7 @@
         type,
         panes,
         editable,
+        stretch,
         onTabClick,
         onTabRemove,
         navStyle,
@@ -246,7 +248,13 @@
         <div class={['el-tabs__nav-wrap', scrollable ? 'is-scrollable' : '', `is-${ this.rootTabs.tabPosition }`]}>
           {scrollBtn}
           <div class={['el-tabs__nav-scroll']} ref="navScroll">
-            <div class="el-tabs__nav" ref="nav" style={navStyle} role="tablist" on-keydown={ changeTab }>
+            <div
+              class={['el-tabs__nav', stretch && ['top', 'bottom'].indexOf(this.rootTabs.tabPosition) !== -1 ? 'is-stretch' : '']}
+              ref="nav"
+              style={navStyle}
+              role="tablist"
+              on-keydown={ changeTab }
+            >
               {!type ? <tab-bar tabs={panes}></tab-bar> : null}
               {tabs}
             </div>

+ 6 - 3
packages/tabs/src/tabs.vue

@@ -19,7 +19,8 @@
         type: String,
         default: 'top'
       },
-      beforeLeave: Function
+      beforeLeave: Function,
+      stretch: Boolean
     },
 
     provide() {
@@ -109,7 +110,8 @@
         panes,
         editable,
         addable,
-        tabPosition
+        tabPosition,
+        stretch
       } = this;
 
       const newButton = editable || addable
@@ -132,7 +134,8 @@
           onTabRemove: handleTabRemove,
           editable,
           type,
-          panes
+          panes,
+          stretch
         },
         ref: 'nav'
       };

+ 10 - 0
packages/theme-chalk/src/tabs.scss

@@ -82,6 +82,15 @@
     transition: transform .3s;
     float: left;
     z-index: #{$--index-normal + 1};
+
+    @include when(stretch) {
+      min-width: 100%;
+      display: flex;
+      & > * {
+        flex: 1;
+        text-align: center;
+      }
+    }
   }
   @include e(item) {
     padding: 0 20px;
@@ -149,6 +158,7 @@
       border: 1px solid $--border-color-light;
       border-bottom: none;
       border-radius: 4px 4px 0 0;
+      box-sizing: border-box;
     }
     > .el-tabs__header .el-tabs__active-bar {
       display: none;

+ 28 - 0
test/unit/specs/tabs.spec.js

@@ -395,6 +395,34 @@ describe('Tabs', () => {
       });
     }, 100);
   });
+  it('stretch', done => {
+    vm = createVue({
+      template: `
+        <el-tabs ref="tabs" stretch :tab-position="tabPosition">
+          <el-tab-pane label="用户管理">A</el-tab-pane>
+          <el-tab-pane label="配置管理">B</el-tab-pane>
+          <el-tab-pane label="角色管理" ref="pane-click">C</el-tab-pane>
+          <el-tab-pane label="定时任务补偿">D</el-tab-pane>
+        </el-tabs>
+      `,
+      data() {
+        return {
+          tabPosition: 'bottom'
+        };
+      }
+    }, true);
+
+    setTimeout(_ => {
+      expect(vm.$el.querySelector('[role=tablist]').classList.contains('is-stretch')).to.be.true;
+
+      vm.tabPosition = 'left';
+
+      vm.$nextTick(_ => {
+        expect(vm.$el.querySelector('[role=tablist]').classList.contains('is-stretch')).not.to.be.true;
+        done();
+      });
+    }, 100);
+  });
   it('horizonal-scrollable', done => {
     vm = createVue({
       template: `

+ 3 - 0
types/tabs.d.ts

@@ -23,6 +23,9 @@ export declare class ElTabs extends ElementUIComponent {
   /** Position of tabs */
   tabPosition: TabPosition
 
+  /** Whether width of tab automatically fits its container */
+  stretch: Boolean
+
   /** Hook function before switching tab. If false or a Promise is returned and then is rejected, switching will be prevented */
   beforeLeave: () => boolean | Promise<any>
 }