feat(ui): implement dynamic dropdown navigation and refactor project cards

Replaced the static navigation with a dynamic, internationalized dropdown menu powered by a new `useNavLinks` composable. The
navigation items are now sourced from i18n files. The featured project cards on the homepage have been refactored to use the
`<UPageCard>` component, and the content schema is updated with `spotlight` and `highlight` options for enhanced display.
This commit is contained in:
xiaomai
2025-11-06 00:17:34 +08:00
parent 78bc2c34a0
commit 31a4103f9b
10 changed files with 276 additions and 108 deletions

View File

@@ -0,0 +1,85 @@
// composables/useNavLinks.ts
import type { NavigationMenuItem } from "@nuxt/ui";
export const useNavLinks = () => {
const { t } = useI18n();
const navLinks = computed<NavigationMenuItem[]>(() => [
{
label: t("common.header.services.label"),
icon: "mdi:briefcase-outline",
children: [
{
label: t("common.header.services.children.webDev.label"),
description: t("common.header.services.children.webDev.description"),
icon: "mdi:web",
},
{
label: t("common.header.services.children.softwareDev.label"),
description: t(
"common.header.services.children.softwareDev.description"
),
icon: "mdi:tools",
},
{
label: t("common.header.services.children.eventVisual.label"),
description: t(
"common.header.services.children.eventVisual.description"
),
icon: "mdi:monitor-dashboard",
},
{
label: t("common.header.services.children.lab.label"),
description: t("common.header.services.children.lab.description"),
icon: "mdi:test-tube-off",
},
],
},
{
label: t("common.header.projects.label"),
icon: "mdi:lightbulb-group-outline",
children: [
{
label: t("common.header.projects.children.commercialWebsite.label"),
description: t(
"common.header.projects.children.commercialWebsite.description"
),
icon: "mdi:web",
},
{
label: t("common.header.projects.children.gameDev.label"),
description: t("common.header.projects.children.gameDev.description"),
icon: "mdi:gamepad-variant-outline",
},
{
label: t("common.header.projects.children.tools.label"),
description: t("common.header.projects.children.tools.description"),
icon: "mdi:tools",
},
{
label: t("common.header.projects.children.special.label"),
description: t("common.header.projects.children.special.description"),
icon: "mdi:star",
},
],
},
{
label: t("common.header.insights.label"),
icon: "mdi:brain",
children: [
{
label: t("common.header.insights.children.xiaomaiBlog.label"),
description: t(
"common.header.insights.children.xiaomaiBlog.description"
),
icon: "mdi:pencil-outline",
to: "https://xiaomai.tootaio.com/",
type: "link",
target: "_blank",
},
],
},
]);
return navLinks;
};

View File

@@ -1,9 +1,19 @@
<template>
<UPage>
<UHeader>
<UHeader
:ui="{
left: 'flex items-center gap-1.5',
center: 'hidden lg:flex lg:flex-16',
right: 'flex items-center justify-end gap-1.5',
}"
>
<template #title> Tootaio Studio </template>
<template #default>
<UNavigationMenu :items="navLinks" variant="link" />
<UNavigationMenu
:items="navLinks"
variant="link"
class="w-full justify-center"
/>
</template>
<template #body>
<UNavigationMenu :items="navLinks" orientation="vertical" />
@@ -42,6 +52,7 @@
<script lang="ts" setup>
const { setLocale } = useI18n();
const navLinks = useNavLinks();
</script>
<style></style>

View File

@@ -23,26 +23,24 @@
:items="page?.featuredProjects.projects"
:ui="{ item: 'basis-full sm:basis-1/2 lg:basis-1/3' }"
>
<UCard class="my-2">
<template #header>
<h3 class="text-2xl font-bold">{{ item.title }}</h3>
</template>
<template #default>
<img :src="item.image" :alt="item.title" />
<p class="mt-2 line-clamp-3">{{ item.description }}</p>
</template>
<template #footer>
<UButton
v-if="item.demoLink"
:href="item.demoLink"
target="_blank"
rel="noopener"
size="sm"
>
{{ $t("index.featuredProjects.viewDemo") }}
</UButton>
</template>
</UCard>
<UPageCard
class="my-2"
:title="item.title"
:description="item.description"
:highlight="item.highlight"
:spotlight="item.spotlight"
>
<img :src="item.image" :alt="item.title" />
<UButton
v-if="item.demoLink"
:href="item.demoLink"
target="_blank"
rel="noopener"
size="sm"
>
{{ $t("index.featuredProjects.viewDemo") }}
</UButton>
</UPageCard>
</UCarousel>
</UPageSection>

View File

@@ -1,12 +0,0 @@
import type {NavigationMenuItem} from "@nuxt/ui";
export const navLinks: NavigationMenuItem[] = [{
label: "Services",
icon: "mdi:briefcase-outline"
}, {
label: "Projects",
icon: "mdi:lightbulb-group-outline"
}, {
label: "Insights",
icon: "mdi:brain"
}]