Explorar o código

Link: add link component (#15052)

iamkun %!s(int64=6) %!d(string=hai) anos
pai
achega
5ecf4c2895

+ 1 - 0
components.json

@@ -70,6 +70,7 @@
   "footer": "./packages/footer/index.js",
   "timeline": "./packages/timeline/index.js",
   "timeline-item": "./packages/timeline-item/index.js",
+  "link": "./packages/link/index.js",
   "divider": "./packages/divider/index.js",
   "image": "./packages/image/index.js"
 }

+ 77 - 0
examples/docs/en-US/link.md

@@ -0,0 +1,77 @@
+## Link
+
+Text hyperlink
+
+### Basic
+
+Basic text link
+:::demo
+
+```html
+<div>
+  <el-link href="https://element.eleme.io" target="_blank">default</el-link>
+  <el-link type="primary">primary</el-link>
+  <el-link type="success">success</el-link>
+  <el-link type="warning">warning</el-link>
+  <el-link type="danger">danger</el-link>
+  <el-link type="info">info</el-link>
+</div>
+```
+
+:::
+
+### Disabled
+
+Disabled state of link
+:::demo
+
+```html
+<div>
+  <el-link disabled>default</el-link>
+  <el-link type="primary" disabled>primary</el-link>
+  <el-link type="success" disabled>success</el-link>
+  <el-link type="warning" disabled>warning</el-link>
+  <el-link type="danger" disabled>danger</el-link>
+  <el-link type="info" disabled>info</el-link>
+</div>
+```
+
+:::
+
+### Underline
+
+Underline of link
+:::demo
+
+```html
+<div>
+  <el-link :underline="false">Without Underline</el-link>
+  <el-link>With Underline</el-link>
+</div>
+```
+
+:::
+
+### Icon
+
+Link with icon
+:::demo
+
+```html
+<div>
+  <el-link icon="el-icon-edit">Edit</el-link>
+  <el-link>Check<i class="el-icon-view el-icon--right"></i> </el-link>
+</div>
+```
+
+:::
+
+### Attributes
+
+| Attribute | Description                         | Type    | Options                                     | Default |
+| --------- | ----------------------------------- | ------- | ------------------------------------------- | ------- |
+| type      | type                                | string  | primary / success / warning / danger / info | default |
+| underline | whether the component has underline | boolean | —                                           | true    |
+| disabled  | whether the component is disabled   | boolean | —                                           | false   |
+| href      | same as native hyperlink's `href`   | string  | —                                           | -       |
+| icon      | class name of icon                  | string  | —                                           | -       |

+ 77 - 0
examples/docs/es/link.md

@@ -0,0 +1,77 @@
+## Link
+
+Text hyperlink
+
+### Basic
+
+Basic text link
+:::demo
+
+```html
+<div>
+  <el-link href="https://element.eleme.io" target="_blank">default</el-link>
+  <el-link type="primary">primary</el-link>
+  <el-link type="success">success</el-link>
+  <el-link type="warning">warning</el-link>
+  <el-link type="danger">danger</el-link>
+  <el-link type="info">info</el-link>
+</div>
+```
+
+:::
+
+### Disabled
+
+Disabled state of link
+:::demo
+
+```html
+<div>
+  <el-link disabled>default</el-link>
+  <el-link type="primary" disabled>primary</el-link>
+  <el-link type="success" disabled>success</el-link>
+  <el-link type="warning" disabled>warning</el-link>
+  <el-link type="danger" disabled>danger</el-link>
+  <el-link type="info" disabled>info</el-link>
+</div>
+```
+
+:::
+
+### Underline
+
+Underline of link
+:::demo
+
+```html
+<div>
+  <el-link :underline="false">Without Underline</el-link>
+  <el-link>With Underline</el-link>
+</div>
+```
+
+:::
+
+### Icon
+
+Link with icon
+:::demo
+
+```html
+<div>
+  <el-link icon="el-icon-edit">Edit</el-link>
+  <el-link>Check<i class="el-icon-view el-icon--right"></i> </el-link>
+</div>
+```
+
+:::
+
+### Attributes
+
+| Attribute | Description                         | Type    | Options                                     | Default |
+| --------- | ----------------------------------- | ------- | ------------------------------------------- | ------- |
+| type      | type                                | string  | primary / success / warning / danger / info | default |
+| underline | whether the component has underline | boolean | —                                           | true    |
+| disabled  | whether the component is disabled   | boolean | —                                           | false   |
+| href      | same as native hyperlink's `href`   | string  | —                                           | -       |
+| icon      | class name of icon                  | string  | —                                           | -       |

