diff --git a/app/docs/components/menubar/page.tsx b/app/docs/components/menubar/page.tsx
new file mode 100644
index 00000000..2658ab8e
--- /dev/null
+++ b/app/docs/components/menubar/page.tsx
@@ -0,0 +1,191 @@
+import { Metadata } from "next"
+
+import { menubarMetaData } from "@/lib/metadata"
+import {
+ Menubar,
+ MenubarCheckboxItem,
+ MenubarContent,
+ MenubarItem,
+ MenubarMenu,
+ MenubarRadioGroup,
+ MenubarRadioItem,
+ MenubarSeparator,
+ MenubarShortcut,
+ MenubarSub,
+ MenubarSubContent,
+ MenubarSubTrigger,
+ MenubarTrigger,
+} from "@/components/ui/8bit/menubar"
+import { Separator } from "@/components/ui/separator"
+
+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 Menubar",
+ description: "Displays an 8-bit menubar component.",
+ openGraph: {
+ images: menubarMetaData,
+ },
+}
+
+export default function MenubarPage() {
+ return (
+
+
+
Menubar
+
+
+
+
+ Displays an 8-bit menubar component.
+
+
+
+
+
+ 8-bit menubar component
+
+
+
+
+
+
+
+
+
+ File
+
+
+ New Tab ⌘T
+
+
+ New Window ⌘N
+
+ New Incognito Window
+
+
+ Share
+
+ Email link
+ Messages
+ Notes
+
+
+
+
+ Print... ⌘P
+
+
+
+
+ Edit
+
+
+ Undo ⌘Z
+
+
+ Redo ⇧⌘Z
+
+
+
+ Find
+
+ Search the web
+
+ Find...
+ Find Next
+ Find Previous
+
+
+
+ Cut
+ Copy
+ Paste
+
+
+
+ View
+
+
+ Always Show Bookmarks Bar
+
+
+ Always Show Full URLs
+
+
+
+ Reload ⌘R
+
+
+ Force Reload ⇧⌘R
+
+
+ Toggle Fullscreen
+
+ Hide Sidebar
+
+
+
+ Profiles
+
+
+ Andy
+ Benoit
+ Luis
+
+
+ Edit...
+
+ Add Profile...
+
+
+
+
+
+
+
Installation
+
+
+
+
+
+
Usage
+
+
+
+
{`import {
+ Menubar,
+ MenubarContent,
+ MenubarItem,
+ MenubarMenu,
+ MenubarSeparator,
+ MenubarShortcut,
+ MenubarTrigger,
+} from "@/components/ui/8bit/menubar"`}
+
+
{`
+
+ File
+
+
+ New Tab ⌘T
+
+ New Window
+
+ Share
+
+ Print
+
+
+`}
+
+ )
+}
diff --git a/components/ui/8bit/menubar.tsx b/components/ui/8bit/menubar.tsx
new file mode 100644
index 00000000..24a469da
--- /dev/null
+++ b/components/ui/8bit/menubar.tsx
@@ -0,0 +1,381 @@
+"use client"
+
+import * as React from "react"
+import { Press_Start_2P } from "next/font/google"
+import * as MenubarPrimitive from "@radix-ui/react-menubar"
+import { cva } from "class-variance-authority"
+import { Circle } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+const pressStart = Press_Start_2P({
+ weight: ["400"],
+ subsets: ["latin"],
+})
+
+export const menubarVariants = cva("", {
+ variants: {
+ font: {
+ normal: "",
+ retro: pressStart.className,
+ },
+ },
+ defaultVariants: {
+ font: "retro",
+ },
+})
+
+function MenubarMenu({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function MenubarGroup({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function MenubarPortal({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function MenubarRadioGroup({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function MenubarSub({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+const Menubar = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+Menubar.displayName = MenubarPrimitive.Root.displayName
+
+const MenubarTrigger = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName
+
+const MenubarSubTrigger = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ }
+>(({ className, inset, children, ...props }, ref) => (
+
+ {children}
+
+
+))
+MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName
+
+const MenubarSubContent = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName
+
+const MenubarContent = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef
+>(
+ (
+ { className, align = "start", alignOffset = -4, sideOffset = 8, ...props },
+ ref
+ ) => (
+
+
+
+ )
+)
+MenubarContent.displayName = MenubarPrimitive.Content.displayName
+
+const MenubarItem = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ }
+>(({ className, inset, ...props }, ref) => (
+
+))
+MenubarItem.displayName = MenubarPrimitive.Item.displayName
+
+const MenubarCheckboxItem = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, checked, ...props }, ref) => (
+
+
+
+
+
+
+ {children}
+
+))
+MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName
+
+const MenubarRadioItem = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+
+
+
+ {children}
+
+))
+MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName
+
+const MenubarLabel = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ }
+>(({ className, inset, ...props }, ref) => (
+
+))
+MenubarLabel.displayName = MenubarPrimitive.Label.displayName
+
+const MenubarSeparator = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName
+
+const MenubarShortcut = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => {
+ return (
+
+ )
+}
+MenubarShortcut.displayname = "MenubarShortcut"
+
+export {
+ Menubar,
+ MenubarMenu,
+ MenubarTrigger,
+ MenubarContent,
+ MenubarItem,
+ MenubarSeparator,
+ MenubarLabel,
+ MenubarCheckboxItem,
+ MenubarRadioGroup,
+ MenubarRadioItem,
+ MenubarPortal,
+ MenubarSubContent,
+ MenubarSubTrigger,
+ MenubarGroup,
+ MenubarSub,
+ MenubarShortcut,
+}
diff --git a/config/nav-items.ts b/config/nav-items.ts
index 7b58ab6e..6aa11008 100644
--- a/config/nav-items.ts
+++ b/config/nav-items.ts
@@ -120,6 +120,11 @@ const components = [
title: "Label",
url: "/docs/components/label",
},
+ {
+ title: "Menubar",
+ url: "/docs/components/menubar",
+ new: true,
+ },
{
title: "Pagination",
url: "/docs/components/pagination",
diff --git a/lib/metadata.ts b/lib/metadata.ts
index f5106a52..ac5240ef 100644
--- a/lib/metadata.ts
+++ b/lib/metadata.ts
@@ -50,3 +50,4 @@ export const accordionMetaData = "/assets/8bitcn-accordion-light.png"
export const sliderMetaData = "/assets/8bitcn-slider-light.png"
export const datePickerMetaData = "/assets/8bitcn-date-picker-light.png"
export const contextMenuMetaData = "/assets/8bitcn-context-menu-light.png"
+export const menubarMetaData = "/assets/8bitcn-menubar-light.png"
diff --git a/package.json b/package.json
index 52fca727..2126a322 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
"@radix-ui/react-dropdown-menu": "^2.1.14",
"@radix-ui/react-hover-card": "^1.1.13",
"@radix-ui/react-label": "^2.1.6",
+ "@radix-ui/react-menubar": "^1.1.14",
"@radix-ui/react-popover": "^1.1.13",
"@radix-ui/react-progress": "^1.1.6",
"@radix-ui/react-radio-group": "^1.3.6",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1e25d716..65ad03bf 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -38,6 +38,9 @@ importers:
'@radix-ui/react-label':
specifier: ^2.1.6
version: 2.1.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-menubar':
+ specifier: ^1.1.14
+ version: 1.1.14(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-popover':
specifier: ^1.1.13
version: 1.1.13(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
@@ -913,6 +916,19 @@ packages:
'@types/react-dom':
optional: true
+ '@radix-ui/react-menubar@1.1.14':
+ resolution: {integrity: sha512-nWLOS7EG3iYhT/zlE/Pbip17rrMnV/0AS7ueb3pKHTSAnpA6/N9rXQYowulZw4owZ9P+qSilHsFzSx/kU7yplQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@radix-ui/react-popover@1.1.13':
resolution: {integrity: sha512-84uqQV3omKDR076izYgcha6gdpN8m3z6w/AeJ83MSBJYVG/AbOHdLjAgsPZkeC/kt+k64moXFCnio8BbqXszlw==}
peerDependencies:
@@ -4560,6 +4576,24 @@ snapshots:
'@types/react': 19.1.4
'@types/react-dom': 19.1.5(@types/react@19.1.4)
+ '@radix-ui/react-menubar@1.1.14(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-collection': 1.1.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.4)(react@19.1.0)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.1.4)(react@19.1.0)
+ '@radix-ui/react-direction': 1.1.1(@types/react@19.1.4)(react@19.1.0)
+ '@radix-ui/react-id': 1.1.1(@types/react@19.1.4)(react@19.1.0)
+ '@radix-ui/react-menu': 2.1.14(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-roving-focus': 1.1.9(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.4)(react@19.1.0)
+ react: 19.1.0
+ react-dom: 19.1.0(react@19.1.0)
+ optionalDependencies:
+ '@types/react': 19.1.4
+ '@types/react-dom': 19.1.5(@types/react@19.1.4)
+
'@radix-ui/react-popover@1.1.13(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.2
diff --git a/public/assets/8bitcn-menubar-light.png b/public/assets/8bitcn-menubar-light.png
new file mode 100644
index 00000000..57265583
Binary files /dev/null and b/public/assets/8bitcn-menubar-light.png differ
diff --git a/public/r/8bit-menubar.json b/public/r/8bit-menubar.json
new file mode 100644
index 00000000..6f84dfee
--- /dev/null
+++ b/public/r/8bit-menubar.json
@@ -0,0 +1,16 @@
+{
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
+ "name": "8bit-menubar",
+ "type": "registry:component",
+ "title": "8-bit Menu Bar",
+ "description": "A simple 8-bit menu bar component",
+ "registryDependencies": [],
+ "files": [
+ {
+ "path": "components/ui/8bit/menubar.tsx",
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Press_Start_2P } from \"next/font/google\"\nimport * as MenubarPrimitive from \"@radix-ui/react-menubar\"\nimport { cva } from \"class-variance-authority\"\nimport { Circle } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst pressStart = Press_Start_2P({\n weight: [\"400\"],\n subsets: [\"latin\"],\n})\n\nexport const menubarVariants = cva(\"\", {\n variants: {\n font: {\n normal: \"\",\n retro: pressStart.className,\n },\n },\n defaultVariants: {\n font: \"retro\",\n },\n})\n\nfunction MenubarMenu({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction MenubarGroup({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction MenubarPortal({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction MenubarRadioGroup({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction MenubarSub({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nconst Menubar = React.forwardRef<\n React.ComponentRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nMenubar.displayName = MenubarPrimitive.Root.displayName\n\nconst MenubarTrigger = React.forwardRef<\n React.ComponentRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nMenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName\n\nconst MenubarSubTrigger = React.forwardRef<\n React.ComponentRef,\n React.ComponentPropsWithoutRef & {\n inset?: boolean\n }\n>(({ className, inset, children, ...props }, ref) => (\n \n {children}\n \n \n))\nMenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName\n\nconst MenubarSubContent = React.forwardRef<\n React.ComponentRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nMenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName\n\nconst MenubarContent = React.forwardRef<\n React.ComponentRef,\n React.ComponentPropsWithoutRef\n>(\n (\n { className, align = \"start\", alignOffset = -4, sideOffset = 8, ...props },\n ref\n ) => (\n \n \n \n )\n)\nMenubarContent.displayName = MenubarPrimitive.Content.displayName\n\nconst MenubarItem = React.forwardRef<\n React.ComponentRef,\n React.ComponentPropsWithoutRef & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n \n))\nMenubarItem.displayName = MenubarPrimitive.Item.displayName\n\nconst MenubarCheckboxItem = React.forwardRef<\n React.ComponentRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, checked, ...props }, ref) => (\n \n \n \n \n \n \n {children}\n \n))\nMenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName\n\nconst MenubarRadioItem = React.forwardRef<\n React.ComponentRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, ...props }, ref) => (\n \n \n \n \n \n \n {children}\n \n))\nMenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName\n\nconst MenubarLabel = React.forwardRef<\n React.ComponentRef,\n React.ComponentPropsWithoutRef & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n \n))\nMenubarLabel.displayName = MenubarPrimitive.Label.displayName\n\nconst MenubarSeparator = React.forwardRef<\n React.ComponentRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nMenubarSeparator.displayName = MenubarPrimitive.Separator.displayName\n\nconst MenubarShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes) => {\n return (\n \n )\n}\nMenubarShortcut.displayname = \"MenubarShortcut\"\n\nexport {\n Menubar,\n MenubarMenu,\n MenubarTrigger,\n MenubarContent,\n MenubarItem,\n MenubarSeparator,\n MenubarLabel,\n MenubarCheckboxItem,\n MenubarRadioGroup,\n MenubarRadioItem,\n MenubarPortal,\n MenubarSubContent,\n MenubarSubTrigger,\n MenubarGroup,\n MenubarSub,\n MenubarShortcut,\n}\n",
+ "type": "registry:component",
+ "target": "components/ui/8bit/menubar.tsx"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/registry.json b/registry.json
index 14f43b35..c2bf903c 100644
--- a/registry.json
+++ b/registry.json
@@ -423,6 +423,20 @@
}
]
},
+ {
+ "name": "8bit-menubar",
+ "type": "registry:component",
+ "title": "8-bit Menu Bar",
+ "description": "A simple 8-bit menu bar component",
+ "registryDependencies": [],
+ "files": [
+ {
+ "path": "components/ui/8bit/menubar.tsx",
+ "type": "registry:component",
+ "target": "components/ui/8bit/menubar.tsx"
+ }
+ ]
+ },
{
"name": "8bit-toggle",
"type": "registry:component",