diff --git a/components.json b/components.json index c610146d424..f67283ce908 100644 --- a/components.json +++ b/components.json @@ -74,5 +74,6 @@ "divider": "./packages/divider/index.js", "image": "./packages/image/index.js", "calendar": "./packages/calendar/index.js", + "backtop": "./packages/backtop/index.js", "infiniteScroll": "./packages/infiniteScroll/index.js" } diff --git a/examples/docs/en-US/backtop.md b/examples/docs/en-US/backtop.md new file mode 100644 index 00000000000..faadfe35259 --- /dev/null +++ b/examples/docs/en-US/backtop.md @@ -0,0 +1,60 @@ +## Backtop + +A button to back to top + +### Basic usage + +Scroll down to see the bottom-right button. +:::demo + +```html + +``` + +::: + +### Customizations + +Display area is 40px \* 40px. +:::demo + +```html + +``` + +::: + +### Attributes + +| Attribute | Description | Type | Accepted Values | Default | +| ----------------- | ------------------------------------------------------------------- | --------------- | --------------- | ------- | +| target | the target to trigger scroll | string | | | +| visibility-height | the button will not show until the scroll height reaches this value | number | | 200 | +| right | right distance | number | | 40 | +| bottom | bottom distance | number | | 40 | + +### Events + +| Event Name | Description | Parameters | +| ---------- | ------------------- | ----------- | +| click | triggers when click | click event | diff --git a/examples/docs/es/backtop.md b/examples/docs/es/backtop.md new file mode 100644 index 00000000000..faadfe35259 --- /dev/null +++ b/examples/docs/es/backtop.md @@ -0,0 +1,60 @@ +## Backtop + +A button to back to top + +### Basic usage + +Scroll down to see the bottom-right button. +:::demo + +```html + +``` + +::: + +### Customizations + +Display area is 40px \* 40px. +:::demo + +```html + +``` + +::: + +### Attributes + +| Attribute | Description | Type | Accepted Values | Default | +| ----------------- | ------------------------------------------------------------------- | --------------- | --------------- | ------- | +| target | the target to trigger scroll | string | | | +| visibility-height | the button will not show until the scroll height reaches this value | number | | 200 | +| right | right distance | number | | 40 | +| bottom | bottom distance | number | | 40 | + +### Events + +| Event Name | Description | Parameters | +| ---------- | ------------------- | ----------- | +| click | triggers when click | click event | diff --git a/examples/docs/fr-FR/backtop.md b/examples/docs/fr-FR/backtop.md new file mode 100644 index 00000000000..639d20b149e --- /dev/null +++ b/examples/docs/fr-FR/backtop.md @@ -0,0 +1,60 @@ +## Backtop + +A button to back to top + +### Basic usage + +Scroll down to see the bottom-right button. +:::demo + +```html + +``` + +::: + +### Customizations + +Display area is 40px \* 40px. +:::demo + +```html + +``` + +::: + +### Attributes + +| Attribute | Description | Type | Accepted Values | Default | +| ----------------- | ------------------------------------------------------------------- | --------------- | --------------- | ------- | +| target | the target to trigger scroll | string | | | +| visibility-height | the button will not show until the scroll height reaches this value | number | | 200 | +| right | right distance | number | | 40 | +| bottom | bottom distance | number | | 40 | + +### Events + +| Event Name | Description | Parameters | +| ---------- | ------------------- | ----------- | +| click | triggers when click | click event | diff --git a/examples/docs/zh-CN/backtop.md b/examples/docs/zh-CN/backtop.md new file mode 100644 index 00000000000..a29983629cb --- /dev/null +++ b/examples/docs/zh-CN/backtop.md @@ -0,0 +1,60 @@ +## Backtop 回到顶部 + +返回页面顶部的操作按钮 + +### 基础用法 + +滑动页面即可看到右下方的按钮。 +:::demo + +```html + +``` + +::: + +### 自定义显示内容 + +显示区域被固定为 40px \* 40px 的区域, 其中的内容可支持自定义。 +:::demo + +```html + +``` + +::: + +### Attributes + +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| ----------------- | -------------------------------- | --------------- | ------ | ------ | +| target | 触发滚动的对象 | string | | | +| visibility-height | 滚动高度达到此参数值才出现 | number | | 200 | +| right | 控制其显示位置, 距离页面右边距 | number | | 40 | +| bottom | 控制其显示位置, 距离页面底部距离 | number | | 40 | + +### Events + +| 事件名 | 说明 | 回调参数 | +| ------ | ------------------ | -------- | +| click | 点击按钮触发的事件 | 点击事件 | diff --git a/examples/nav.config.json b/examples/nav.config.json index fbce249109d..999a2a1378b 100644 --- a/examples/nav.config.json +++ b/examples/nav.config.json @@ -268,6 +268,10 @@ "path": "/image", "title": "Image 图片" }, + { + "path": "/backtop", + "title": "Backtop 回到顶部" + }, { "path": "/infiniteScroll", "title": "InfiniteScroll 无限滚动" @@ -546,6 +550,10 @@ "path": "/image", "title": "Image" }, + { + "path": "/backtop", + "title": "Backtop" + }, { "path": "/infiniteScroll", "title": "InfiniteScroll" @@ -824,6 +832,10 @@ "path": "/image", "title": "Image" }, + { + "path": "/backtop", + "title": "Backtop" + }, { "path": "/infiniteScroll", "title": "InfiniteScroll" @@ -1102,6 +1114,10 @@ "path": "/image", "title": "Image" }, + { + "path": "/backtop", + "title": "Backtop" + }, { "path": "/infiniteScroll", "title": "InfiniteScroll" diff --git a/examples/pages/template/component.tpl b/examples/pages/template/component.tpl index d0dd642b11b..d1650d2573a 100644 --- a/examples/pages/template/component.tpl +++ b/examples/pages/template/component.tpl @@ -101,38 +101,6 @@ } } } - - .page-component-up { - background-color: #fff; - position: fixed; - right: 100px; - bottom: 150px; - width: 40px; - height: 40px; - size: 40px; - border-radius: 20px; - cursor: pointer; - transition: .3s; - box-shadow: 0 0 6px rgba(0,0,0, .12); - z-index: 5; - - i { - color: #409EFF; - display: block; - line-height: 40px; - text-align: center; - font-size: 18px; - } - - &.hover { - opacity: 1; - } - } - .back-top-fade-enter, - .back-top-fade-leave-active { - transform: translateY(-30px); - opacity: 0; - } } @media (max-width: 768px) { @@ -157,9 +125,6 @@ overflow: auto; display: block; } - .page-component-up { - display: none; - } } } @@ -173,17 +138,12 @@ - -
- -
-
+ @@ -197,8 +157,6 @@ return { lang: this.$route.meta.lang, navsData, - hover: false, - showBackToTop: false, scrollTop: 0, showHeader: true, componentScrollBar: null, @@ -238,15 +196,9 @@ }, 50); } }, - toTop() { - this.hover = false; - this.showBackToTop = false; - this.componentScrollBox.scrollTop = 0; - }, handleScroll() { const scrollTop = this.componentScrollBox.scrollTop; - this.showBackToTop = scrollTop >= 0.5 * document.body.clientHeight; if (this.showHeader !== this.scrollTop > scrollTop) { this.showHeader = this.scrollTop > scrollTop; } @@ -259,6 +211,11 @@ this.scrollTop = scrollTop; } }, + computed: { + showBackToTop() { + return !this.$route.path.match(/backtop/); + } + }, created() { bus.$on('navFade', val => { this.navFaded = val; diff --git a/packages/backtop/index.js b/packages/backtop/index.js new file mode 100644 index 00000000000..21433c53645 --- /dev/null +++ b/packages/backtop/index.js @@ -0,0 +1,8 @@ +import Backtop from './src/main'; + +/* istanbul ignore next */ +Backtop.install = function(Vue) { + Vue.component(Backtop.name, Backtop); +}; + +export default Backtop; diff --git a/packages/backtop/src/main.vue b/packages/backtop/src/main.vue new file mode 100644 index 00000000000..6e1beb130dd --- /dev/null +++ b/packages/backtop/src/main.vue @@ -0,0 +1,101 @@ + + + diff --git a/packages/theme-chalk/src/backtop.scss b/packages/theme-chalk/src/backtop.scss new file mode 100644 index 00000000000..f41524358ad --- /dev/null +++ b/packages/theme-chalk/src/backtop.scss @@ -0,0 +1,22 @@ +@import "mixins/mixins"; +@import "common/var"; + +@include b(backtop) { + position: fixed; + background-color: $--backtop-background-color; + width: 40px; + height: 40px; + border-radius: 50%; + color: $--backtop-font-color; + display: flex; + align-items: center; + justify-content: center; + font-size: 20px; + box-shadow: 0 0 6px rgba(0,0,0, .12); + cursor: pointer; + z-index: 5; + + &:hover { + background-color: $--backtop-hover-background-color + } +} diff --git a/packages/theme-chalk/src/common/var.scss b/packages/theme-chalk/src/common/var.scss index a738a2be173..1559fc859dc 100644 --- a/packages/theme-chalk/src/common/var.scss +++ b/packages/theme-chalk/src/common/var.scss @@ -905,6 +905,15 @@ $--timeline-node-size-normal: 12px !default; $--timeline-node-size-large: 14px !default; $--timeline-node-color: $--border-color-light !default; +/* Backtop +--------------------------*/ +/// color||Color|0 +$--backtop-background-color: $--color-white !default; +/// color||Color|0 +$--backtop-font-color: $--color-primary !default; +/// color||Color|0 +$--backtop-hover-background-color: $--border-color-extra-light !default; + /* Link --------------------------*/ /// fontSize||Font|1 diff --git a/packages/theme-chalk/src/index.scss b/packages/theme-chalk/src/index.scss index e933ae1325e..73be7631494 100644 --- a/packages/theme-chalk/src/index.scss +++ b/packages/theme-chalk/src/index.scss @@ -71,3 +71,4 @@ @import "./divider.scss"; @import "./image.scss"; @import "./calendar.scss"; +@import "./backtop.scss"; diff --git a/src/index.js b/src/index.js index cf398f1976b..7c6268b5a60 100644 --- a/src/index.js +++ b/src/index.js @@ -75,6 +75,7 @@ import Link from '../packages/link/index.js'; import Divider from '../packages/divider/index.js'; import Image from '../packages/image/index.js'; import Calendar from '../packages/calendar/index.js'; +import Backtop from '../packages/backtop/index.js'; import InfiniteScroll from '../packages/infiniteScroll/index.js'; import locale from 'element-ui/src/locale'; import CollapseTransition from 'element-ui/src/transitions/collapse-transition'; @@ -151,6 +152,7 @@ const components = [ Divider, Image, Calendar, + Backtop, CollapseTransition ]; @@ -266,5 +268,6 @@ export default { Divider, Image, Calendar, + Backtop, InfiniteScroll }; diff --git a/test/unit/specs/backtop.spec.js b/test/unit/specs/backtop.spec.js new file mode 100644 index 00000000000..05de5663e45 --- /dev/null +++ b/test/unit/specs/backtop.spec.js @@ -0,0 +1,28 @@ +import { createVue, destroyVM, wait } from '../util'; + +describe('Backtop', () => { + let vm; + afterEach(() => { + destroyVM(vm); + }); + + it('create', async() => { + vm = createVue({ + template: ` +
+
+ + test_up_text + +
+
+ ` + }, true); + expect(vm.$el).to.exist; + expect(vm.$el.innerText).to.be.equal(''); + vm.$refs.scrollTarget.scrollTop = 2000; + await wait(); + expect(vm.$el.innerText).to.be.equal('test_up_text'); + }); +}); + diff --git a/types/backtop.d.ts b/types/backtop.d.ts new file mode 100644 index 00000000000..a171c76e1db --- /dev/null +++ b/types/backtop.d.ts @@ -0,0 +1,16 @@ +import { ElementUIComponent } from './component' + +/** Backtop Component */ +export declare class ElBacktop extends ElementUIComponent { + /** Backtop target */ + target: string + + /** Backtop visibility height */ + visibilityHeight: string | number + + /** Backtop right position */ + right: string | number + + /** Backtop bottom position */ + bottom: string | number +} diff --git a/types/element-ui.d.ts b/types/element-ui.d.ts index a352f6a0dae..89779a2e6dc 100644 --- a/types/element-ui.d.ts +++ b/types/element-ui.d.ts @@ -74,6 +74,7 @@ import { ElDivider } from './divider' import { ElIcon } from './icon' import { ElCalendar } from './calendar' import { ElImage } from './image' +import { ElBacktop } from './backtop' import { ElInfiniteScroll } from './infiniteScroll' export interface InstallationOptions { @@ -322,5 +323,9 @@ export class Icon extends ElIcon {} /** Calendar Component */ export class Calendar extends ElCalendar {} +/** Backtop Component */ +export class Backtop extends ElBacktop {} + /** InfiniteScroll Component */ export class InfiniteScroll extends ElInfiniteScroll {} +