+ 77 - 0
examples/docs/fr-FR/link.md

@@ -0,0 +1,77 @@
+## Link
+
+Text hyperlink
+
+### Basic
+
+Basic text link
+:::demo
+
+```html
+<div>
+  <el-link href="https://element.eleme.io" target="_blank">default</el-link>
+  <el-link type="primary">primary</el-link>
+  <el-link type="success">success</el-link>
+  <el-link type="warning">warning</el-link>
+  <el-link type="danger">danger</el-link>
+  <el-link type="info">info</el-link>
+</div>
+```
+
+:::
+
+### Disabled
+
+Disabled state of link
+:::demo
+
+```html
+<div>
+  <el-link disabled>default</el-link>
+  <el-link type="primary" disabled>primary</el-link>
+  <el-link type="success" disabled>success</el-link>
+  <el-link type="warning" disabled>warning</el-link>
+  <el-link type="danger" disabled>danger</el-link>
+  <el-link type="info" disabled>info</el-link>
+</div>
+```
+
+:::
+
+### Underline
+
+Underline of link
+:::demo
+
+```html
+<div>
+  <el-link :underline="false">Without Underline</el-link>
+  <el-link>With Underline</el-link>
+</div>
+```
+
+:::
+
+### Icon
+
+Link with icon
+:::demo
+
+```html
+<div>
+  <el-link icon="el-icon-edit">Edit</el-link>
+  <el-link>Check<i class="el-icon-view el-icon--right"></i> </el-link>
+</div>
+```
+
+:::
+
+### Attributes
+
+| Attribute | Description                         | Type    | Options                                     | Default |
+| --------- | ----------------------------------- | ------- | ------------------------------------------- | ------- |
+| type      | type                                | string  | primary / success / warning / danger / info | default |
+| underline | whether the component has underline | boolean | —                                           | true    |
+| disabled  | whether the component is disabled   | boolean | —                                           | false   |
+| href      | same as native hyperlink's `href`   | string  | —                                           | -       |
+| icon      | class name of icon                  | string  | —                                           | -       |

+ 66 - 0
examples/docs/zh-CN/link.md

@@ -0,0 +1,66 @@
+## Link 文字链接
+
+文字超链接
+
+### 基础用法
+基础的文字链接用法。
+:::demo
+```html
+<div>
+  <el-link href="https://element.eleme.io" target="_blank">默认链接</el-link>
+  <el-link type="primary">主要链接</el-link>
+  <el-link type="success">成功链接</el-link>
+  <el-link type="warning">警告链接</el-link>
+  <el-link type="danger">危险链接</el-link>
+  <el-link type="info">信息链接</el-link>
+</div>
+```
+:::
+
+### 禁用状态
+文字链接不可用状态。
+:::demo
+```html
+<div>
+  <el-link disabled>默认链接</el-link>
+  <el-link type="primary" disabled>主要链接</el-link>
+  <el-link type="success" disabled>成功链接</el-link>
+  <el-link type="warning" disabled>警告链接</el-link>
+  <el-link type="danger" disabled>危险链接</el-link>
+  <el-link type="info" disabled>信息链接</el-link>
+</div>
+```
+:::
+
+### 下划线
+文字链接下划线。
+:::demo
+```html
+<div>
+  <el-link :underline="false">无下划线</el-link>
+  <el-link>有下划线</el-link>
+</div>
+```
+:::
+
+### 图标
+
+带图标的文字链接可增强辨识度。
+:::demo
+```html
+<div>
+  <el-link icon="el-icon-edit">编辑</el-link>
+  <el-link>查看<i class="el-icon-view el-icon--right"></i> </el-link>
+</div>
+```
+:::
+
+### Attributes
+
+| 参数           | 说明                           | 类型      | 可选值                               | 默认值  |
+| -------------- | ------------------------------ | --------- | ------------------------------------ | ------- |
+| type           | 类型                   | string  | primary / success / warning / danger / info | default |
+| underline      | 是否下划线                         | boolean | —                                    | true    |
+| disabled       | 是否禁用状态                       | boolean | —                                    | false   |
+| href           | 原生 href 属性                     | string  | —                                    | -       |
+| icon           | 图标类名                       | string  | —                                    | -       |

+ 16 - 0
examples/nav.config.json

