feat: 新增可配置选项
This commit is contained in:
parent
92fb84d946
commit
19dd1f002a
@ -1,6 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { usePageFrontmatter, } from '@vuepress/client'
|
||||
import { useWindowScroll } from '@vueuse/core'
|
||||
import { computed } from 'vue'
|
||||
import { ref, watchPostEffect } from 'vue'
|
||||
import { useSidebar } from '../../composables/sidebar.js'
|
||||
import NavBarAppearance from './NavBarAppearance.vue'
|
||||
import NavBarExtra from './NavBarExtra.vue'
|
||||
@ -16,13 +17,18 @@ defineProps<{
|
||||
}>()
|
||||
defineEmits<(e: 'toggle-screen') => void>()
|
||||
|
||||
const matter = usePageFrontmatter()
|
||||
|
||||
const { y } = useWindowScroll()
|
||||
const { hasSidebar } = useSidebar()
|
||||
|
||||
const classes = computed(() => ({
|
||||
'has-sidebar': hasSidebar.value,
|
||||
'fill': y.value > 0,
|
||||
}))
|
||||
const classes = ref<Record<string, boolean>>({})
|
||||
watchPostEffect(() => {
|
||||
classes.value = {
|
||||
'has-sidebar': hasSidebar.value,
|
||||
top: !!matter.value.home && y.value === 0,
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -58,13 +64,10 @@ const classes = computed(() => ({
|
||||
border-bottom: 1px solid transparent;
|
||||
padding: 0 8px 0 24px;
|
||||
height: var(--vp-nav-height);
|
||||
transition: border-color 0.5s, background-color 0.5s;
|
||||
pointer-events: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.navbar-wrapper.has-sidebar {
|
||||
border-bottom-color: var(--vp-c-gutter);
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.navbar-wrapper {
|
||||
@ -74,11 +77,10 @@ const classes = computed(() => ({
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.navbar-wrapper.has-sidebar {
|
||||
border-bottom-color: transparent;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.navbar-wrapper.fill:not(.has-sidebar) {
|
||||
.navbar-wrapper:not(.has-sidebar):not(.top) {
|
||||
border-bottom-color: var(--vp-c-gutter);
|
||||
background-color: var(--vp-nav-bg-color);
|
||||
}
|
||||
@ -166,13 +168,18 @@ const classes = computed(() => ({
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.navbar-wrapper.has-sidebar .content-body,
|
||||
.navbar-wrapper.fill .content-body {
|
||||
.navbar-wrapper:not(.top) .content-body {
|
||||
position: relative;
|
||||
background-color: var(--vp-nav-bg-color);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.content-body {
|
||||
column-gap: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.menu + .translations::before,
|
||||
.menu + .appearance::before,
|
||||
.menu + .social-links::before,
|
||||
|
||||
@ -11,8 +11,8 @@ watch(
|
||||
)
|
||||
|
||||
function focusOnTargetAnchor({ target }: Event) {
|
||||
const el = document.querySelector<HTMLAnchorElement>(
|
||||
(target as HTMLAnchorElement).hash
|
||||
const el = document.getElementById(
|
||||
decodeURIComponent((target as HTMLAnchorElement).hash).slice(1)
|
||||
)
|
||||
|
||||
if (el) {
|
||||
@ -62,9 +62,6 @@ function focusOnTargetAnchor({ target }: Event) {
|
||||
clip-path: none;
|
||||
}
|
||||
|
||||
.dark .skip-link {
|
||||
color: var(--vp-c-green);
|
||||
}
|
||||
|
||||
@media (min-width: 1280px) {
|
||||
.skip-link {
|
||||
|
||||
@ -3,27 +3,28 @@ import { computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { EXTERNAL_URL_RE } from '../utils/index.js'
|
||||
|
||||
const props = defineProps<{
|
||||
interface Props {
|
||||
tag?: string
|
||||
size?: 'medium' | 'big'
|
||||
theme?: 'brand' | 'alt' | 'sponsor'
|
||||
text: string
|
||||
href?: string
|
||||
}>()
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
size: 'medium',
|
||||
theme: 'brand',
|
||||
tag: undefined,
|
||||
href: undefined,
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
const classes = computed(() => [props.size ?? 'medium', props.theme ?? 'brand'])
|
||||
|
||||
const isExternal = computed(
|
||||
() => props.href && EXTERNAL_URL_RE.test(props.href)
|
||||
)
|
||||
|
||||
const component = computed(() => {
|
||||
if (props.tag) {
|
||||
return props.tag
|
||||
}
|
||||
|
||||
return props.href ? 'a' : 'button'
|
||||
return props.tag || props.href ? 'a' : 'button'
|
||||
})
|
||||
|
||||
const linkTo = (e: Event) => {
|
||||
@ -38,7 +39,7 @@ const linkTo = (e: Event) => {
|
||||
<Component
|
||||
:is="component"
|
||||
class="VPButton"
|
||||
:class="classes"
|
||||
:class="[size, theme]"
|
||||
:href="href"
|
||||
:target="isExternal ? '_blank' : undefined"
|
||||
:rel="isExternal ? 'noreferrer' : undefined"
|
||||
|
||||
@ -42,7 +42,13 @@ const { hasSidebar } = useSidebar()
|
||||
}
|
||||
|
||||
.plume-footer :deep(a) {
|
||||
color: var(--vp-c-brand);
|
||||
text-decoration-line: underline;
|
||||
text-underline-offset: 2px;
|
||||
transition: color 0.25s;
|
||||
}
|
||||
|
||||
.plume-footer :deep(a:hover) {
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
|
||||
@ -1,12 +1,16 @@
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
interface Props {
|
||||
text?: string
|
||||
type?: 'info' | 'tip' | 'warning' | 'danger'
|
||||
}>()
|
||||
}
|
||||
withDefaults(defineProps<Props>(), {
|
||||
type: 'tip',
|
||||
text: undefined
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span class="badge-view" :class="type ?? 'tip'">
|
||||
<span class="badge-view" :class="type">
|
||||
<slot>{{ text }}</slot>
|
||||
</span>
|
||||
</template>
|
||||
@ -16,11 +20,11 @@ defineProps<{
|
||||
display: inline-block;
|
||||
margin-left: 2px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 10px;
|
||||
padding: 0 8px;
|
||||
line-height: 18px;
|
||||
border-radius: 12px;
|
||||
padding: 0 10px;
|
||||
line-height: 22px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
font-weight: 500;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
|
||||
@ -3,8 +3,11 @@ import { withBase } from '@vuepress/client'
|
||||
import { ref } from 'vue'
|
||||
import LayoutContent from '../components/LayoutContent.vue'
|
||||
import Nav from '../components/Nav/index.vue'
|
||||
import { useThemeLocaleData } from '../composables'
|
||||
|
||||
const root = ref('/')
|
||||
const themeData = useThemeLocaleData()
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -12,17 +15,16 @@ const root = ref('/')
|
||||
<Nav />
|
||||
<LayoutContent is-not-found>
|
||||
<div class="not-found">
|
||||
<p class="code">404</p>
|
||||
<h1 class="title">PAGE NOT FOUND</h1>
|
||||
<p class="code">{{ themeData.notFound?.code ?? '404' }}</p>
|
||||
<h1 class="title">{{ themeData.notFound?.title ?? 'PAGE NOT FOUND' }}</h1>
|
||||
<div class="divider" />
|
||||
<blockquote class="quote">
|
||||
But if you don't change your direction, and if you keep looking, you
|
||||
may end up where you are heading.
|
||||
{{ themeData.notFound?.quote ?? `But if you don't change your direction, and if you keep looking, you may end up where you are heading.` }}
|
||||
</blockquote>
|
||||
|
||||
<div class="action">
|
||||
<a class="link" :href="withBase(root)" aria-label="go to home">
|
||||
Take me home
|
||||
<a class="link" :href="withBase(root)" :aria-label="themeData.notFound?.linkLabel ?? 'go to home'">
|
||||
{{ themeData.notFound?.linkText ?? 'Take me home' }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -177,14 +177,24 @@ export interface PlumeThemeLocaleData extends LocaleData {
|
||||
*/
|
||||
openInNewWindow?: string | boolean
|
||||
|
||||
// notFound?: string[]
|
||||
|
||||
// backToHome?: string
|
||||
|
||||
sidebarMenuLabel?: string
|
||||
|
||||
returnToTopLabel?: string
|
||||
|
||||
footer?:
|
||||
| false
|
||||
| {
|
||||
message?: string
|
||||
copyright?: string
|
||||
}
|
||||
|
||||
notFound?: {
|
||||
code?: string | number
|
||||
title?: string
|
||||
quote?: string
|
||||
linkLabel?: string
|
||||
linkText?: string
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user