Skip to content

Commit

Permalink
feat(plugin-back-to-top): rebuild plugin (#55)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mister-Hope authored Feb 3, 2024
1 parent d91cf15 commit 1900257
Show file tree
Hide file tree
Showing 22 changed files with 381 additions and 58 deletions.
14 changes: 14 additions & 0 deletions docs/plugins/back-to-top.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ export default {
}
```

## Options

### threshold

- Type: `number`
- Default: `100`
- Details: Scroll threshold distance to display back to top button (in pixels)

### progress

- Type: `boolean`
- Default: `true`
- Details: Whether display progress bar around icon

## Styles

You can customize the style of the _back to top_ button via CSS variables:
Expand Down
16 changes: 12 additions & 4 deletions docs/themes/default/plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@ export default {

## themePlugins.backToTop

- Type: `boolean`
- Type: `BackToTopPluginOptions | boolean`

- Default: `true`

- Details:

Enable [@vuepress/plugin-back-to-top](../../plugins/back-to-top.md) or not.

Object value is supported as plugin options.

## themePlugins.container

- Type: `Record<ContainerType, boolean>`
Expand Down Expand Up @@ -68,14 +70,16 @@ export default {

## themePlugins.copyCode

- Type: `boolean`
- Type: `CopyCodePluginOptions | boolean`

- Default: `true`

- Details:

Enable [@vuepress/plugin-copy-code](../../plugins/copy-code.md) or not.

Object value is supported as plugin options.

## themePlugins.git

- Type: `boolean`
Expand Down Expand Up @@ -108,20 +112,24 @@ export default {

## themePlugins.seo

- Type: `boolean`
- Type: `SeoPluginOptions | boolean`

- Default: `true`

- Details:

Enable [@vuepress/plugin-seo](../../plugins/seo/README.md) or not.

Object value is supported as plugin options.

## themePlugins.sitemap

- Type: `boolean`
- Type: `SitemapPluginOptions | boolean`

- Default: `true`

- Details:

Enable [@vuepress/plugin-sitemap](../../plugins/sitemap/README.md) or not.

Object value is supported as plugin options.
14 changes: 14 additions & 0 deletions docs/zh/plugins/back-to-top.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ export default {
}
```

## 选项

### threshold

- 类型:`数字`
- 默认值:`100`
- 详情:显示返回顶部按钮的滚动阈值距离(以像素为单位)

### progress

- 类型:`布尔值`
- 默认值:`true`
- 详情:是否在图标周围显示进度条

## 样式

你可以通过 CSS 变量来自定义 _返回顶部_ 按钮的样式:
Expand Down
16 changes: 12 additions & 4 deletions docs/zh/themes/default/plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@ export default {

### themePlugins.backToTop

- 类型: `boolean`
- 类型: `BackToTopPluginOptions | boolean`

- 默认值: `true`

- 详情:

是否启用 [@vuepress/plugin-back-to-top](../../plugins/back-to-top.md)

支持对象格式以作为插件选项。

## themePlugins.container

- 类型: `Record<ContainerType, boolean>`
Expand All @@ -58,14 +60,16 @@ export default {

## themePlugins.copyCode

- 类型: `boolean`
- 类型: `CopyCodePluginOptions | boolean`

- 默认值: `true`

- 详情:

是否启用 [@vuepress/plugin-copy-code](../../plugins/copy-code.md)

支持对象格式以作为插件选项。

## themePlugins.externalLinkIcon

- 类型: `boolean`
Expand Down Expand Up @@ -108,20 +112,24 @@ export default {

## themePlugins.seo

- 类型: `boolean`
- 类型: `SeoPluginOptions | boolean`

- 默认值: `true`

- 详情:

是否启用 [@vuepress/plugin-seo](../../plugins/seo/README.md)

支持对象格式以作为插件选项。

## themePlugins.sitemap

- 类型: `boolean`
- 类型: `SitemapPluginOptions | boolean`

- 默认值: `true`

- 详情:

是否启用 [@vuepress/plugin-sitemap](../../plugins/sitemap/README.md)

支持对象格式以作为插件选项。
3 changes: 2 additions & 1 deletion plugins/plugin-back-to-top/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"style": "sass src:lib --no-source-map"
},
"dependencies": {
"ts-debounce": "^4.0.0",
"@vuepress/helper": "workspace:*",
"@vueuse/core": "^10.7.2",
"vue": "^3.4.15"
},
"peerDependencies": {
Expand Down
102 changes: 79 additions & 23 deletions plugins/plugin-back-to-top/src/client/components/BackToTop.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,93 @@
import { debounce } from 'ts-debounce'
import { computed, defineComponent, h, onMounted, ref, Transition } from 'vue'
import { getScrollTop, scrollToTop } from '../utils.js'
import { useLocaleConfig } from '@vuepress/helper/client'
import { useElementSize, useWindowScroll, useWindowSize } from '@vueuse/core'
import {
computed,
defineComponent,
h,
onMounted,
shallowRef,
Transition,
} from 'vue'
import { usePageFrontmatter } from 'vuepress/client'
import type { BackToTopPluginLocaleConfig } from '../../shared/index.js'

import '../styles/vars.css'
import '../styles/back-to-top.css'

declare const __BACK_TO_TOP_LOCALES__: BackToTopPluginLocaleConfig
declare const __BACK_TO_TOP_PROGRESS__: boolean
declare const __BACK_TO_TOP_THRESHOLD__: number

export const BackToTop = defineComponent({
name: 'BackToTop',

setup() {
const scrollTop = ref(0)
const show = computed(() => scrollTop.value > 300)
const onScroll = debounce(() => {
scrollTop.value = getScrollTop()
}, 100)
setup(props) {
const pageFrontmatter = usePageFrontmatter<{ backToTop?: boolean }>()
const locale = useLocaleConfig(__BACK_TO_TOP_LOCALES__)
const body = shallowRef<HTMLElement>()
const { height: bodyHeight } = useElementSize(body)
const { height: windowHeight } = useWindowSize()

onMounted(() => {
scrollTop.value = getScrollTop()
/** Scroll distance */
const { y } = useWindowScroll()

window.addEventListener('scroll', () => onScroll())
})
/** Whether to display button */
const show = computed(
() =>
pageFrontmatter.value.backToTop !== false &&
y.value > __BACK_TO_TOP_THRESHOLD__,
)

const backToTopEl = h('div', { class: 'back-to-top', onClick: scrollToTop })
const progress = computed(
() => (y.value / (bodyHeight.value - windowHeight.value)) * 100,
)

onMounted(() => {
body.value = document.body
})

return () =>
h(
Transition,
{
name: 'back-to-top',
},
() => (show.value ? backToTopEl : null),
h(Transition, { name: 'back-to-top' }, () =>
show.value
? h(
'button',
{
'type': 'button',
'class': 'vp-back-to-top-button',
'aria-label': locale.value.backToTop,
'onClick': () => {
window.scrollTo({ top: 0, behavior: 'smooth' })
},
},
[
__BACK_TO_TOP_PROGRESS__
? h(
'span',
{
'class': 'vp-scroll-progress',
'role': 'progressbar',
'aria-labelledby': 'loadinglabel',
'aria-valuenow': progress.value,
},
h(
'svg',
h('circle', {
cx: '50%',
cy: '50%',
style: {
'stroke-dasharray': `calc(${
Math.PI * progress.value
}% - ${4 * Math.PI}px) calc(${Math.PI * 100}% - ${
4 * Math.PI
}px)`,
},
}),
),
)
: null,
h('div', { class: 'back-to-top-icon' }),
],
)
: null,
)
},
})

export default BackToTop
2 changes: 2 additions & 0 deletions plugins/plugin-back-to-top/src/client/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { defineClientConfig } from 'vuepress/client'
import type { ClientConfig } from 'vuepress/client'
import { BackToTop } from './components/index.js'

import './styles/vars.css'

export default defineClientConfig({
rootComponents: [BackToTop],
}) as ClientConfig
82 changes: 68 additions & 14 deletions plugins/plugin-back-to-top/src/client/styles/back-to-top.scss
Original file line number Diff line number Diff line change
@@ -1,25 +1,79 @@
.back-to-top {
cursor: pointer;
position: fixed;
bottom: 2rem;
right: 2.5rem;
width: 2rem;
height: 1.2rem;
background-color: var(--back-to-top-color);
mask: url('back-to-top.svg') no-repeat;
z-index: var(--back-to-top-z-index);
.vp-back-to-top-button {
position: fixed !important;
bottom: 4rem;
inset-inline-end: 1rem;
z-index: 100;

&:hover {
background-color: var(--back-to-top-color-hover);
}
width: 3rem;
height: 3rem;
padding: 0.5rem;
border-width: 0;
border-radius: 50%;

background: var(--back-to-top-bg-color);
color: var(--back-to-top-color);
box-shadow: 2px 2px 10px 4px var(--back-to-top-shadow);

cursor: pointer;

@media (max-width: 959px) {
display: none;
width: 2.5rem;
height: 2.5rem;
}

@media print {
display: none;
}

&:hover {
color: var(--back-to-top-color-hover);
}

.back-to-top-icon {
overflow: hidden;
width: 100%;
height: 100%;
background: currentcolor;
border-radius: 50%;
-webkit-mask-image: var(--back-to-top-icon);
mask-image: var(--back-to-top-icon);
-webkit-mask-position: 50%;
mask-position: 50%;
-webkit-mask-size: cover;
mask-size: cover;
}
}

.vp-scroll-progress {
position: absolute;
right: -2px;
bottom: -2px;

width: calc(100% + 4px);
height: calc(100% + 4px);

svg {
width: 100%;
height: 100%;
}

circle {
opacity: 0.9;
fill: none;
stroke: currentColor;

transform: rotate(-90deg);
transform-origin: 50% 50%;

r: 22;

stroke-dasharray: 0% 314.1593%;
stroke-width: 3px;

@media (max-width: 959px) {
r: 18;
}
}
}

.back-to-top-enter-active,
Expand Down
Loading

0 comments on commit 1900257

Please sign in to comment.