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 \n \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 \n \n \n \n \n \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 \n \n \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",