parent
118ae9a50b
commit
de00607dc7
@ -1,20 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders ./components/back-top/demo/basic.vue correctly 1`] = `
|
||||
<div class="ant-back-top fade-enter fade-enter-prepare" style="display: none;">
|
||||
<div class="ant-back-top-content">
|
||||
<div class="ant-back-top-icon"><span role="img" aria-label="vertical-align-top" class="anticon anticon-vertical-align-top"><svg focusable="false" class="" data-icon="vertical-align-top" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M859.9 168H164.1c-4.5 0-8.1 3.6-8.1 8v60c0 4.4 3.6 8 8.1 8h695.8c4.5 0 8.1-3.6 8.1-8v-60c0-4.4-3.6-8-8.1-8zM518.3 355a8 8 0 00-12.6 0l-112 141.7a7.98 7.98 0 006.3 12.9h73.9V848c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V509.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 355z"></path></svg></span></div>
|
||||
</div>
|
||||
</div>
|
||||
Scroll down to see the bottom-right
|
||||
<strong style="color: rgba(64, 64, 64, 0.6);">gray</strong>
|
||||
button.
|
||||
`;
|
||||
|
||||
exports[`renders ./components/back-top/demo/custom.vue correctly 1`] = `
|
||||
<div id="components-back-top-demo-custom">
|
||||
<div class="ant-back-top fade-enter fade-enter-prepare" style="display: none;">
|
||||
<div class="ant-back-top-inner">UP</div>
|
||||
</div> Scroll down to see the bottom-right <strong style="color: rgb(16, 136, 233);">blue</strong> button.
|
||||
</div>
|
||||
`;
|
@ -1,3 +0,0 @@
|
||||
import demoTest from '../../../tests/shared/demoTest';
|
||||
|
||||
demoTest('back-top');
|
@ -1,46 +0,0 @@
|
||||
import { mount } from '@vue/test-utils';
|
||||
import BackTop from '..';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
|
||||
describe('BackTop', () => {
|
||||
it('should scroll to top after click it', async () => {
|
||||
const wrapper = mount(BackTop, {
|
||||
props: {
|
||||
visibilityHeight: -1,
|
||||
},
|
||||
attachTo: 'body',
|
||||
});
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
|
||||
window.scrollY = y;
|
||||
window.pageYOffset = y;
|
||||
document.documentElement.scrollTop = y;
|
||||
});
|
||||
window.scrollTo(0, 400);
|
||||
expect(document.documentElement.scrollTop).toBe(400);
|
||||
await sleep(100);
|
||||
wrapper.find('.ant-back-top').trigger('click');
|
||||
await sleep(500);
|
||||
expect(document.documentElement.scrollTop).toBe(0);
|
||||
scrollToSpy.mockRestore();
|
||||
});
|
||||
it('support onClick', async () => {
|
||||
const onClick = jest.fn();
|
||||
const wrapper = mount(BackTop, {
|
||||
props: {
|
||||
visibilityHeight: -1,
|
||||
onClick,
|
||||
},
|
||||
attachTo: 'body',
|
||||
});
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
|
||||
window.scrollY = y;
|
||||
window.pageYOffset = y;
|
||||
});
|
||||
document.dispatchEvent(new Event('scroll'));
|
||||
window.scrollTo(0, 400);
|
||||
await sleep(10);
|
||||
wrapper.find('.ant-back-top').trigger('click');
|
||||
expect(onClick).toHaveBeenCalled();
|
||||
scrollToSpy.mockRestore();
|
||||
});
|
||||
});
|
@ -1,23 +0,0 @@
|
||||
<docs>
|
||||
---
|
||||
order: 0
|
||||
title:
|
||||
zh-CN: 基本使用
|
||||
en-US: Basic Usage
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
最简单的用法。
|
||||
|
||||
## en-US
|
||||
|
||||
The simplest usage.
|
||||
</docs>
|
||||
|
||||
<template>
|
||||
<a-back-top />
|
||||
Scroll down to see the bottom-right
|
||||
<strong style="color: rgba(64, 64, 64, 0.6)">gray</strong>
|
||||
button.
|
||||
</template>
|
@ -1,27 +0,0 @@
|
||||
<template>
|
||||
<demo-sort>
|
||||
<basic />
|
||||
<custom />
|
||||
</demo-sort>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Basic from './basic.vue';
|
||||
import Custom from './custom.vue';
|
||||
|
||||
import CN from '../index.zh-CN.md';
|
||||
import US from '../index.en-US.md';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
CN,
|
||||
US,
|
||||
components: {
|
||||
Basic,
|
||||
Custom,
|
||||
},
|
||||
setup() {
|
||||
return {};
|
||||
},
|
||||
});
|
||||
</script>
|
@ -1,30 +0,0 @@
|
||||
---
|
||||
category: Components
|
||||
type: Other
|
||||
title: BackTop
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/tJZ5jbTwX/BackTop.svg
|
||||
---
|
||||
|
||||
`BackTop` makes it easy to go back to the top of the page.
|
||||
|
||||
## When To Use
|
||||
|
||||
- When the page content is very long.
|
||||
- When you need to go back to the top very frequently in order to view the contents.
|
||||
|
||||
## API
|
||||
|
||||
> The distance to the bottom is set to `50px` by default, which is overridable.
|
||||
>
|
||||
> If you decide to use custom styles, please note the size limit: no more than `40px * 40px`.
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| target | specifies the scrollable area dom node | () => HTMLElement | () => window | |
|
||||
| visibilityHeight | the `BackTop` button will not show until the scroll height reaches this value | number | 400 | |
|
||||
|
||||
### events
|
||||
|
||||
| Events Name | Description | Arguments | Version |
|
||||
| --- | --- | --- | --- |
|
||||
| click | a callback function, which can be executed when you click the button | Function | |
|
@ -1,144 +0,0 @@
|
||||
import type { ExtractPropTypes, PropType } from 'vue';
|
||||
import {
|
||||
defineComponent,
|
||||
nextTick,
|
||||
onActivated,
|
||||
onBeforeUnmount,
|
||||
onMounted,
|
||||
reactive,
|
||||
ref,
|
||||
watch,
|
||||
onDeactivated,
|
||||
} from 'vue';
|
||||
import VerticalAlignTopOutlined from '@ant-design/icons-vue/VerticalAlignTopOutlined';
|
||||
import getScroll from '../_util/getScroll';
|
||||
import { getTransitionProps, Transition } from '../_util/transition';
|
||||
import scrollTo from '../_util/scrollTo';
|
||||
import { withInstall, eventType } from '../_util/type';
|
||||
import throttleByAnimationFrame from '../_util/throttleByAnimationFrame';
|
||||
import useConfigInject from '../config-provider/hooks/useConfigInject';
|
||||
import type { MouseEventHandler } from '../_util/EventInterface';
|
||||
import useStyle from './style';
|
||||
|
||||
export const backTopProps = () => ({
|
||||
visibilityHeight: { type: Number, default: 400 },
|
||||
duration: { type: Number, default: 450 },
|
||||
target: Function as PropType<() => HTMLElement | Window | Document>,
|
||||
prefixCls: String,
|
||||
onClick: eventType<MouseEventHandler>(),
|
||||
// visible: { type: Boolean, default: undefined }, // Only for test. Don't use it.
|
||||
});
|
||||
|
||||
export type BackTopProps = Partial<ExtractPropTypes<typeof backTopProps>>;
|
||||
|
||||
const BackTop = defineComponent({
|
||||
compatConfig: { MODE: 3 },
|
||||
name: 'ABackTopLegacy',
|
||||
inheritAttrs: false,
|
||||
props: backTopProps(),
|
||||
// emits: ['click'],
|
||||
setup(props, { slots, attrs, emit }) {
|
||||
const { prefixCls, direction } = useConfigInject('back-top', props);
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
const domRef = ref();
|
||||
const state = reactive({
|
||||
visible: false,
|
||||
scrollEvent: null,
|
||||
});
|
||||
|
||||
const getDefaultTarget = () =>
|
||||
domRef.value && domRef.value.ownerDocument ? domRef.value.ownerDocument : window;
|
||||
|
||||
const scrollToTop = (e: Event) => {
|
||||
const { target = getDefaultTarget, duration } = props;
|
||||
scrollTo(0, {
|
||||
getContainer: target,
|
||||
duration,
|
||||
});
|
||||
emit('click', e);
|
||||
};
|
||||
|
||||
const handleScroll = throttleByAnimationFrame((e: Event | { target: any }) => {
|
||||
const { visibilityHeight } = props;
|
||||
const scrollTop = getScroll(e.target, true);
|
||||
state.visible = scrollTop >= visibilityHeight;
|
||||
});
|
||||
|
||||
const bindScrollEvent = () => {
|
||||
const { target } = props;
|
||||
const getTarget = target || getDefaultTarget;
|
||||
const container = getTarget();
|
||||
handleScroll({ target: container });
|
||||
container?.addEventListener('scroll', handleScroll);
|
||||
};
|
||||
|
||||
const scrollRemove = () => {
|
||||
const { target } = props;
|
||||
const getTarget = target || getDefaultTarget;
|
||||
const container = getTarget();
|
||||
handleScroll.cancel();
|
||||
container?.removeEventListener('scroll', handleScroll);
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.target,
|
||||
() => {
|
||||
scrollRemove();
|
||||
nextTick(() => {
|
||||
bindScrollEvent();
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
bindScrollEvent();
|
||||
});
|
||||
});
|
||||
|
||||
onActivated(() => {
|
||||
nextTick(() => {
|
||||
bindScrollEvent();
|
||||
});
|
||||
});
|
||||
|
||||
onDeactivated(() => {
|
||||
scrollRemove();
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
scrollRemove();
|
||||
});
|
||||
|
||||
return () => {
|
||||
const defaultElement = (
|
||||
<div class={`${prefixCls.value}-content`}>
|
||||
<div class={`${prefixCls.value}-icon`}>
|
||||
<VerticalAlignTopOutlined />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
const divProps = {
|
||||
...attrs,
|
||||
onClick: scrollToTop,
|
||||
class: {
|
||||
[hashId.value]: true,
|
||||
[`${prefixCls.value}`]: true,
|
||||
[`${attrs.class}`]: attrs.class,
|
||||
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
|
||||
},
|
||||
};
|
||||
|
||||
const transitionProps = getTransitionProps('fade');
|
||||
return wrapSSR(
|
||||
<Transition {...transitionProps}>
|
||||
<div v-show={state.visible} {...divProps} ref={domRef}>
|
||||
{slots.default?.() || defaultElement}
|
||||
</div>
|
||||
</Transition>,
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default withInstall(BackTop);
|
@ -1,31 +0,0 @@
|
||||
---
|
||||
category: Components
|
||||
type: 其他
|
||||
subtitle: 回到顶部
|
||||
title: BackTop
|
||||
cover: https://gw.alipayobjects.com/zos/alicdn/tJZ5jbTwX/BackTop.svg
|
||||
---
|
||||
|
||||
返回页面顶部的操作按钮。
|
||||
|
||||
## 何时使用
|
||||
|
||||
- 当页面内容区域比较长时;
|
||||
- 当用户需要频繁返回顶部查看相关内容时。
|
||||
|
||||
## API
|
||||
|
||||
> 有默认样式,距离底部 `50px`,可覆盖。
|
||||
>
|
||||
> 自定义样式宽高不大于 40px \* 40px。
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| target | 设置需要监听其滚动事件的元素,值为一个返回对应 DOM 元素的函数 | Function | () => window | |
|
||||
| visibilityHeight | 滚动高度达到此参数值才出现 `BackTop` | number | 400 | |
|
||||
|
||||
### 事件
|
||||
|
||||
| 事件名称 | 说明 | 回调参数 | 版本 |
|
||||
| -------- | ------------------ | -------- | ---- |
|
||||
| click | 点击按钮的回调函数 | Function | |
|
@ -1,118 +0,0 @@
|
||||
import type { CSSObject } from '../../_util/cssinjs';
|
||||
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
||||
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
||||
import { resetComponent } from '../../style';
|
||||
|
||||
/** Component only token. Which will handle additional calculation of alias token */
|
||||
export interface ComponentToken {
|
||||
zIndexPopup: number;
|
||||
}
|
||||
|
||||
type BackTopToken = FullToken<'BackTop'> & {
|
||||
backTopBackground: string;
|
||||
backTopColor: string;
|
||||
backTopHoverBackground: string;
|
||||
backTopFontSize: number;
|
||||
backTopSize: number;
|
||||
|
||||
// Position
|
||||
backTopBlockEnd: number;
|
||||
backTopInlineEnd: number;
|
||||
backTopInlineEndMD: number;
|
||||
backTopInlineEndXS: number;
|
||||
};
|
||||
|
||||
// ============================== Shared ==============================
|
||||
const genSharedBackTopStyle: GenerateStyle<BackTopToken, CSSObject> = (token): CSSObject => {
|
||||
const { componentCls, backTopFontSize, backTopSize, zIndexPopup } = token;
|
||||
|
||||
return {
|
||||
[componentCls]: {
|
||||
...resetComponent(token),
|
||||
|
||||
position: 'fixed',
|
||||
insetInlineEnd: token.backTopInlineEnd,
|
||||
insetBlockEnd: token.backTopBlockEnd,
|
||||
zIndex: zIndexPopup,
|
||||
width: 40,
|
||||
height: 40,
|
||||
cursor: 'pointer',
|
||||
|
||||
'&:empty': {
|
||||
display: 'none',
|
||||
},
|
||||
|
||||
[`${componentCls}-content`]: {
|
||||
width: backTopSize,
|
||||
height: backTopSize,
|
||||
overflow: 'hidden',
|
||||
color: token.backTopColor,
|
||||
textAlign: 'center',
|
||||
backgroundColor: token.backTopBackground,
|
||||
borderRadius: backTopSize,
|
||||
transition: `all ${token.motionDurationMid}`,
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: token.backTopHoverBackground,
|
||||
transition: `all ${token.motionDurationMid}`,
|
||||
},
|
||||
},
|
||||
|
||||
// change to .backtop .backtop-icon
|
||||
[`${componentCls}-icon`]: {
|
||||
fontSize: backTopFontSize,
|
||||
lineHeight: `${backTopSize}px`,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const genMediaBackTopStyle: GenerateStyle<BackTopToken> = (token): CSSObject => {
|
||||
const { componentCls } = token;
|
||||
|
||||
return {
|
||||
[`@media (max-width: ${token.screenMD}px)`]: {
|
||||
[componentCls]: {
|
||||
insetInlineEnd: token.backTopInlineEndMD,
|
||||
},
|
||||
},
|
||||
|
||||
[`@media (max-width: ${token.screenXS}px)`]: {
|
||||
[componentCls]: {
|
||||
insetInlineEnd: token.backTopInlineEndXS,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genComponentStyleHook<'BackTop'>(
|
||||
'BackTop',
|
||||
|
||||
token => {
|
||||
const {
|
||||
fontSizeHeading3,
|
||||
colorTextDescription,
|
||||
colorTextLightSolid,
|
||||
colorText,
|
||||
controlHeightLG,
|
||||
} = token;
|
||||
|
||||
const backTopToken = mergeToken<BackTopToken>(token, {
|
||||
backTopBackground: colorTextDescription,
|
||||
backTopColor: colorTextLightSolid,
|
||||
backTopHoverBackground: colorText,
|
||||
backTopFontSize: fontSizeHeading3,
|
||||
backTopSize: controlHeightLG,
|
||||
|
||||
backTopBlockEnd: controlHeightLG * 1.25,
|
||||
backTopInlineEnd: controlHeightLG * 2.5,
|
||||
backTopInlineEndMD: controlHeightLG * 1.5,
|
||||
backTopInlineEndXS: controlHeightLG * 0.5,
|
||||
});
|
||||
return [genSharedBackTopStyle(backTopToken), genMediaBackTopStyle(backTopToken)];
|
||||
},
|
||||
token => ({
|
||||
zIndexPopup: token.zIndexBase + 10,
|
||||
}),
|
||||
);
|
Loading…
Reference in new issue