From f853aa45849437d1f6f1225b07086a8f2c0b7706 Mon Sep 17 00:00:00 2001 From: "Mr.Hope" Date: Wed, 4 Jan 2023 12:47:26 +0800 Subject: [PATCH] feat(theme): improve home features --- .../src/client/components/HomeFeatures.ts | 45 ++++++++++++------- .../theme/src/client/components/HomePage.ts | 34 +++++++++++--- packages/theme/src/shared/frontmatter/home.ts | 26 +++++++++-- 3 files changed, 78 insertions(+), 27 deletions(-) diff --git a/packages/theme/src/client/components/HomeFeatures.ts b/packages/theme/src/client/components/HomeFeatures.ts index d08a49f8f3dc..85ab27ec9b22 100644 --- a/packages/theme/src/client/components/HomeFeatures.ts +++ b/packages/theme/src/client/components/HomeFeatures.ts @@ -1,32 +1,42 @@ -import { usePageFrontmatter } from "@vuepress/client"; -import { isArray, isLinkExternal } from "@vuepress/shared"; -import { computed, defineComponent, h } from "vue"; +import { isLinkExternal } from "@vuepress/shared"; +import { defineComponent, h } from "vue"; import { RouterLink } from "vue-router"; import Icon from "@theme-hope/components/Icon"; -import type { VNode } from "vue"; -import type { ThemeProjectHomePageFrontmatter } from "../../shared/index.js"; +import type { PropType, VNode } from "vue"; +import type { ThemeProjectHomeFeatureItemOptions } from "../../shared/index.js"; export default defineComponent({ name: "HomeFeatures", - setup() { - const frontmatter = usePageFrontmatter(); + props: { + /** + * Feature config + */ + items: { + type: Object as PropType, + default: (): ThemeProjectHomeFeatureItemOptions[] => + [] as ThemeProjectHomeFeatureItemOptions[], + }, - const features = computed(() => { - if (isArray(frontmatter.value.features)) - return frontmatter.value.features; - - return []; - }); + /** + * Feature header + */ + header: { + type: String, + default: "", + }, + }, - return (): VNode | null => - features.value.length + setup(props) { + return (): (VNode | null)[] => [ + props.header ? h("h3", props.header) : null, + props.items.length ? h( "div", { class: "features" }, - frontmatter.value.features?.map((feature) => { + props.items?.map((feature) => { const children = [ h("h2", [ h(Icon, { icon: feature.icon }), @@ -61,6 +71,7 @@ export default defineComponent({ : h("div", { class: "feature" }, children); }) ) - : null; + : null, + ]; }, }); diff --git a/packages/theme/src/client/components/HomePage.ts b/packages/theme/src/client/components/HomePage.ts index 129a64373bc7..f22034244a83 100644 --- a/packages/theme/src/client/components/HomePage.ts +++ b/packages/theme/src/client/components/HomePage.ts @@ -1,5 +1,6 @@ -import { defineComponent, h } from "vue"; +import { computed, defineComponent, h } from "vue"; import { usePageFrontmatter } from "@vuepress/client"; +import { isArray } from "@vuepress/shared"; import DropTransition from "@theme-hope/components/transitions/DropTransition"; import HomeFeatures from "@theme-hope/components/HomeFeatures"; @@ -8,7 +9,11 @@ import HomeHero from "@theme-hope/components/HomeHero"; import { usePure } from "@theme-hope/composables/index"; import type { VNode } from "vue"; -import type { ThemeProjectHomePageFrontmatter } from "../../shared/index.js"; +import type { + ThemeProjectHomeFeatureOptions, + ThemeProjectHomeFeatureItemOptions, + ThemeProjectHomePageFrontmatter, +} from "../../shared/index.js"; import "../styles/home-page.scss"; @@ -19,6 +24,17 @@ export default defineComponent({ const pure = usePure(); const frontmatter = usePageFrontmatter(); + const features = computed(() => { + const { features } = frontmatter.value; + + if (isArray(features)) + return features.some((item) => !("items" in item)) + ? [{ items: features as ThemeProjectHomeFeatureItemOptions[] }] + : (features as ThemeProjectHomeFeatureOptions[]); + + return []; + }); + return (): VNode => h( "main", @@ -31,12 +47,18 @@ export default defineComponent({ [ slots["top"]?.(), h(HomeHero), - h(DropTransition, { appear: true, delay: 0.16 }, () => - h(HomeFeatures) + features.value.map(({ header = "", items }, index) => + h( + DropTransition, + { appear: true, delay: 0.16 + index * 0.08 }, + () => h(HomeFeatures, { header, items }) + ) ), slots["center"]?.(), - h(DropTransition, { appear: true, delay: 0.24 }, () => - h(MarkdownContent, { custom: true }) + h( + DropTransition, + { appear: true, delay: 0.16 + features.value.length * 0.08 }, + () => h(MarkdownContent, { custom: true }) ), slots["bottom"]?.(), ] diff --git a/packages/theme/src/shared/frontmatter/home.ts b/packages/theme/src/shared/frontmatter/home.ts index 7d13c7474e0c..06d1427501d1 100644 --- a/packages/theme/src/shared/frontmatter/home.ts +++ b/packages/theme/src/shared/frontmatter/home.ts @@ -1,6 +1,6 @@ import type { ThemePageFrontmatter } from "./base.js"; -export interface ThemeHomeActionOptions { +export interface ThemeProjectHomeActionOptions { /** * Action name * @@ -25,7 +25,7 @@ export interface ThemeHomeActionOptions { type?: "primary" | "default"; } -export interface ThemeHomeFeatureOptions { +export interface ThemeProjectHomeFeatureItemOptions { /** * Feature name * @@ -59,6 +59,22 @@ export interface ThemeHomeFeatureOptions { link?: string; } +export interface ThemeProjectHomeFeatureOptions { + /** + * Feature header + * + * 功能标题 + */ + header?: string; + + /** + * Feature config + * + * 功能配置 + */ + items: ThemeProjectHomeFeatureItemOptions[]; +} + export interface ThemeProjectHomePageFrontmatter extends ThemePageFrontmatter { home: true; heroImage?: string; @@ -67,6 +83,8 @@ export interface ThemeProjectHomePageFrontmatter extends ThemePageFrontmatter { heroText?: string | false; tagline?: string | false; - actions?: ThemeHomeActionOptions[]; - features?: ThemeHomeFeatureOptions[]; + actions?: ThemeProjectHomeActionOptions[]; + features?: + | ThemeProjectHomeFeatureItemOptions[] + | ThemeProjectHomeFeatureOptions[]; }