diff --git a/src/back-top/__test__/__snapshots__/demo.test.jsx.snap b/src/back-top/__test__/__snapshots__/demo.test.jsx.snap index f41168aa6..b01e1b454 100644 --- a/src/back-top/__test__/__snapshots__/demo.test.jsx.snap +++ b/src/back-top/__test__/__snapshots__/demo.test.jsx.snap @@ -24,52 +24,10 @@ exports[`BackTop > BackTop baseVue demo works fine 1`] = ` - -
- -
- - -`; - -exports[`BackTop > BackTop halfRoundVue demo works fine 1`] = ` -
- -
@@ -141,13 +99,9 @@ exports[`BackTop > BackTop mobileVue demo works fine 1`] = `

- 01 类型 + 形状

-

- 圆型返回顶部 -

+
BackTop mobileVue demo works fine 1`] = ` -
-
- -
- - - - -
-
- -

- 半圆型返回顶部 -

-
-
- - -
@@ -308,17 +206,6 @@ exports[`BackTop > BackTop mobileVue demo works fine 1`] = `
-
-
- -
- -
-
BackTop mobileVue demo works fine 1`] = `
- -
- -
- -
-
BackTop mobileVue demo works fine 1`] = `
- -
- -
- -
-
BackTop mobileVue demo works fine 1`] = `
- -
- -
- -
-
BackTop mobileVue demo works fine 1`] = `
- -
- -
- -
-
BackTop mobileVue demo works fine 1`] = `
- -
- -
- -
-
{ describe('props', () => { diff --git a/src/back-top/back-top.en-US.md b/src/back-top/back-top.en-US.md index bececb01f..a105a6ddb 100644 --- a/src/back-top/back-top.en-US.md +++ b/src/back-top/back-top.en-US.md @@ -1,15 +1,18 @@ :: BASE_DOC :: ## API + ### BackTop Props name | type | default | description | required -- | -- | -- | -- | -- +container | Function | - | Typescript:`() => HTMLElement` | N fixed | Boolean | true | \- | N -icon | Slot / Function / Boolean | true | Typescript:`TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N +icon | Boolean / Slot / Function | true | Typescript:`boolean \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N target | Function | - | Typescript:`() => HTMLElement` | N text | String | '' | \- | N -theme | String | round | options:round/half-round/round-dark/half-round-dark | N +theme | String | round | options: round/half-round/round-dark/half-round-dark | N +visibilityHeight | Number | 200 | \- | N onToTop | Function | | Typescript:`() => void`
| N ### BackTop Events @@ -18,8 +21,8 @@ name | params | description -- | -- | -- to-top | \- | \- - ### CSS Variables + The component provides the following CSS variables, which can be used to customize styles. Name | Default Value | Description -- | -- | -- @@ -30,4 +33,4 @@ Name | Default Value | Description --td-back-top-round-border-radius | @radius-circle | - --td-back-top-round-color | @font-gray-1 | - --td-back-top-round-dark-bg-color | @gray-color-14 | - ---td-back-top-round-dark-color | @font-white-1 | - +--td-back-top-round-dark-color | @font-white-1 | - \ No newline at end of file diff --git a/src/back-top/back-top.md b/src/back-top/back-top.md index 673d59fec..bf3380803 100644 --- a/src/back-top/back-top.md +++ b/src/back-top/back-top.md @@ -1,15 +1,18 @@ :: BASE_DOC :: ## API + ### BackTop Props -名称 | 类型 | 默认值 | 说明 | 必传 +名称 | 类型 | 默认值 | 描述 | 必传 -- | -- | -- | -- | -- +container | Function | - | 滚动的容器。TS 类型:`() => HTMLElement` | N fixed | Boolean | true | 是否绝对定位固定到屏幕右下方 | N -icon | Slot / Function / Boolean | true | 图标。TS 类型:`TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N +icon | Boolean / Slot / Function | true | 图标。TS 类型:`boolean \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N target | Function | - | 定位滚动到指定对象。TS 类型:`() => HTMLElement` | N text | String | '' | 文案 | N theme | String | round | 预设的样式类型。可选项:round/half-round/round-dark/half-round-dark | N +visibilityHeight | Number | 200 | 滚动高度达到此参数值才出现 | N onToTop | Function | | TS 类型:`() => void`
点击触发 | N ### BackTop Events @@ -18,8 +21,8 @@ onToTop | Function | | TS 类型:`() => void`
点击触发 | N -- | -- | -- to-top | \- | 点击触发 +### CSS Variables -### CSS 变量 组件提供了下列 CSS 变量,可用于自定义样式。 名称 | 默认值 | 描述 -- | -- | -- @@ -30,4 +33,4 @@ to-top | \- | 点击触发 --td-back-top-round-border-radius | @radius-circle | - --td-back-top-round-color | @font-gray-1 | - --td-back-top-round-dark-bg-color | @gray-color-14 | - ---td-back-top-round-dark-color | @font-white-1 | - +--td-back-top-round-dark-color | @font-white-1 | - \ No newline at end of file diff --git a/src/back-top/back-top.tsx b/src/back-top/back-top.tsx new file mode 100644 index 000000000..083f1e3d8 --- /dev/null +++ b/src/back-top/back-top.tsx @@ -0,0 +1,82 @@ +import { computed, defineComponent, onMounted, onUnmounted, ref } from 'vue'; +import { useElementBounding } from '@vueuse/core'; +import { BacktopIcon as TIconBackTop } from 'tdesign-icons-vue-next'; + +import { isBrowser } from '../shared'; +import props from './props'; +import config from '../config'; +import { useTNodeJSX } from '../hooks/tnode'; +import { usePrefixClass } from '../hooks/useClass'; + +const { prefix } = config; + +export default defineComponent({ + name: `${prefix}-back-top`, + props, + setup(props) { + const renderTNodeJSX = useTNodeJSX(); + const backTopClass = usePrefixClass('back-top'); + + const target = computed(() => { + if (!isBrowser) return undefined; + return props.target ? props.target() : window.document.documentElement; + }); + const container = ref(); + const { top } = useElementBounding(target); + const visible = ref(false); + const backTopClasses = computed(() => { + return { + [`${backTopClass.value}`]: true, + [`${backTopClass.value}--fixed`]: props.fixed, + [`${backTopClass.value}--${props.theme}`]: true, + }; + }); + + const handleClick = () => { + if (isBrowser) { + container.value.scrollTop = 0 + top.value; + props.onToTop?.(); + } + }; + const getContainer = (container: Function) => { + if (typeof container === 'function') { + return container(); + } + return document.documentElement; + }; + + onMounted(() => { + if (isBrowser) { + container.value = getContainer(props.container); + container.value.onscroll = () => { + if (container.value?.scrollTop >= props.visibilityHeight) { + visible.value = true; + } + if (visible.value && container.value?.scrollTop < props.visibilityHeight) { + visible.value = false; + } + }; + } + }); + + onUnmounted(() => { + container.value.onscroll = null; + }); + + const readerIcon = () => { + if (props.icon === true) { + return ; + } + + return renderTNodeJSX('icon'); + }; + return () => { + return ( +
+ {readerIcon()} + {props.text && {props.text}} +
+ ); + }; + }, +}); diff --git a/src/back-top/back-top.vue b/src/back-top/back-top.vue deleted file mode 100644 index 9dccfe07e..000000000 --- a/src/back-top/back-top.vue +++ /dev/null @@ -1,62 +0,0 @@ - - - diff --git a/src/back-top/demos/base.vue b/src/back-top/demos/base.vue index 273f33d7f..c6d0b3d5e 100644 --- a/src/back-top/demos/base.vue +++ b/src/back-top/demos/base.vue @@ -10,9 +10,19 @@ }" @click="onClick('round', '顶部')" /> +
- +
@@ -20,7 +30,7 @@ import { ref, defineProps, defineEmits, h } from 'vue'; import { CloseIcon } from 'tdesign-icons-vue-next'; -defineProps({ +const props = defineProps({ visible: { type: Boolean, default: false, @@ -29,6 +39,9 @@ defineProps({ type: Object, default: () => {}, }, + container: { + type: Function, + }, }); const emit = defineEmits(['close']); const theme = ref('round'); @@ -40,7 +53,7 @@ const onClick = (tem: string, txt: string) => { text.value = txt; theme.value = tem; emit('close'); - window.scrollTo(0, 1200); + props.container().scrollTo(0, 1200); }; function handleToTop() { console.log('handleToTop'); @@ -50,6 +63,7 @@ function handleToTop() { diff --git a/src/back-top/demos/mobile.vue b/src/back-top/demos/mobile.vue index 702f8ddaa..332711dc6 100644 --- a/src/back-top/demos/mobile.vue +++ b/src/back-top/demos/mobile.vue @@ -1,12 +1,9 @@