diff --git a/components/BackTop/Backtop.tsx b/components/BackTop/Backtop.tsx new file mode 100644 index 0000000..7a42345 --- /dev/null +++ b/components/BackTop/Backtop.tsx @@ -0,0 +1,111 @@ + +import {Component} from 'react'; +import * as React from 'react'; +import * as classNames from 'classnames'; +import {IBaseComponent} from '../template/component'; +import Icon from '../Icon'; +import { RenderInRootDom } from '../utils/renderInRootDom'; +import { backTop } from './assist'; + +export interface IBackTopProps extends IBaseComponent { + /** + * 距离底部距离 + */ + bottom?: number; + /** + * 距离右侧距离 + */ + right?: number; + /** + * 触发backtop的高度 + */ + height?: number; + /** + * 动画时间 + */ + duration?: number; + /** + * 回调函数 + */ + onBackTop?: () => void; +} + +export interface IBackTopState { + /** + * 是否显示backtop + */ + show: boolean; +} + +/** + * **返回顶部**-返回页面顶部的操作按钮。 + */ +class BackTop extends Component { + state = { + show: false, + }; + + static defaultProps = { + height: 200, + bottom: 50, + right: 50, + duration: 500, + }; + + scrollListener = () => { + const height = this.props.height ? this.props.height : 200; + const top = document.documentElement.scrollTop || document.body.scrollTop; + const show = top >= height; + this.setState({ + show, + }); + } + + componentDidMount() { + window.addEventListener('scroll', this.scrollListener, false); + window.addEventListener('resize', this.scrollListener, false); + } + + componentWillUnMount() { + window.removeEventListener('scroll', this.scrollListener, false); + window.removeEventListener('resize', this.scrollListener, false); + } + render() { + const { + className, style, children, + bottom, right, duration, + onBackTop, + ...otherProps} = this.props; + const preCls = 'yoshino-backtop'; + const clsName = classNames( + preCls, className, + ); + const backtopStyle = { + right: `${right}px`, + bottom: `${bottom}px`, + }; + return ( + +
+ { + this.state.show ? children ? children : ( +
+ +
+ ) : null + } +
+
+ ); + } +} + +export default BackTop; diff --git a/components/BackTop/README.md b/components/BackTop/README.md new file mode 100644 index 0000000..e5b7f3f --- /dev/null +++ b/components/BackTop/README.md @@ -0,0 +1,9 @@ +### 默认 +```js + +``` + +### 自定义 +```js + alert('到顶了!')}>回到顶部 +``` \ No newline at end of file diff --git a/components/BackTop/__tests__/e2e.test.tsx b/components/BackTop/__tests__/e2e.test.tsx new file mode 100644 index 0000000..3f1e6c0 --- /dev/null +++ b/components/BackTop/__tests__/e2e.test.tsx @@ -0,0 +1,12 @@ +import * as React from 'react'; +import {Simulate, renderIntoDocument, scryRenderedComponentsWithType} from 'react-dom/test-utils'; +import {findDOMNode} from 'react-dom'; +import Backtop from '../index'; + +describe('多选', () => { + test('点击其中一个选项后可通过 onChange 拿到最新的值', () => { + const component = renderIntoDocument( + , + ) as Backtop; + }); +}); diff --git a/components/BackTop/__tests__/props.test.tsx b/components/BackTop/__tests__/props.test.tsx new file mode 100644 index 0000000..a3f907b --- /dev/null +++ b/components/BackTop/__tests__/props.test.tsx @@ -0,0 +1,14 @@ +import * as renderer from 'react-test-renderer'; +import * as React from 'react'; +import Backtop from '../index'; + +describe('Props', () => { + + test('默认', () => { + const component = renderer.create( + , + ); + const tree = component.toJSON(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/components/BackTop/assist.tsx b/components/BackTop/assist.tsx new file mode 100644 index 0000000..008b927 --- /dev/null +++ b/components/BackTop/assist.tsx @@ -0,0 +1,20 @@ +export const backTop = (durations: number, callback: () => void | undefined) => { + let dom: HTMLElement; + if (document.documentElement.scrollTop) { + dom = document.documentElement; + } else { + dom = document.body; + } + const scrollTop = dom.scrollTop; + // tslint:disable + for (let i = 60; i >= 0; i--) { + setTimeout(((i) => { + return () => { + dom.scrollTop = scrollTop * i / 60; + if (i === 0 && typeof callback === 'function') { + callback(); + } + }; + })(i), durations * (1 - i / 60)); + } +}; diff --git a/components/BackTop/index.tsx b/components/BackTop/index.tsx new file mode 100644 index 0000000..b773cbb --- /dev/null +++ b/components/BackTop/index.tsx @@ -0,0 +1,5 @@ +import Backtop from './Backtop'; +import { IBackTopProps } from './Backtop'; + +export {IBackTopProps}; +export default Backtop; diff --git a/components/BackTop/style/index.less b/components/BackTop/style/index.less new file mode 100644 index 0000000..e40a1ac --- /dev/null +++ b/components/BackTop/style/index.less @@ -0,0 +1,28 @@ +@import './var.less'; + +@backtop-prefix-cls: ~"@{css-prefix}-backtop"; +.@{backtop-prefix-cls} { + position: fixed; + z-index: 100; + cursor: pointer; + display: block; + border-radius: 4px; + + &-default { + background-color: @primary-color; + border-radius: @border-radius-base; + box-shadow: 0 1px 3px rgba(0,0,0,.2); + transition: all .2s ease-in-out; + display: block; + + :hover { + background-color: @primary-color-hover; + } + } + + i { + color: #fff; + font-size: 24px; + padding: 8px 12px; + } +} \ No newline at end of file diff --git a/components/BackTop/style/var.less b/components/BackTop/style/var.less new file mode 100644 index 0000000..a7ba615 --- /dev/null +++ b/components/BackTop/style/var.less @@ -0,0 +1,2 @@ +@import '../../styles/var.less'; +@import '../../styles/common/reset.less'; \ No newline at end of file diff --git a/docs/pages/BackTop/demo/backTopCustom.tsx b/docs/pages/BackTop/demo/backTopCustom.tsx index b2d99c5..66d8f84 100644 --- a/docs/pages/BackTop/demo/backTopCustom.tsx +++ b/docs/pages/BackTop/demo/backTopCustom.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; -import { Backtop } from '../../../../components/'; +import { BackTop } from '../../../../components/'; const img = require('./fire.png'); export default function () { return ( - alert('到顶了!')}> + alert('到顶了!')}> - + ) } diff --git a/docs/pages/BackTop/demo/backTopDemo.tsx b/docs/pages/BackTop/demo/backTopDemo.tsx index a7f12b3..05d0b08 100644 --- a/docs/pages/BackTop/demo/backTopDemo.tsx +++ b/docs/pages/BackTop/demo/backTopDemo.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; -import { Backtop } from '../../../../components/'; +import { BackTop } from '../../../../components/'; export default function () { return (
- +
) } diff --git a/docs/pages/index.tsx b/docs/pages/index.tsx index 52bd4a9..42c6ae7 100644 --- a/docs/pages/index.tsx +++ b/docs/pages/index.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { Component } from 'react'; import { Switch, Route, Redirect } from 'react-router-dom'; import { Link } from 'react-router-dom'; -import {Menu, Backtop} from '../../components/'; +import {Menu, BackTop} from '../../components/'; import './index.less'; import menuObj from './menu'; import { MenuItem } from '../../components/Menu/MenuItem'; @@ -27,7 +27,7 @@ export default class Components extends Component { const current = this.props.match.params.name; return (
- +
Yoshino