From 19a898b7c5dbb32ffd66916776ea8bf7a67c7661 Mon Sep 17 00:00:00 2001 From: Jonathan Summers-Muir Date: Mon, 3 Jun 2024 22:40:32 +0800 Subject: [PATCH] [Design System] chore: add scroll example of Navigation Menu (#26974) * init * Update navigation-menu.mdx * Update navigation-menu.tsx --- apps/design-system/__registry__/index.tsx | 11 ++ .../components/component-preview.tsx | 6 +- .../docs/components/navigation-menu.mdx | 31 +++ .../default/example/navigation-menu-demo.tsx | 121 ++++++------ .../example/navigation-menu-responsive.tsx | 182 ++++++++++++++++++ apps/design-system/registry/examples.ts | 6 + apps/www/components/Nav/index.tsx | 11 +- .../components/shadcn/ui/navigation-menu.tsx | 25 +-- 8 files changed, 317 insertions(+), 76 deletions(-) create mode 100644 apps/design-system/registry/default/example/navigation-menu-responsive.tsx diff --git a/apps/design-system/__registry__/index.tsx b/apps/design-system/__registry__/index.tsx index 8a807716cb6..d1fa65d3377 100644 --- a/apps/design-system/__registry__/index.tsx +++ b/apps/design-system/__registry__/index.tsx @@ -764,6 +764,17 @@ export const Index: Record = { subcategory: "undefined", chunks: [] }, + "navigation-menu-responsive": { + name: "navigation-menu-responsive", + type: "components:example", + registryDependencies: ["navigation-menu"], + component: React.lazy(() => import("@/registry/default/example/navigation-menu-responsive")), + source: "", + files: ["registry/default/example/navigation-menu-responsive.tsx"], + category: "undefined", + subcategory: "undefined", + chunks: [] + }, "popover-demo": { name: "popover-demo", type: "components:example", diff --git a/apps/design-system/components/component-preview.tsx b/apps/design-system/components/component-preview.tsx index 744f02e076a..c1304ec5986 100644 --- a/apps/design-system/components/component-preview.tsx +++ b/apps/design-system/components/component-preview.tsx @@ -127,7 +127,7 @@ export function ComponentPreview({
{showGrid && ( @@ -170,9 +170,7 @@ export function ComponentPreview({ return (
{showGrid && (
diff --git a/apps/design-system/content/docs/components/navigation-menu.mdx b/apps/design-system/content/docs/components/navigation-menu.mdx index 042dc0945d6..ec074e3a585 100644 --- a/apps/design-system/content/docs/components/navigation-menu.mdx +++ b/apps/design-system/content/docs/components/navigation-menu.mdx @@ -97,3 +97,34 @@ import { navigationMenuTriggerStyle } from '@/components/ui/navigation-menu' ``` See also the [Radix UI documentation](https://www.radix-ui.com/docs/primitives/components/navigation-menu#with-client-side-routing) for handling client side routing. + +### With horizontal scroll + +We can wrap a the `` in a `` component to make the menu scroll. + +However, then we must also make sure the `` is positioned correctly and rendered outside the scroll area. +We set `renderViewport={false}` on the `` component to prevent the viewport from being rendered. +And then add our own Viewport with ``. + +Then all our content panels will render themselves outside the scroll area and inside the viewport. + +You can also add props to `` to style it as you like, including the `containerProps` prop to add classes to the container div element inside the viewport. + +```tsx {1, 2, 11-13} + + + + + Item One + + Link + + + + + + + +``` + + diff --git a/apps/design-system/registry/default/example/navigation-menu-demo.tsx b/apps/design-system/registry/default/example/navigation-menu-demo.tsx index 24522235ace..df916d9d85c 100644 --- a/apps/design-system/registry/default/example/navigation-menu-demo.tsx +++ b/apps/design-system/registry/default/example/navigation-menu-demo.tsx @@ -3,8 +3,7 @@ import * as React from 'react' import Link from 'next/link' -import { cn } from 'ui' -// import { Icons } from '@/components/icons' +import { buttonVariants, cn } from 'ui' import { NavigationMenu, NavigationMenuContent, @@ -54,60 +53,66 @@ const components: { title: string; href: string; description: string }[] = [ export default function NavigationMenuDemo() { return ( - - - - Getting started - - - - - - Components - - + + + + + Components + + +
    + {components.map((component) => ( + + {component.description} + + ))} +
+
+
+ + + + Documentation + + + +
+
+
) } @@ -119,13 +124,13 @@ const ListItem = React.forwardRef, React.ComponentPropsWit -
{title}
-

{children}

+
{title}
+

{children}

diff --git a/apps/design-system/registry/default/example/navigation-menu-responsive.tsx b/apps/design-system/registry/default/example/navigation-menu-responsive.tsx new file mode 100644 index 00000000000..4764bf931b1 --- /dev/null +++ b/apps/design-system/registry/default/example/navigation-menu-responsive.tsx @@ -0,0 +1,182 @@ +'use client' + +import * as React from 'react' +import Link from 'next/link' + +import { NavigationMenuViewport, ScrollArea, ScrollBar, buttonVariants, cn } from 'ui' +// import { Icons } from '@/components/icons' +import { + NavigationMenu, + NavigationMenuContent, + NavigationMenuItem, + NavigationMenuLink, + NavigationMenuList, + NavigationMenuTrigger, + navigationMenuTriggerStyle, +} from 'ui' + +const components: { title: string; href: string; description: string }[] = [ + { + title: 'Alert Dialog', + href: '/docs/primitives/alert-dialog', + description: + 'A modal dialog that interrupts the user with important content and expects a response.', + }, + { + title: 'Hover Card', + href: '/docs/primitives/hover-card', + description: 'For sighted users to preview content available behind a link.', + }, + { + title: 'Progress', + href: '/docs/primitives/progress', + description: + 'Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.', + }, + { + title: 'Scroll-area', + href: '/docs/primitives/scroll-area', + description: 'Visually or semantically separates content.', + }, + { + title: 'Tabs', + href: '/docs/primitives/tabs', + description: + 'A set of layered sections of content—known as tab panels—that are displayed one at a time.', + }, + { + title: 'Tooltip', + href: '/docs/primitives/tooltip', + description: + 'A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.', + }, +] + +export default function NavigationMenuDemo() { + return ( + + + + + + + + + + + Components + + +
    + {components.map((component) => ( + + {component.description} + + ))} +
+
+
+ + + Components + + +
    + {components.map((component) => ( + + {component.description} + + ))} +
+
+
+ + + Components + + +
    + {components.map((component) => ( + + {component.description} + + ))} +
+
+
+ + + Components + + +
    + {components.map((component) => ( + + {component.description} + + ))} +
+
+
+ + + + Documentation + + + +
+ +
+ +
+ ) +} + +const ListItem = React.forwardRef, React.ComponentPropsWithoutRef<'a'>>( + ({ className, title, children, ...props }, ref) => { + return ( +
  • + + +
    {title}
    +

    {children}

    +
    +
    +
  • + ) + } +) +ListItem.displayName = 'ListItem' diff --git a/apps/design-system/registry/examples.ts b/apps/design-system/registry/examples.ts index dd0a1543894..8676892a518 100644 --- a/apps/design-system/registry/examples.ts +++ b/apps/design-system/registry/examples.ts @@ -491,6 +491,12 @@ export const examples: Registry = [ registryDependencies: ['navigation-menu'], files: ['example/navigation-menu-demo.tsx'], }, + { + name: 'navigation-menu-responsive', + type: 'components:example', + registryDependencies: ['navigation-menu'], + files: ['example/navigation-menu-responsive.tsx'], + }, // { // name: 'pagination-demo', // type: 'components:example', diff --git a/apps/www/components/Nav/index.tsx b/apps/www/components/Nav/index.tsx index 669d6c1b137..b0b2c78be0b 100644 --- a/apps/www/components/Nav/index.tsx +++ b/apps/www/components/Nav/index.tsx @@ -5,7 +5,7 @@ import { useRouter } from 'next/router' import { useTheme } from 'next-themes' import { useWindowSize } from 'react-use' -import { Button, cn } from 'ui' +import { Button, buttonVariants, cn } from 'ui' import { NavigationMenu, NavigationMenuContent, @@ -136,11 +136,16 @@ const Nav = (props: Props) => { {menu.primaryNav.map((menuItem) => menuItem.hasDropdown ? ( - + {menuItem.title} {menuItem.dropdown} diff --git a/packages/ui/src/components/shadcn/ui/navigation-menu.tsx b/packages/ui/src/components/shadcn/ui/navigation-menu.tsx index 8e3331c1aa0..95cc153e35d 100644 --- a/packages/ui/src/components/shadcn/ui/navigation-menu.tsx +++ b/packages/ui/src/components/shadcn/ui/navigation-menu.tsx @@ -4,23 +4,25 @@ import { ChevronDown } from 'lucide-react' import * as React from 'react' import { cn } from '../../../lib/utils/cn' +import { buttonVariants } from './../../Button/Button' interface NavigationMenuProps extends React.ComponentPropsWithoutRef { viewportClassName?: string | undefined + renderViewport?: boolean | undefined } const NavigationMenu = React.forwardRef< React.ElementRef, NavigationMenuProps ->(({ className, viewportClassName, children, ...props }, ref) => ( +>(({ className, viewportClassName, renderViewport = true, children, ...props }, ref) => ( {children} - + {renderViewport && } )) NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName @@ -47,11 +49,7 @@ const NavigationMenuTrigger = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, children, ...props }, ref) => ( - + {children}{' '} , - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( -
    + React.ComponentPropsWithoutRef & { + containerProps?: React.HTMLAttributes + } +>(({ className, containerProps, ...props }, ref) => ( +