refactor: reorganize marketing menu and update mobile navbar

- Move AI menu section to the top of the marketing menu configuration
- Remove duplicate AI menu section in marketing links
- Add TODO comment for mobile menu scrollbar layout issue
- Remove scrollbar from mobile menu using RemoveScroll component
- Improve mobile menu accessibility and scrolling behavior
This commit is contained in:
javayhu 2025-03-08 23:21:58 +08:00
parent b9a5c4927e
commit 12b33b29ce
2 changed files with 44 additions and 35 deletions

View File

@ -28,6 +28,13 @@ import * as React from 'react';
import { RemoveScroll } from 'react-remove-scroll';
import { UserButton } from './user-button';
/**
* TODO:
*
* 1. bug: when the mobile menu is open, and its height is greater than the viewport height,
* the layout will shift because the mobile menu is scrollable and scrollbar appears.
* if we set scrollbar-gutter: stable; for html in globals.css.
*/
export function NavbarMobile({
className,
...other
@ -103,7 +110,9 @@ export function NavbarMobile({
{/* mobile menu */}
{open && (
<Portal asChild>
<RemoveScroll allowPinchZoom removeScrollBar enabled>
{/* if we don't add RemoveScroll component, the underlying
page will scroll when we scroll the mobile menu */}
<RemoveScroll allowPinchZoom enabled>
<MainMobileMenu onLinkClicked={handleToggleMobileMenu} />
</RemoveScroll>
</Portal>
@ -125,7 +134,7 @@ function MainMobileMenu({ onLinkClicked }: MainMobileMenuProps) {
const localePathname = useLocalePathname();
return (
<div className="fixed w-full inset-0 z-50 mt-[72px] overflow-y-auto
<div className="fixed w-full inset-0 z-50 mt-[72px] overflow-y-auto
bg-background backdrop-blur-md animate-in fade-in-0">
<div className="flex size-full flex-col items-start space-y-4 p-4">
{/* action buttons */}

View File

@ -67,6 +67,39 @@ export function getMenuLinks(t: TranslationFunction): NestedMenuItem[] {
href: Routes.Blog,
external: false
},
{
title: t('Marketing.menu.ai.title'),
items: [
{
title: t('Marketing.menu.ai.items.text.title'),
description: t('Marketing.menu.ai.items.text.description'),
icon: <SquarePenIcon className="size-5 shrink-0" />,
href: Routes.AIText,
external: false
},
{
title: t('Marketing.menu.ai.items.image.title'),
description: t('Marketing.menu.ai.items.image.description'),
icon: <ImageIcon className="size-5 shrink-0" />,
href: Routes.AIImage,
external: false
},
{
title: t('Marketing.menu.ai.items.video.title'),
description: t('Marketing.menu.ai.items.video.description'),
icon: <FilmIcon className="size-5 shrink-0" />,
href: Routes.AIVideo,
external: false
},
{
title: t('Marketing.menu.ai.items.audio.title'),
description: t('Marketing.menu.ai.items.audio.description'),
icon: <AudioLinesIcon className="size-5 shrink-0" />,
href: Routes.AIAudio,
external: false
}
]
},
{
title: t('Marketing.menu.pages.title'),
items: [
@ -128,39 +161,6 @@ export function getMenuLinks(t: TranslationFunction): NestedMenuItem[] {
}
]
},
{
title: t('Marketing.menu.ai.title'),
items: [
{
title: t('Marketing.menu.ai.items.text.title'),
description: t('Marketing.menu.ai.items.text.description'),
icon: <SquarePenIcon className="size-5 shrink-0" />,
href: Routes.AIText,
external: false
},
{
title: t('Marketing.menu.ai.items.image.title'),
description: t('Marketing.menu.ai.items.image.description'),
icon: <ImageIcon className="size-5 shrink-0" />,
href: Routes.AIImage,
external: false
},
{
title: t('Marketing.menu.ai.items.video.title'),
description: t('Marketing.menu.ai.items.video.description'),
icon: <FilmIcon className="size-5 shrink-0" />,
href: Routes.AIVideo,
external: false
},
{
title: t('Marketing.menu.ai.items.audio.title'),
description: t('Marketing.menu.ai.items.audio.description'),
icon: <AudioLinesIcon className="size-5 shrink-0" />,
href: Routes.AIAudio,
external: false
}
]
},
];
}