mirror of
https://github.com/pengzhanbo/vuepress-theme-plume.git
synced 2026-04-23 10:58:13 +08:00
feat(theme): add Home Features
This commit is contained in:
parent
09bbd7eb99
commit
bc8f5aded3
115
theme/src/client/components/Home/HomeFeature.vue
Normal file
115
theme/src/client/components/Home/HomeFeature.vue
Normal file
@ -0,0 +1,115 @@
|
||||
<script setup lang="ts">
|
||||
import type { PlumeThemeHomeFeature } from '../../../shared/index.js'
|
||||
import AutoLink from '../AutoLink.vue'
|
||||
import VImage from '../VImage.vue'
|
||||
|
||||
defineProps<PlumeThemeHomeFeature>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AutoLink
|
||||
class="home-feature"
|
||||
:href="link"
|
||||
:rel="rel"
|
||||
:target="target"
|
||||
:no-icon="true"
|
||||
:tag="link ? 'a' : 'div'"
|
||||
>
|
||||
<article class="box">
|
||||
<div v-if="typeof icon === 'object' && icon.wrap" class="icon">
|
||||
<VImage
|
||||
:image="icon"
|
||||
:alt="icon.alt"
|
||||
:height="icon.height || 48"
|
||||
:width="icon.width || 48"
|
||||
/>
|
||||
</div>
|
||||
<VImage
|
||||
v-else-if="typeof icon === 'object'"
|
||||
:image="icon"
|
||||
:alt="icon.alt"
|
||||
:height="icon.height || 48"
|
||||
:width="icon.width || 48"
|
||||
/>
|
||||
<div v-else-if="icon" class="icon" v-html="icon" />
|
||||
<h2 class="title" v-html="title" />
|
||||
<p v-if="details" class="details" v-html="details" />
|
||||
|
||||
<div v-if="linkText" class="link-text">
|
||||
<p class="link-text-value">
|
||||
{{ linkText }} <span class="vpi-arrow-right link-text-icon" />
|
||||
</p>
|
||||
</div>
|
||||
</article>
|
||||
</AutoLink>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.home-feature {
|
||||
display: block;
|
||||
height: 100%;
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-bg-soft);
|
||||
border-radius: 12px;
|
||||
transition: border-color var(--t-color), background-color var(--t-color);
|
||||
}
|
||||
|
||||
.home-feature.link:hover {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.box > :deep(.VPImage) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin-bottom: 20px;
|
||||
font-size: 24px;
|
||||
background-color: var(--vp-c-default-soft);
|
||||
border-radius: 6px;
|
||||
transition: background-color var(--t-color);
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.details {
|
||||
flex-grow: 1;
|
||||
padding-top: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.link-text {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.link-text-value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.link-text-icon {
|
||||
margin-left: 6px;
|
||||
}
|
||||
</style>
|
||||
152
theme/src/client/components/Home/HomeFeatures.vue
Normal file
152
theme/src/client/components/Home/HomeFeatures.vue
Normal file
@ -0,0 +1,152 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import type { PlumeThemeHomeFeatures } from '../../../shared/index.js'
|
||||
import HomeFeature from './HomeFeature.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
onlyOnce?: boolean
|
||||
} & PlumeThemeHomeFeatures>()
|
||||
|
||||
const grid = computed(() => {
|
||||
const length = props.features?.length
|
||||
|
||||
if (!length)
|
||||
return undefined
|
||||
|
||||
else if (length === 2)
|
||||
return 'grid-2'
|
||||
|
||||
else if (length === 3)
|
||||
return 'grid-3'
|
||||
|
||||
else if (length % 3 === 0)
|
||||
return 'grid-6'
|
||||
|
||||
else if (length > 3)
|
||||
return 'grid-4'
|
||||
|
||||
return undefined
|
||||
})
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</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 {
|
||||
margin-bottom: 20px;
|
||||
font-size: 20px;
|
||||
font-weight: 900;
|
||||
color: var(--vp-c-text-1);
|
||||
text-align: center;
|
||||
transition: color var(--t-color);
|
||||
}
|
||||
|
||||
.container .description {
|
||||
margin-bottom: 20px;
|
||||
font-size: 16px;
|
||||
line-height: 1.7;
|
||||
color: var(--vp-c-text-1);
|
||||
text-align: center;
|
||||
transition: color var(--t-color);
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.container .title {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.container .description {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.container .title {
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
.items {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: -8px;
|
||||
}
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.item.grid-2,
|
||||
.item.grid-4,
|
||||
.item.grid-6 {
|
||||
width: calc(100% / 2);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.item.grid-2,
|
||||
.item.grid-4 {
|
||||
width: calc(100% / 2);
|
||||
}
|
||||
|
||||
.item.grid-3,
|
||||
.item.grid-6 {
|
||||
width: calc(100% / 3);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.item.grid-4 {
|
||||
width: calc(100% / 4);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Loading…
x
Reference in New Issue
Block a user