feat: support nested footer links

This commit is contained in:
2025-09-29 21:19:48 +08:00
parent 36775a4a8d
commit 7f61b58880
6 changed files with 88 additions and 24 deletions

View File

@@ -1,6 +1,7 @@
{
"name": "",
"name": "backend",
"version": "1.0.0",
"private": true,
"description": "Website template for Payload",
"license": "MIT",
"type": "module",
@@ -83,12 +84,5 @@
"engines": {
"node": "^18.20.2 || >=20.9.0",
"pnpm": "^9 || ^10"
},
"pnpm": {
"onlyBuiltDependencies": [
"sharp",
"esbuild",
"unrs-resolver"
]
}
}

View File

@@ -22,9 +22,24 @@ export async function Footer() {
<div className="flex flex-col-reverse items-start md:flex-row gap-4 md:items-center">
<ThemeSelector />
<nav className="flex flex-col md:flex-row gap-4">
{navItems.map(({ link }, i) => {
return <CMSLink className="text-white" key={i} {...link} />
<nav className="flex flex-col md:flex-row gap-6">
{navItems.map(({ link, childNavItems }, i) => {
const hasChildren = Array.isArray(childNavItems) && childNavItems.length > 0
return (
<div className="flex flex-col gap-2" key={i}>
<CMSLink className="text-white font-medium" {...link} />
{hasChildren ? (
<ul className="ml-2 flex flex-col gap-2 text-sm text-white/80">
{childNavItems?.map(({ link: childLink }, childIndex) => (
<li key={childIndex}>
<CMSLink className="hover:text-white transition" {...childLink} />
</li>
))}
</ul>
) : null}
</div>
)
})}
</nav>
</div>

View File

@@ -1,9 +1,9 @@
'use client'
import { Header } from '@/payload-types'
import { Footer as FooterGlobal } from '@/payload-types'
import { RowLabelProps, useRowLabel } from '@payloadcms/ui'
export const RowLabel: React.FC<RowLabelProps> = () => {
const data = useRowLabel<NonNullable<Header['navItems']>[number]>()
const data = useRowLabel<NonNullable<FooterGlobal['navItems']>[number]>()
const label = data?.data?.link?.label
? `Nav item ${data.rowNumber !== undefined ? data.rowNumber + 1 : ''}: ${data?.data?.link?.label}`

View File

@@ -16,6 +16,20 @@ export const Footer: GlobalConfig = {
link({
appearances: false,
}),
{
name: 'childNavItems',
label: 'Nested links',
type: 'array',
fields: [
link({
appearances: false,
}),
],
maxRows: 8,
admin: {
initCollapsed: true,
},
},
],
maxRows: 6,
admin: {

View File

@@ -154,7 +154,7 @@ export interface Page {
root: {
type: string;
children: {
type: any;
type: string;
version: number;
[k: string]: unknown;
}[];
@@ -219,7 +219,7 @@ export interface Post {
root: {
type: string;
children: {
type: any;
type: string;
version: number;
[k: string]: unknown;
}[];
@@ -265,7 +265,7 @@ export interface Media {
root: {
type: string;
children: {
type: any;
type: string;
version: number;
[k: string]: unknown;
}[];
@@ -401,7 +401,7 @@ export interface CallToActionBlock {
root: {
type: string;
children: {
type: any;
type: string;
version: number;
[k: string]: unknown;
}[];
@@ -452,7 +452,7 @@ export interface ContentBlock {
root: {
type: string;
children: {
type: any;
type: string;
version: number;
[k: string]: unknown;
}[];
@@ -509,7 +509,7 @@ export interface ArchiveBlock {
root: {
type: string;
children: {
type: any;
type: string;
version: number;
[k: string]: unknown;
}[];
@@ -545,7 +545,7 @@ export interface FormBlock {
root: {
type: string;
children: {
type: any;
type: string;
version: number;
[k: string]: unknown;
}[];
@@ -602,7 +602,7 @@ export interface Form {
root: {
type: string;
children: {
type: any;
type: string;
version: number;
[k: string]: unknown;
}[];
@@ -685,7 +685,7 @@ export interface Form {
root: {
type: string;
children: {
type: any;
type: string;
version: number;
[k: string]: unknown;
}[];
@@ -717,7 +717,7 @@ export interface Form {
root: {
type: string;
children: {
type: any;
type: string;
version: number;
[k: string]: unknown;
}[];
@@ -1598,6 +1598,26 @@ export interface Footer {
url?: string | null;
label: string;
};
childNavItems?:
| {
link: {
type?: ('reference' | 'custom') | null;
newTab?: boolean | null;
reference?:
| ({
relationTo: 'pages';
value: string | Page;
} | null)
| ({
relationTo: 'posts';
value: string | Post;
} | null);
url?: string | null;
label: string;
};
id?: string | null;
}[]
| null;
id?: string | null;
}[]
| null;
@@ -1644,6 +1664,20 @@ export interface FooterSelect<T extends boolean = true> {
url?: T;
label?: T;
};
childNavItems?:
| T
| {
link?:
| T
| {
type?: T;
newTab?: T;
reference?: T;
url?: T;
label?: T;
};
id?: T;
};
id?: T;
};
updatedAt?: T;
@@ -1682,7 +1716,7 @@ export interface BannerBlock {
root: {
type: string;
children: {
type: any;
type: string;
version: number;
[k: string]: unknown;
}[];