@@ -70,6 +70,10 @@
             {
               "path": "/button",
               "title": "Button 按钮"
+            },
+            {
+              "path": "/link",
+              "title": "Link 文字链接"
             }
           ]
         },
@@ -336,6 +340,10 @@
             {
               "path": "/button",
               "title": "Button"
+            },
+            {
+              "path": "/link",
+              "title": "Link"
             }
           ]
         },
@@ -602,6 +610,10 @@
             {
               "path": "/button",
               "title": "Button"
+            },
+            {
+              "path": "/link",
+              "title": "Link"
             }
           ]
         },
@@ -868,6 +880,10 @@
             {
               "path": "/button",
               "title": "Button"
+            },
+            {
+              "path": "/link",
+              "title": "Link"
             }
           ]
         },

+ 8 - 0
packages/link/index.js

@@ -0,0 +1,8 @@
+import Link from './src/main';
+
+/* istanbul ignore next */
+Link.install = function(Vue) {
+  Vue.component(Link.name, Link);
+};
+
+export default Link;

+ 53 - 0
packages/link/src/main.vue

@@ -0,0 +1,53 @@
+<template>
+  <a
+    :class="[
+      'el-link',
+      type ? `el-link--${type}` : '',
+      disabled && 'is-disabled',
+      underline && !disabled && 'is-underline'
+    ]"
+    :href="href"
+    v-bind="$attrs"
+    @click="handleClick"
+  >
+
+    <el-icon :class="icon" v-if="icon"></el-icon>
+
+    <span v-if="$slots.default" class="el-link--inner">
+      <slot></slot>
+    </span>
+
+    <template v-if="$slots.icon"><slot v-if="$slots.icon" name="icon"></slot></template>
+  </a>
+</template>
+
+<script>
+
+export default {
+  name: 'ElLink',
+
+  props: {
+    type: {
+      type: String,
+      default: 'default'
+    },
+    underline: {
+      type: Boolean,
+      default: true
+    },
+    disabled: Boolean,
+    href: String,
+    icon: String
+  },
+
+  methods: {
+    handleClick(event) {
+      if (!this.disabled) {
+        if (!this.href) {
+          this.$emit('click', event);
+        }
+      }
+    }
+  }
+};
+</script>

+ 23 - 0
packages/theme-chalk/src/common/var.scss

@@ -863,6 +863,29 @@ $--timeline-node-size-normal: 12px !default;
 $--timeline-node-size-large: 14px !default;
 $--timeline-node-color: $--border-color-light !default;
 
+/* Link
+--------------------------*/
+/// fontSize||Font|1
+$--link-font-size: $--font-size-base !default;
+/// fontWeight||Font|1
+$--link-font-weight: $--font-weight-primary !default;
+/// color||Color|0
+$--link-default-font-color: $--color-text-regular !default;
+/// color||Color|0
+$--link-default-active-color: $--color-primary !default;
+/// color||Color|0
+$--link-disabled-font-color: $--color-text-placeholder !default;
+/// color||Color|0
+$--link-primary-font-color: $--color-primary !default;
+/// color||Color|0
+$--link-success-font-color: $--color-success !default;
+/// color||Color|0
+$--link-warning-font-color: $--color-warning !default;
+/// color||Color|0
+$--link-danger-font-color: $--color-danger !default;
+/// color||Color|0
+$--link-info-font-color: $--color-info !default;
+
 /* Break-point
 --------------------------*/
 $--sm: 768px !default;

+ 1 - 0
packages/theme-chalk/src/index.scss

@@ -67,5 +67,6 @@
 @import "./footer.scss";
 @import "./timeline.scss";
 @import "./timeline-item.scss";
+@import "./link.scss";
 @import "./divider.scss";
 @import "./image.scss";

+ 76 - 0
packages/theme-chalk/src/link.scss

