perf: 优化首页组件结构
This commit is contained in:
parent
2be308b262
commit
83bae10344
@ -4,7 +4,7 @@ config:
|
||||
-
|
||||
type: hero
|
||||
full: true
|
||||
background: filter
|
||||
background: filter-blur
|
||||
hero:
|
||||
name: Theme Plume
|
||||
tagline: Vuepress Next Theme
|
||||
|
||||
@ -19,6 +19,12 @@ const components: Record<string, Component<any, any, any>> = {
|
||||
'custom': HomeCustom,
|
||||
}
|
||||
|
||||
const DEFAULT_HERO = {
|
||||
name: 'Theme Plume',
|
||||
tagline: 'VuePress Next Theme',
|
||||
text: '一个简约的,功能丰富的 vuepress 文档&博客 主题',
|
||||
}
|
||||
|
||||
const matter = usePageFrontmatter<PlumeThemeHomeFrontmatter>()
|
||||
|
||||
const config = computed(() => {
|
||||
@ -26,15 +32,22 @@ const config = computed(() => {
|
||||
if (config && config.length)
|
||||
return config
|
||||
|
||||
// @deprecated
|
||||
// 适配旧版本配置,将在正式版本中删去
|
||||
if (matter.value.banner) {
|
||||
return [{
|
||||
type: 'banner',
|
||||
banner: matter.value.banner,
|
||||
bannerMask: matter.value.bannerMask,
|
||||
hero: matter.value.hero ?? DEFAULT_HERO,
|
||||
}]
|
||||
}
|
||||
|
||||
return [{
|
||||
type: 'hero',
|
||||
full: true,
|
||||
background: 'filter',
|
||||
hero: matter.value.hero ?? {
|
||||
name: 'Theme Plume',
|
||||
tagline: 'VuePress Next Theme',
|
||||
text: '一个简约的,功能丰富的 vuepress 文档&博客 主题',
|
||||
},
|
||||
hero: matter.value.hero ?? DEFAULT_HERO,
|
||||
}]
|
||||
})
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ import type { PlumeThemeHomeBanner, PlumeThemeHomeFrontmatter } from '../../../s
|
||||
import { useDarkMode } from '../../composables/darkMode.js'
|
||||
import VButton from '../VButton.vue'
|
||||
|
||||
const props = defineProps<PlumeThemeHomeBanner & { onlyOnce: boolean }>()
|
||||
const props = defineProps<PlumeThemeHomeBanner>()
|
||||
|
||||
const DEFAULT_BANNER = 'http://file.mo7.cc/api/public/bz'
|
||||
|
||||
@ -49,6 +49,7 @@ const actions = computed(() => props.hero?.actions ?? matter.value.hero?.actions
|
||||
<p v-if="text" class="hero-text">
|
||||
{{ text }}
|
||||
</p>
|
||||
|
||||
<div v-if="actions.length" class="actions">
|
||||
<div v-for="action in actions" :key="action.link" class="action">
|
||||
<VButton
|
||||
@ -134,11 +135,7 @@ const actions = computed(() => props.hero?.actions ?? matter.value.hero?.actions
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: var(--vp-c-text-hero-text);
|
||||
|
||||
/* padding: 6px 20px; */
|
||||
border-radius: 5px;
|
||||
|
||||
/* background-color: rgba(0, 0, 0, 0.25); */
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
|
||||
@ -1,59 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { Content, withBase } from 'vuepress/client'
|
||||
import { computed } from 'vue'
|
||||
import { isLinkHttp } from 'vuepress/shared'
|
||||
import { Content } from 'vuepress/client'
|
||||
import type { PlumeThemeHomeCustom } from '../../../shared/index.js'
|
||||
import { useDarkMode } from '../../composables/index.js'
|
||||
import HomeBox from './HomeBox.vue'
|
||||
|
||||
const props = defineProps<PlumeThemeHomeCustom & { onlyOnce?: boolean }>()
|
||||
|
||||
const isDark = useDarkMode()
|
||||
|
||||
const styles = computed(() => {
|
||||
if (!props.backgroundImage)
|
||||
return null
|
||||
|
||||
const image = typeof props.backgroundImage === 'string' ? props.backgroundImage : (props.backgroundImage[isDark.value ? 'dark' : 'light'] ?? props.backgroundImage.light)
|
||||
|
||||
const link = isLinkHttp(image) ? props.backgroundImage : withBase(image)
|
||||
return {
|
||||
'background-image': `url(${link})`,
|
||||
'background-size': 'cover',
|
||||
'background-position': 'center',
|
||||
'background-repeat': 'no-repeat',
|
||||
'background-attachment': props.backgroundAttachment || '',
|
||||
}
|
||||
})
|
||||
const props = defineProps<PlumeThemeHomeCustom>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="home-custom" :style="styles">
|
||||
<div class="container">
|
||||
<Content class="plume-content" />
|
||||
</div>
|
||||
</div>
|
||||
<HomeBox class="home-custom" v-bind="props">
|
||||
<Content class="plume-content" />
|
||||
</HomeBox>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.home-custom {
|
||||
position: relative;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.home-custom {
|
||||
padding: 32px 48px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.home-custom {
|
||||
padding: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1152px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -2,10 +2,9 @@
|
||||
import { computed } from 'vue'
|
||||
import type { PlumeThemeHomeFeatures } from '../../../shared/index.js'
|
||||
import HomeFeature from './HomeFeature.vue'
|
||||
import HomeBox from './HomeBox.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
onlyOnce?: boolean
|
||||
} & PlumeThemeHomeFeatures>()
|
||||
const props = defineProps<PlumeThemeHomeFeatures>()
|
||||
|
||||
const grid = computed(() => {
|
||||
const length = props.features?.length
|
||||
@ -30,56 +29,40 @@ const grid = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="features" class="home-features">
|
||||
<div class="container">
|
||||
<h2 v-if="title" class="title" v-html="title" />
|
||||
<p v-if="description" class="description" v-html="description" />
|
||||
<div class="items">
|
||||
<div
|
||||
v-for="feature in features"
|
||||
:key="feature.title"
|
||||
class="item"
|
||||
:class="[grid]"
|
||||
>
|
||||
<HomeFeature
|
||||
:icon="feature.icon"
|
||||
:title="feature.title"
|
||||
:details="feature.details"
|
||||
:link="feature.link"
|
||||
:link-text="feature.linkText"
|
||||
:rel="feature.rel"
|
||||
:target="feature.target"
|
||||
/>
|
||||
</div>
|
||||
<HomeBox
|
||||
v-if="features"
|
||||
class="home-features"
|
||||
:type="type"
|
||||
:background-image="backgroundImage"
|
||||
:background-attachment="backgroundAttachment"
|
||||
:full="full"
|
||||
>
|
||||
<h2 v-if="title" class="title" v-html="title" />
|
||||
<p v-if="description" class="description" v-html="description" />
|
||||
|
||||
<div class="items">
|
||||
<div
|
||||
v-for="feature in features"
|
||||
:key="feature.title"
|
||||
class="item"
|
||||
:class="[grid]"
|
||||
>
|
||||
<HomeFeature
|
||||
:icon="feature.icon"
|
||||
:title="feature.title"
|
||||
:details="feature.details"
|
||||
:link="feature.link"
|
||||
:link-text="feature.linkText"
|
||||
:rel="feature.rel"
|
||||
:target="feature.target"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</HomeBox>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.home-features {
|
||||
position: relative;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.home-features {
|
||||
padding: 24px 48px 48px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.home-features {
|
||||
padding: 48px 64px 64px;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1152px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.container .title {
|
||||
.title {
|
||||
margin-bottom: 20px;
|
||||
font-size: 20px;
|
||||
font-weight: 900;
|
||||
@ -88,7 +71,7 @@ const grid = computed(() => {
|
||||
transition: color var(--t-color);
|
||||
}
|
||||
|
||||
.container .description {
|
||||
.description {
|
||||
margin-bottom: 20px;
|
||||
font-size: 16px;
|
||||
line-height: 1.7;
|
||||
@ -98,17 +81,17 @@ const grid = computed(() => {
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.container .title {
|
||||
.title {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.container .description {
|
||||
.description {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.container .title {
|
||||
.title {
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,18 +3,33 @@ import { usePageFrontmatter, withBase } from 'vuepress/client'
|
||||
import { isLinkHttp } from 'vuepress/shared'
|
||||
import { computed } from 'vue'
|
||||
import VButton from '../VButton.vue'
|
||||
import { useDarkMode } from '../../composables/index.js'
|
||||
import type { PlumeThemeHomeFrontmatter, PlumeThemeHomeHero } from '../../../shared/index.js'
|
||||
|
||||
const props = defineProps<PlumeThemeHomeHero & { onlyOnce: boolean }>()
|
||||
const props = defineProps<PlumeThemeHomeHero>()
|
||||
|
||||
const matter = usePageFrontmatter<PlumeThemeHomeFrontmatter>()
|
||||
const isDark = useDarkMode()
|
||||
|
||||
const background = computed(() => {
|
||||
const background = props.background !== 'filter' ? props.background : ''
|
||||
const link = background ? isLinkHttp(background) ? background : withBase(background) : ''
|
||||
return link
|
||||
? { 'background-image': `url(${link})` }
|
||||
: null
|
||||
const heroBackground = computed(() => {
|
||||
if (props.background === 'filter-blur')
|
||||
return null
|
||||
const image = props.backgroundImage
|
||||
? typeof props.backgroundImage === 'string'
|
||||
? props.backgroundImage
|
||||
: (props.backgroundImage[isDark.value ? 'dark' : 'light'] ?? props.backgroundImage.light)
|
||||
: ''
|
||||
const background = image || props.background
|
||||
|
||||
if (!background)
|
||||
return null
|
||||
|
||||
const link = isLinkHttp(background) ? background : withBase(background)
|
||||
return {
|
||||
'background-image': `url(${link})`,
|
||||
'background-attachment': props.backgroundAttachment || '',
|
||||
'--vp-hero-bg-filter': props.filter,
|
||||
}
|
||||
})
|
||||
|
||||
const hero = computed(() => props.hero ?? matter.value.hero ?? {})
|
||||
@ -23,9 +38,9 @@ const actions = computed(() => hero.value.actions ?? [])
|
||||
|
||||
<template>
|
||||
<div class="home-hero" :class="{ full: props.full, once: props.onlyOnce }">
|
||||
<div v-if="background" class="home-hero-bg" :style="background" />
|
||||
<div v-if="heroBackground" class="home-hero-bg" :style="heroBackground" />
|
||||
|
||||
<div v-if="props.background === 'filter'" class="bg-filter">
|
||||
<div v-if="background === 'filter-blur'" class="bg-filter">
|
||||
<div class="g g-1" />
|
||||
<div class="g g-2" />
|
||||
<div class="g g-3" />
|
||||
@ -36,16 +51,12 @@ const actions = computed(() => hero.value.actions ?? [])
|
||||
<h1 v-if="hero.name" class="hero-name" v-html="hero.name" />
|
||||
<p v-if="hero.tagline" class="hero-tagline" v-html="hero.tagline" />
|
||||
<p v-if="hero.text" class="hero-text" v-html="hero.text" />
|
||||
|
||||
<div v-if="actions.length" class="actions">
|
||||
<div class="action">
|
||||
<VButton
|
||||
v-for="action in actions"
|
||||
:key="action.link"
|
||||
tag="a"
|
||||
size="medium"
|
||||
:theme="action.theme"
|
||||
:text="action.text"
|
||||
:href="action.link"
|
||||
v-for="action in actions" :key="action.link" tag="a" size="medium" :theme="action.theme"
|
||||
:text="action.text" :href="action.link"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -68,6 +79,17 @@ const actions = computed(() => hero.value.actions ?? [])
|
||||
height: calc(100vh - var(--vp-nav-height) - var(--vp-footer-height, 0px));
|
||||
}
|
||||
|
||||
.home-hero-bg {
|
||||
position: absolute;
|
||||
z-index: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
filter: var(--vp-hero-bg-filter);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
@ -3,8 +3,9 @@ import { computed } from 'vue'
|
||||
import type { PlumeThemeHomeProfile } from '../../../shared/index.js'
|
||||
import VImage from '../VImage.vue'
|
||||
import { useThemeLocaleData } from '../../composables/index.js'
|
||||
import HomeBox from './HomeBox.vue'
|
||||
|
||||
const props = defineProps<PlumeThemeHomeProfile & { onlyOnce?: boolean }>()
|
||||
const props = defineProps<PlumeThemeHomeProfile>()
|
||||
|
||||
const theme = useThemeLocaleData()
|
||||
|
||||
@ -21,66 +22,53 @@ const profile = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="home-profile">
|
||||
<div class="container">
|
||||
<VImage v-if="profile.avatar" :image="profile.avatar" :class="{ circle: profile.circle }" />
|
||||
<h3 v-if="profile.name">
|
||||
{{ profile.name }}
|
||||
</h3>
|
||||
<p v-if="profile.description">
|
||||
{{ profile.description }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<HomeBox
|
||||
class="home-profile"
|
||||
:type="type"
|
||||
:background-image="backgroundImage"
|
||||
:background-attachment="backgroundAttachment"
|
||||
:full="full"
|
||||
>
|
||||
<VImage v-if="profile.avatar" :image="profile.avatar" :class="{ circle: profile.circle }" />
|
||||
|
||||
<h3 v-if="profile.name">
|
||||
{{ profile.name }}
|
||||
</h3>
|
||||
|
||||
<p v-if="profile.description">
|
||||
{{ profile.description }}
|
||||
</p>
|
||||
</HomeBox>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.home-profile {
|
||||
position: relative;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.home-profile {
|
||||
padding: 32px 48px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.home-profile {
|
||||
padding: 48px 64px;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1152px;
|
||||
margin: 0 auto;
|
||||
.home-profile :deep(.container) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.container :deep(img) {
|
||||
.home-profile :deep(img) {
|
||||
float: left;
|
||||
width: 64px;
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.container :deep(img.circle) {
|
||||
.home-profile :deep(img.circle) {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.container :deep(img) {
|
||||
.home-profile :deep(img) {
|
||||
width: 96px;
|
||||
}
|
||||
}
|
||||
|
||||
.container :deep(h3) {
|
||||
.home-profile :deep(h3) {
|
||||
margin-bottom: 12px;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.container :deep(p) {
|
||||
.home-profile :deep(p) {
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
|
||||
@ -1,14 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { isLinkHttp } from 'vuepress/shared'
|
||||
import { withBase } from 'vuepress/client'
|
||||
import type { PlumeThemeHomeTextImage } from '../../../shared/index.js'
|
||||
import VImage from '../VImage.vue'
|
||||
import { useDarkMode } from '../../composables/index.js'
|
||||
import HomeBox from './HomeBox.vue'
|
||||
|
||||
const props = defineProps<PlumeThemeHomeTextImage & { onlyOnce?: boolean }>()
|
||||
|
||||
const isDark = useDarkMode()
|
||||
const props = defineProps<PlumeThemeHomeTextImage>()
|
||||
|
||||
const maxWidth = computed(() => {
|
||||
const width = props.width
|
||||
@ -18,70 +14,45 @@ const maxWidth = computed(() => {
|
||||
|
||||
return width
|
||||
})
|
||||
|
||||
const styles = computed(() => {
|
||||
if (!props.backgroundImage)
|
||||
return null
|
||||
|
||||
const image = typeof props.backgroundImage === 'string' ? props.backgroundImage : (props.backgroundImage[isDark.value ? 'dark' : 'light'] ?? props.backgroundImage.light)
|
||||
|
||||
const link = isLinkHttp(image) ? props.backgroundImage : withBase(image)
|
||||
return {
|
||||
'background-image': `url(${link})`,
|
||||
'background-size': 'cover',
|
||||
'background-position': 'center',
|
||||
'background-repeat': 'no-repeat',
|
||||
'background-attachment': props.backgroundAttachment || '',
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="home-text-image" :style="styles">
|
||||
<div class="container" :class="{ reverse: type === 'text-image' }">
|
||||
<div class="content-image">
|
||||
<VImage :image="image" :style="{ maxWidth }" />
|
||||
</div>
|
||||
<div class="content-text plume-content">
|
||||
<section>
|
||||
<h2 v-if="title" class="title">
|
||||
{{ title }}
|
||||
</h2>
|
||||
<p v-if="description" class="description" v-html="description" />
|
||||
<ul v-if="list && list.length" class="list">
|
||||
<li v-for="(item, index) in list" :key="index">
|
||||
<template v-if="typeof item === 'object'">
|
||||
<h3 v-if="item.title" v-html="item.title" />
|
||||
<p v-if="item.description" v-html="item.description" />
|
||||
</template>
|
||||
<p v-else v-html="item" />
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
<HomeBox
|
||||
class="home-text-image"
|
||||
:type="type"
|
||||
:background-image="backgroundImage"
|
||||
:background-attachment="backgroundAttachment"
|
||||
:full="full"
|
||||
:container-class="{ reverse: type === 'text-image' }"
|
||||
>
|
||||
<div class="content-image">
|
||||
<VImage :image="image" :style="{ maxWidth }" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-text plume-content">
|
||||
<section>
|
||||
<h2 v-if="title" class="title">
|
||||
{{ title }}
|
||||
</h2>
|
||||
|
||||
<p v-if="description" class="description" v-html="description" />
|
||||
|
||||
<ul v-if="list && list.length" class="list">
|
||||
<li v-for="(item, index) in list" :key="index">
|
||||
<template v-if="typeof item === 'object'">
|
||||
<h3 v-if="item.title" v-html="item.title" />
|
||||
<p v-if="item.description" v-html="item.description" />
|
||||
</template>
|
||||
<p v-else v-html="item" />
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
</HomeBox>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.home-text-image {
|
||||
position: relative;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.home-text-image {
|
||||
padding: 32px 48px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.home-text-image {
|
||||
padding: 48px 64px;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
.home-text-image :deep(.container) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
@ -92,11 +63,11 @@ const styles = computed(() => {
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.container {
|
||||
.home-text-image :deep(.container) {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.container.reverse {
|
||||
.home-text-image :deep(.container.reverse) {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
}
|
||||
@ -152,7 +123,7 @@ const styles = computed(() => {
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.container {
|
||||
.home-text-image :deep(.container) {
|
||||
gap: 48px;
|
||||
}
|
||||
|
||||
@ -161,7 +132,7 @@ const styles = computed(() => {
|
||||
margin: 0 96px;
|
||||
}
|
||||
|
||||
.container .content-text {
|
||||
.content-text {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
max-width: 80%;
|
||||
|
||||
@ -8,6 +8,7 @@ import ExternalLinkIcon from './components/global/ExternalLinkIcon.vue'
|
||||
import { setupDarkMode, useScrollPromise } from './composables/index.js'
|
||||
import Layout from './layouts/Layout.vue'
|
||||
import NotFound from './layouts/NotFound.vue'
|
||||
import HomeBox from './components/Home/HomeBox.vue'
|
||||
|
||||
export default defineClientConfig({
|
||||
enhance({ app, router }) {
|
||||
@ -43,6 +44,8 @@ export default defineClientConfig({
|
||||
return null
|
||||
})
|
||||
|
||||
app.component('HomeBox', HomeBox)
|
||||
|
||||
// handle scrollBehavior with transition
|
||||
const scrollBehavior = router.options.scrollBehavior!
|
||||
router.options.scrollBehavior = async (...args) => {
|
||||
|
||||
@ -4,3 +4,9 @@ export { default as plumeClientConfig } from './config.js'
|
||||
|
||||
export { default as Layout } from './layouts/Layout.vue'
|
||||
export { default as NotFound } from './layouts/NotFound.vue'
|
||||
|
||||
export {
|
||||
useDarkMode,
|
||||
useThemeData,
|
||||
useThemeLocaleData,
|
||||
} from './composables/index.js'
|
||||
|
||||
@ -23,9 +23,13 @@ export interface PlumeThemeHeroAction {
|
||||
|
||||
export interface PlumeHomeConfigBase {
|
||||
type: 'banner' | 'hero' | 'text-image' | 'image-text' | 'features' | 'profile' | 'custom'
|
||||
full?: boolean
|
||||
backgroundImage?: string | { light: string, dark: string }
|
||||
backgroundAttachment?: 'fixed' | 'local'
|
||||
onlyOnce?: boolean
|
||||
}
|
||||
|
||||
export interface PlumeThemeHomeBanner extends PlumeHomeConfigBase {
|
||||
export interface PlumeThemeHomeBanner extends Pick<PlumeHomeConfigBase, 'type' | 'onlyOnce' | 'full'> {
|
||||
type: 'banner'
|
||||
banner?: string
|
||||
bannerMask?: number | { light?: number, dark?: number }
|
||||
@ -36,7 +40,8 @@ export interface PlumeThemeHomeHero extends PlumeHomeConfigBase {
|
||||
type: 'hero'
|
||||
hero: PlumeThemeHero
|
||||
full?: boolean
|
||||
background?: 'filter' | (string & { zz_IGNORE?: never })
|
||||
background?: 'filter-blur' | (string & { zz_IGNORE?: never })
|
||||
filter?: string
|
||||
}
|
||||
|
||||
export interface PlumeThemeHomeTextImage extends PlumeHomeConfigBase {
|
||||
@ -46,8 +51,6 @@ export interface PlumeThemeHomeTextImage extends PlumeHomeConfigBase {
|
||||
title?: string
|
||||
description?: string
|
||||
list: (string | { title?: string, description?: string })[]
|
||||
backgroundImage?: string | { light: string, dark: string }
|
||||
backgroundAttachment?: 'fixed' | 'local'
|
||||
}
|
||||
|
||||
export interface PlumeThemeHomeFeatures extends PlumeHomeConfigBase {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user