diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index da72ef5171d..d8cb8be492f 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -34,6 +34,7 @@ - - `n-image` adds showPreview methods, closes [#6695](https://github.com/tusen-ai/naive-ui/issues/6695). - `n-image-preview` `n-image-group` support being used independently. - `n-input-otp` adds `focusOnChar` util method, closes [#7073](https://github.com/tusen-ai/naive-ui/issues/7073). +- `n-back-top` adds `direction` prop,closes [#6830](https://github.com/tusen-ai/naive-ui/issues/6830) ## 2.42.0 diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index 8b74b2fcc71..846f10b6df8 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -34,6 +34,7 @@ - `n-image` 增加 showPreview 方法,关闭 [#6695](https://github.com/tusen-ai/naive-ui/issues/6695) - `n-image-preview`,`n-image-group` 支持单独使用 - `n-input-otp` 增加 `focusOnChar` 方法,关闭 [#7073](https://github.com/tusen-ai/naive-ui/issues/7073) +- `n-back-top` 增加 `direction` 属性,关闭 [#6830](https://github.com/tusen-ai/naive-ui/issues/6830) ## 2.42.0 diff --git a/src/back-top/demos/enUS/index.demo-entry.md b/src/back-top/demos/enUS/index.demo-entry.md index 228a75a4308..44618aae57a 100644 --- a/src/back-top/demos/enUS/index.demo-entry.md +++ b/src/back-top/demos/enUS/index.demo-entry.md @@ -13,6 +13,7 @@ basic.vue visibility-height.vue change-position.vue target-container-selector.vue +to-bottom.vue ``` ## API @@ -26,5 +27,6 @@ target-container-selector.vue | right | `number \| string` | `40` | The width of BackTop from the right side of the page | | show | `boolean` | `undefined` | Whether to show BackTop | | to | `string \| HTMLElement` | `'body'` | Container node to show BackTop | +| direction | `'top' \| 'bottom'` | `'top'` | The default position for BackTop to return to is the top | | visibility-height | `number` | `180` | BackTop's trigger scroll top. | | on-update:show | `(value: boolean) => void` | `undefined` | Callback is triggered when back-top display changes. | diff --git a/src/back-top/demos/enUS/to-bottom.demo.vue b/src/back-top/demos/enUS/to-bottom.demo.vue new file mode 100644 index 00000000000..a9453cd6fcb --- /dev/null +++ b/src/back-top/demos/enUS/to-bottom.demo.vue @@ -0,0 +1,23 @@ + +# Scroll to the bottom + +BackTop determines whether to scroll to the top or the bottom by setting the `direction`. + + + + + diff --git a/src/back-top/demos/zhCN/index.demo-entry.md b/src/back-top/demos/zhCN/index.demo-entry.md index 55d04e8de7f..41b91b45866 100644 --- a/src/back-top/demos/zhCN/index.demo-entry.md +++ b/src/back-top/demos/zhCN/index.demo-entry.md @@ -13,6 +13,7 @@ basic.vue visibility-height.vue change-position.vue target-container-selector.vue +to-bottom.vue ``` ## API @@ -26,5 +27,6 @@ target-container-selector.vue | right | `number \| string` | `40` | BackTop 距离页面右侧的宽度 | | show | `boolean` | `undefined` | 是否显示 BackTop(受控) | | to | `string \| HTMLElement` | `'body'` | BackTop 渲染的容器节点 | +| direction | `'top' \| 'bottom'` | `'top'` | BackTop 返回的位置,默认是返回顶部 | | visibility-height | `number` | `180` | 滚动时触发显示回到顶部的高度 | | on-update:show | `(value: boolean) => void` | `undefined` | BackTop 的 show 改变时触发事件 | diff --git a/src/back-top/demos/zhCN/to-bottom.demo.vue b/src/back-top/demos/zhCN/to-bottom.demo.vue new file mode 100644 index 00000000000..fa9bb8615d6 --- /dev/null +++ b/src/back-top/demos/zhCN/to-bottom.demo.vue @@ -0,0 +1,23 @@ + +# 滚动到底部 + +BackTop 通过设置 direction 决定滚动到顶部还是底部 + + + + + diff --git a/src/back-top/src/BackTop.tsx b/src/back-top/src/BackTop.tsx index 5bc074eb88a..799854172a6 100644 --- a/src/back-top/src/BackTop.tsx +++ b/src/back-top/src/BackTop.tsx @@ -58,6 +58,10 @@ export const backTopProps = { listenTo: [String, Object, Function] as PropType< string | HTMLElement | Document | (() => HTMLElement | Document) >, + direction: { + type: String, + default: 'top' + }, 'onUpdate:show': { type: Function, default: () => {} @@ -101,14 +105,25 @@ export default defineComponent({ const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props) const scrollTopRef = ref(null) - const uncontrolledShowRef = ref(false) + const scrollHeightRef = ref(null) + const clientHeightRef = ref(null) + const uncontrolledShowRef = ref(null) watchEffect(() => { const { value: scrollTop } = scrollTopRef + const { value: scrollHeight } = scrollHeightRef + const { value: clientHeight } = clientHeightRef if (scrollTop === null) { uncontrolledShowRef.value = false return } - uncontrolledShowRef.value = scrollTop >= props.visibilityHeight + if (props.direction === 'top') { + uncontrolledShowRef.value = scrollTop >= props.visibilityHeight + } + else { + uncontrolledShowRef.value + = scrollTop + clientHeight <= scrollHeight - props.visibilityHeight + } + // console.log(scrollTop, scrollHeight - props.visibilityHeight) }) const DomInfoReadyRef = ref(false) watch(uncontrolledShowRef, (value) => { @@ -180,11 +195,11 @@ export default defineComponent({ handleScroll() } function handleClick(): void { - ;(isDocument(scrollElement) + const target = isDocument(scrollElement) ? document.documentElement : scrollElement - ).scrollTo({ - top: 0, + target.scrollTo({ + top: props.direction === 'top' ? 0 : target.scrollHeight, behavior: 'smooth' }) } @@ -192,6 +207,12 @@ export default defineComponent({ scrollTopRef.value = ( isDocument(scrollElement) ? document.documentElement : scrollElement ).scrollTop + scrollHeightRef.value = ( + isDocument(scrollElement) ? document.documentElement : scrollElement + ).scrollHeight + clientHeightRef.value = ( + isDocument(scrollElement) ? document.documentElement : scrollElement + ).clientHeight if (!DomInfoReadyRef.value) { void nextTick(() => { DomInfoReadyRef.value = true