@@ -0,0 +1,76 @@
+@import "mixins/mixins";
+@import "common/var";
+
+$typeMap: (
+  primary: $--link-primary-font-color, 
+  danger: $--link-danger-font-color, 
+  success: $--link-success-font-color, 
+  warning: $--link-warning-font-color, 
+  info: $--link-info-font-color);
+
+@include b(link) {
+  display: inline-flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: center;
+  vertical-align: middle;
+  position: relative;
+  text-decoration: none;
+  outline: none;
+  cursor: pointer;
+  padding: 0;
+  font-size: $--link-font-size;
+  font-weight: $--link-font-weight;
+
+  @include when(underline) {
+    &:hover:after {
+      content: "";
+      position: absolute;
+      left: 0;
+      right: 0;
+      height: 0;
+      bottom: 0;
+      border-bottom: 1px solid $--link-default-active-color
+    }
+  }
+
+  @include when(disabled) {
+    cursor: not-allowed;
+  } 
+
+  & [class*="el-icon-"] {
+    & + span {
+      margin-left: 5px;
+    }
+  }
+    
+    
+  &.el-link--default  {
+    color: $--link-default-font-color;
+    &:hover {
+      color: $--link-default-active-color
+    }
+    &:after {
+      border-color: $--link-default-active-color
+    }
+    @include when(disabled) {
+      color: $--link-disabled-font-color
+    }
+  }
+
+  @each $type, $primaryColor in $typeMap {
+    &.el-link--#{$type} {
+      color: $primaryColor;
+      &:hover {
+        color: mix($primaryColor, $--color-white, 80%)
+      }
+      &:after {
+        border-color: $primaryColor
+      }
+      @include when(disabled) {
+        color: mix($primaryColor, $--color-white, 50%)
+      }
+    }
+  }
+    
+}

+ 3 - 0
src/index.js

@@ -71,6 +71,7 @@ import Main from '../packages/main/index.js';
 import Footer from '../packages/footer/index.js';
 import Timeline from '../packages/timeline/index.js';
 import TimelineItem from '../packages/timeline-item/index.js';
+import Link from '../packages/link/index.js';
 import Divider from '../packages/divider/index.js';
 import Image from '../packages/image/index.js';
 import locale from 'element-ui/src/locale';
@@ -144,6 +145,7 @@ const components = [
   Footer,
   Timeline,
   TimelineItem,
+  Link,
   Divider,
   Image,
   CollapseTransition
@@ -256,6 +258,7 @@ export default {
   Footer,
   Timeline,
   TimelineItem,
+  Link,
   Divider,
   Image
 };

+ 66 - 0
test/unit/specs/link.spec.js

@@ -0,0 +1,66 @@
+import { createTest, createVue, destroyVM, wait } from '../util';
+import Link from 'packages/link';
+
+describe('Link', () => {
+  let vm;
+  afterEach(() => {
+    destroyVM(vm);
+  });
+
+  it('create', () => {
+    vm = createTest(Link, {
+      type: 'primary'
+    }, true);
+    let linkElm = vm.$el;
+    expect(linkElm.classList.contains('el-link--primary')).to.be.true;
+  });
+  it('icon', () => {
+    vm = createTest(Link, {
+      icon: 'el-icon-search'
+    }, true);
+    let linkElm = vm.$el;
+    expect(linkElm.querySelector('.el-icon-search')).to.be.ok;
+  });
+  it('href', () => {
+    vm = createTest(Link, {
+      href: 'https://element.eleme.io/'
+    }, true);
+    let linkElm = vm.$el;
+    expect(linkElm.getAttribute('href')).to.be.equal('https://element.eleme.io/');
+  });
+  it('target', () => {
+    vm = createVue(`
+    <el-link href="https://element.eleme.io" target="_blank">
+      default
+    </el-link>
+    `);
+    let linkElm = vm.$el;
+    expect(linkElm.getAttribute('target')).to.be.equal('_blank');
+  });
+  it('disabled', () => {
+    vm = createTest(Link, {
+      disabled: true
+    }, true);
+    let linkElm = vm.$el;
+    expect(linkElm.classList.contains('is-disabled')).to.be.true;
+  });
+
+  it('click', async() => {
+    let result;
+    vm = createVue({
+      template: `
+        <el-link @click="handleClick"></el-link>
+      `,
+      methods: {
+        handleClick(evt) {
+          result = evt;
+        }
+      }
+    }, true);
+    vm.$el.click();
+    await wait();
+    expect(result).to.exist;
+  });
+
+});
+

+ 25 - 0
types/link.d.ts

@@ -0,0 +1,25 @@
+import { ElementUIComponent } from './component'
+
+/** Button type */
+export type LinkType = 'primary' | 'success' | 'warning' | 'danger' | 'info' 
+
+/** Link Component */
+export declare class ElLink extends ElementUIComponent {
+  /** Link type */
+  type: LinkType
+  
+  /** Disable the link */
+  disabled: boolean
+
+  /** Link underline */
+  underline: boolean
+
+  /** Link icon, accepts an icon name of Element icon component */
+  icon: string
+
+  /** Link href */
+  href: string
+
+  /** Link target */
+  target: string
+}