diff --git a/app/docs/components/navigation-menu/page.tsx b/app/docs/components/navigation-menu/page.tsx new file mode 100644 index 00000000..74dbbfe8 --- /dev/null +++ b/app/docs/components/navigation-menu/page.tsx @@ -0,0 +1,87 @@ +import { Metadata } from "next" + +import { navigationMenuMetaData } from "@/lib/metadata" +import { Separator } from "@/components/ui/separator" +import NavigationMenuDemo from "@/components/examples/navigation-menu" + +import CodeSnippet from "../code-snippet" +import CopyCommandButton from "../copy-command-button" +import InstallationCommands from "../installation-commands" +import { OpenInV0Button } from "../open-in-v0-button" + +export const metadata: Metadata = { + title: "8-bit Navigation Menu", + description: "Displays an 8-bit navigation menu component.", + openGraph: { + images: navigationMenuMetaData, + }, +} + +export default function NavigationMenuPage() { + return ( +
+
+

Navigation Menu

+ +
+ +

+ Displays an 8-bit navigation menu component. +

+ +
+
+

+ 8-bit navigation menu component +

+ +
+ +
+
+
+ +
+
+ +

Installation

+ + + + + +

Usage

+ + + + {`import { + NavigationMenu, + NavigationMenuContent, + NavigationMenuIndicator, + NavigationMenuItem, + NavigationMenuLink, + NavigationMenuList, + NavigationMenuTrigger, + NavigationMenuViewport, +} from "@/components/ui/8bit/navigation-menu" +`} + + {` + + + Item One + + Link + + + + +`} +
+ ) +} diff --git a/components/examples/navigation-menu.tsx b/components/examples/navigation-menu.tsx new file mode 100644 index 00000000..3a31d450 --- /dev/null +++ b/components/examples/navigation-menu.tsx @@ -0,0 +1,139 @@ +"use client" + +import * as React from "react" +import Link from "next/link" + +import { + NavigationMenu, + NavigationMenuContent, + NavigationMenuIndicator, + NavigationMenuItem, + NavigationMenuLink, + NavigationMenuList, + NavigationMenuTrigger, + navigationMenuTriggerStyle, +} from "@/components/ui/8bit/navigation-menu" + +const components: { title: string; href: string; description: string }[] = [ + { + title: "Alert Dialog", + href: "/docs/components/alert-dialog", + description: + "A modal dialog that interrupts the user with important content and expects a response.", + }, + { + title: "Hover Card", + href: "/docs/components/hover-card", + description: + "For sighted users to preview content available behind a link.", + }, + { + title: "Progress", + href: "/docs/components/progress", + description: + "Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.", + }, + { + title: "Scroll-area", + href: "/docs/components/scroll-area", + description: + "Augments native scroll functionality for custom, cross-browser styling.", + }, + { + title: "Tabs", + href: "/docs/components/tabs", + description: + "A set of layered sections of content—known as tab panels—that are displayed one at a time.", + }, + { + title: "Tooltip", + href: "/docs/components/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 ( + + + + Getting started + +
    +
  • + + +
    + 8bitcn/ui +
    +

    + Beautifully designed components built with Tailwind CSS. +

    + +
    +
  • + + How to install dependencies and structure your app. + + + Re-usable components built using Radix UI and Tailwind CSS. + + + Building Retro Blocks for the Web + +
+
+
+ + + Components + +
    + {components.map((component) => ( + + {component.description} + + ))} +
+
+
+ + + + Documentation + + + + +
+
+ ) +} + +function ListItem({ + title, + children, + href, + ...props +}: React.ComponentPropsWithoutRef<"li"> & { href: string }) { + return ( +
  • + + +
    {title}
    +

    + {children} +

    + +
    +
  • + ) +} diff --git a/components/ui/8bit/navigation-menu.tsx b/components/ui/8bit/navigation-menu.tsx new file mode 100644 index 00000000..d44b54d9 --- /dev/null +++ b/components/ui/8bit/navigation-menu.tsx @@ -0,0 +1,193 @@ +import * as React from "react" +import { Press_Start_2P } from "next/font/google" +import { Indicator, Root, Viewport } from "@radix-ui/react-navigation-menu" +import { cva, VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" +import { + NavigationMenuContent as ShadcnNavigationMenuContent, + NavigationMenuIndicator as ShadcnNavigationMenuIndicator, + NavigationMenuItem as ShadcnNavigationMenuItem, + NavigationMenuLink as ShadcnNavigationMenuLink, + NavigationMenuList as ShadcnNavigationMenuList, + NavigationMenuTrigger as ShadcnNavigationMenuTrigger, +} from "@/components/ui/navigation-menu" + +export { navigationMenuTriggerStyle } from "@/components/ui/navigation-menu" + +const pressStart = Press_Start_2P({ + weight: ["400"], + subsets: ["latin"], +}) + +export const navigationMenuVariants = cva("", { + variants: { + font: { + normal: "", + retro: pressStart.className, + }, + }, + defaultVariants: { + font: "retro", + }, +}) + +type FontVariantProps = VariantProps + +const getFontClassName = (font: FontVariantProps["font"]) => + navigationMenuVariants({ font }) + +function NavigationMenu({ + className, + font, + children, + viewport = true, + ...props +}: React.ComponentProps & { + viewport?: boolean +} & FontVariantProps) { + return ( + + {children} + {viewport && } + + ) +} + +function NavigationMenuList({ + className, + font, + ...props +}: React.ComponentProps & + VariantProps) { + return ( + + ) +} + +function NavigationMenuItem({ + className, + font, + ...props +}: React.ComponentProps & FontVariantProps) { + return ( + + ) +} + +function NavigationMenuTrigger({ + className, + font, + ...props +}: React.ComponentProps & + FontVariantProps) { + return ( + + ) +} + +function NavigationMenuContent({ + className, + font, + children, + ...props +}: React.ComponentProps & + FontVariantProps) { + return ( + + {children} + + ) +} + +function NavigationMenuViewport({ + className, + font, + ...props +}: React.ComponentProps & FontVariantProps) { + return ( +
    + +
    + ) +} + +function NavigationMenuLink({ + className, + font, + ...props +}: React.ComponentProps & FontVariantProps) { + return ( + + ) +} + +function NavigationMenuIndicator({ + className, + font, + ...props +}: React.ComponentProps & + FontVariantProps) { + return ( + +
    + + ) +} + +export { + NavigationMenu, + NavigationMenuContent, + NavigationMenuIndicator, + NavigationMenuItem, + NavigationMenuLink, + NavigationMenuList, + NavigationMenuTrigger, + NavigationMenuViewport, +} diff --git a/components/ui/navigation-menu.tsx b/components/ui/navigation-menu.tsx new file mode 100644 index 00000000..1199945c --- /dev/null +++ b/components/ui/navigation-menu.tsx @@ -0,0 +1,168 @@ +import * as React from "react" +import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu" +import { cva } from "class-variance-authority" +import { ChevronDownIcon } from "lucide-react" + +import { cn } from "@/lib/utils" + +function NavigationMenu({ + className, + children, + viewport = true, + ...props +}: React.ComponentProps & { + viewport?: boolean +}) { + return ( + + {children} + {viewport && } + + ) +} + +function NavigationMenuList({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function NavigationMenuItem({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +const navigationMenuTriggerStyle = cva( + "group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=open]:hover:bg-accent data-[state=open]:text-accent-foreground data-[state=open]:focus:bg-accent data-[state=open]:bg-accent/50 focus-visible:ring-ring/50 outline-none transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1" +) + +function NavigationMenuTrigger({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + {children}{" "} + + ) +} + +function NavigationMenuContent({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function NavigationMenuViewport({ + className, + ...props +}: React.ComponentProps) { + return ( +
    + +
    + ) +} + +function NavigationMenuLink({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function NavigationMenuIndicator({ + className, + ...props +}: React.ComponentProps) { + return ( + +
    + + ) +} + +export { + NavigationMenu, + NavigationMenuList, + NavigationMenuItem, + NavigationMenuContent, + NavigationMenuTrigger, + NavigationMenuLink, + NavigationMenuIndicator, + NavigationMenuViewport, + navigationMenuTriggerStyle, +} diff --git a/config/nav-items.ts b/config/nav-items.ts index a3faffbc..e8e9b2b0 100644 --- a/config/nav-items.ts +++ b/config/nav-items.ts @@ -95,6 +95,10 @@ const components = [ title: "Input OTP", url: "/docs/components/input-otp", }, + { + title: "Navigation Menu", + url: "/docs/components/navigation-menu", + }, { title: "Scroll Area", url: "/docs/components/scroll-area", diff --git a/lib/metadata.ts b/lib/metadata.ts index 1e62ae32..e7fec42a 100644 --- a/lib/metadata.ts +++ b/lib/metadata.ts @@ -54,3 +54,4 @@ export const contextMenuMetaData = "/assets/8bitcn-context-menu-light.png" export const menubarMetaData = "/assets/8bitcn-menubar-light.png" export const sidebarMetaData = "/assets/8bitcn-sidebar-light.png" export const toastMetaData = "/assets/8bitcn-toast-light.png" +export const navigationMenuMetaData = "/assets/8bitcn-navigation-menu-light.png" diff --git a/package.json b/package.json index 73356fad..751afc73 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@radix-ui/react-hover-card": "^1.1.14", "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-menubar": "^1.1.15", + "@radix-ui/react-navigation-menu": "^1.2.13", "@radix-ui/react-popover": "^1.1.14", "@radix-ui/react-progress": "^1.1.7", "@radix-ui/react-radio-group": "^1.3.7", diff --git a/public/assets/8bitcn-navigation-menu-light.png b/public/assets/8bitcn-navigation-menu-light.png new file mode 100644 index 00000000..914cabd5 Binary files /dev/null and b/public/assets/8bitcn-navigation-menu-light.png differ diff --git a/public/r/8bit-navigation-menu.json b/public/r/8bit-navigation-menu.json new file mode 100644 index 00000000..bc27ad6f --- /dev/null +++ b/public/r/8bit-navigation-menu.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "8bit-navigation-menu", + "type": "registry:component", + "title": "8-bit Navigation Menu", + "description": "A simple 8-bit navigation menu component", + "registryDependencies": [ + "navigation-menu" + ], + "files": [ + { + "path": "components/ui/8bit/navigation-menu.tsx", + "content": "import * as React from \"react\"\nimport { Press_Start_2P } from \"next/font/google\"\nimport { Indicator, Root, Viewport } from \"@radix-ui/react-navigation-menu\"\nimport { cva, VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport {\n NavigationMenuContent as ShadcnNavigationMenuContent,\n NavigationMenuIndicator as ShadcnNavigationMenuIndicator,\n NavigationMenuItem as ShadcnNavigationMenuItem,\n NavigationMenuLink as ShadcnNavigationMenuLink,\n NavigationMenuList as ShadcnNavigationMenuList,\n NavigationMenuTrigger as ShadcnNavigationMenuTrigger,\n} from \"@/components/ui/navigation-menu\"\n\nexport { navigationMenuTriggerStyle } from \"@/components/ui/navigation-menu\"\n\nconst pressStart = Press_Start_2P({\n weight: [\"400\"],\n subsets: [\"latin\"],\n})\n\nexport const navigationMenuVariants = cva(\"\", {\n variants: {\n font: {\n normal: \"\",\n retro: pressStart.className,\n },\n },\n defaultVariants: {\n font: \"retro\",\n },\n})\n\ntype FontVariantProps = VariantProps\n\nconst getFontClassName = (font: FontVariantProps[\"font\"]) =>\n navigationMenuVariants({ font })\n\nfunction NavigationMenu({\n className,\n font,\n children,\n viewport = true,\n ...props\n}: React.ComponentProps & {\n viewport?: boolean\n} & FontVariantProps) {\n return (\n \n {children}\n {viewport && }\n \n )\n}\n\nfunction NavigationMenuList({\n className,\n font,\n ...props\n}: React.ComponentProps &\n VariantProps) {\n return (\n \n )\n}\n\nfunction NavigationMenuItem({\n className,\n font,\n ...props\n}: React.ComponentProps & FontVariantProps) {\n return (\n \n )\n}\n\nfunction NavigationMenuTrigger({\n className,\n font,\n ...props\n}: React.ComponentProps &\n FontVariantProps) {\n return (\n \n )\n}\n\nfunction NavigationMenuContent({\n className,\n font,\n children,\n ...props\n}: React.ComponentProps &\n FontVariantProps) {\n return (\n \n {children}\n \n )\n}\n\nfunction NavigationMenuViewport({\n className,\n font,\n ...props\n}: React.ComponentProps & FontVariantProps) {\n return (\n \n \n
    \n )\n}\n\nfunction NavigationMenuLink({\n className,\n font,\n ...props\n}: React.ComponentProps & FontVariantProps) {\n return (\n \n )\n}\n\nfunction NavigationMenuIndicator({\n className,\n font,\n ...props\n}: React.ComponentProps &\n FontVariantProps) {\n return (\n \n
    \n \n )\n}\n\nexport {\n NavigationMenu,\n NavigationMenuContent,\n NavigationMenuIndicator,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n NavigationMenuTrigger,\n NavigationMenuViewport,\n}\n", + "type": "registry:component", + "target": "components/ui/8bit/navigation-menu.tsx" + } + ] +} \ No newline at end of file diff --git a/registry.json b/registry.json index a7e9fc6a..8e6f19f9 100644 --- a/registry.json +++ b/registry.json @@ -769,6 +769,20 @@ "target": "components/ui/8bit/drawer.tsx" } ] + }, + { + "name": "8bit-navigation-menu", + "type": "registry:component", + "title": "8-bit Navigation Menu", + "description": "A simple 8-bit navigation menu component", + "registryDependencies": ["navigation-menu"], + "files": [ + { + "path": "components/ui/8bit/navigation-menu.tsx", + "type": "registry:component", + "target": "components/ui/8bit/navigation-menu.tsx" + } + ] } ] }