Menubar
Описание
Визуально постоянное меню, распространенное в настольных приложениях и обеспечивающее быстрый доступ к последовательному набору команд.
Компонент используется только для настольных приложений, поэтому он использует уменьшенные размеры, нежели в компоненте Menu.
Примеры
Компонент
Компонент можно сохранить в src/shared/ui/Menubar.tsx. Обратите внимание на необходимые зависимости: Label.
Так же данный компонент использует @radix-ui/react-menubar компонент.
yarn add @radix-ui/react-menubar
"use client"import React from "react"import * as MenubarPrimitive from "@radix-ui/react-menubar"import { Check, NavArrowRight, Circle } from "iconoir-react"import Label, { labelVariants } from "../typography/Label"import { cn } from "@/lib/cn"const MenubarMenu = MenubarPrimitive.Menuconst MenubarGroup = MenubarPrimitive.Groupconst MenubarPortal = MenubarPrimitive.Portalconst MenubarSub = MenubarPrimitive.Subconst MenubarRadioGroup = MenubarPrimitive.RadioGroupconst Menubar = React.forwardRef<React.ElementRef<typeof MenubarPrimitive.Root>,React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>>(({ className, ...props }, ref) => (<MenubarPrimitive.Rootref={ref}className={cn("flex h-10 items-center space-x-1 rounded-medium border border-outlineVariant p-1",className)}{...props}/>))Menubar.displayName = MenubarPrimitive.Root.displayNameconst MenubarTrigger = React.forwardRef<React.ElementRef<typeof MenubarPrimitive.Trigger>,React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>>(({ className, children, ...props }, ref) => (<MenubarPrimitive.Triggerref={ref}className={cn("flex cursor-default select-none items-center rounded-small px-3 py-1.5 outline-none hover:bg-surfaceContainer focus:bg-surfaceContainerHighest focus:text-onSurface data-[state=open]:bg-surfaceContainerHighest data-[state=open]:text-onSurface transition-colors",className)}{...props}><Label size="large">{children}</Label></MenubarPrimitive.Trigger>))MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayNameconst MenubarSubTrigger = React.forwardRef<React.ElementRef<typeof MenubarPrimitive.SubTrigger>,React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {inset?: boolean}>(({ className, inset, children, ...props }, ref) => (<MenubarPrimitive.SubTriggerref={ref}className={cn("flex cursor-default select-none items-center px-2 py-1.5 outline-none text-onSurface aria-disabled:text-opacity-[0.38] data-[highlighted]:bg-onSurface/[0.12]",inset && "pl-8",className)}{...props}><Label size="large">{children}</Label><NavArrowRight className="ml-auto h-4 w-4" /></MenubarPrimitive.SubTrigger>))MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayNameconst MenubarSubContent = React.forwardRef<React.ElementRef<typeof MenubarPrimitive.SubContent>,React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>>(({ className, ...props }, ref) => (<MenubarPrimitive.SubContentref={ref}className={cn("z-50 min-w-[8rem] flex flex-col rounded bg-surfaceContainer shadow-elevation2 py-1",className)}{...props}/>))MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayNameconst MenubarContent = React.forwardRef<React.ElementRef<typeof MenubarPrimitive.Content>,React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>>(({ className, align = "start", ...props }, ref) => (<MenubarPrimitive.Portal><MenubarPrimitive.Contentref={ref}align={align}className={cn("relative z-50 min-w-[12rem] text-onSurfaceContainer flex flex-col rounded bg-surfaceContainer shadow-elevation2 py-1",className)}{...props}/></MenubarPrimitive.Portal>))MenubarContent.displayName = MenubarPrimitive.Content.displayNameconst MenubarItem = React.forwardRef<React.ElementRef<typeof MenubarPrimitive.Item>,React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {inset?: boolean}>(({ className, inset, ...props }, ref) => (<MenubarPrimitive.Itemref={ref}className={cn(labelVariants({ size: "large" }),"relative flex cursor-default select-none items-center px-2 py-1.5 outline-none text-onSurface aria-disabled:text-opacity-[0.38] data-[highlighted]:bg-onSurface/[0.12]",inset && "pl-8",className)}{...props}/>))MenubarItem.displayName = MenubarPrimitive.Item.displayNameconst MenubarCheckboxItem = React.forwardRef<React.ElementRef<typeof MenubarPrimitive.CheckboxItem>,React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>>(({ className, children, checked, ...props }, ref) => (<MenubarPrimitive.CheckboxItemref={ref}className={cn(labelVariants({ size: "large" }),"relative flex cursor-default select-none items-center py-1.5 pl-8 pr-2 outline-none text-onSurface aria-disabled:text-opacity-[0.38] data-[highlighted]:bg-onSurface/[0.12]",className)}checked={checked}{...props}><span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"><MenubarPrimitive.ItemIndicator><Check className="h-4 w-4" /></MenubarPrimitive.ItemIndicator></span>{children}</MenubarPrimitive.CheckboxItem>))MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayNameconst MenubarRadioItem = React.forwardRef<React.ElementRef<typeof MenubarPrimitive.RadioItem>,React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>>(({ className, children, ...props }, ref) => (<MenubarPrimitive.RadioItemref={ref}className={cn(labelVariants({ size: "large" }),"relative flex cursor-default select-none items-center py-1.5 pl-8 pr-2 outline-none text-onSurface aria-disabled:text-opacity-[0.38] data-[highlighted]:bg-onSurface/[0.12]",className)}{...props}><span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"><MenubarPrimitive.ItemIndicator><Circle className="h-2 w-2 fill-current" /></MenubarPrimitive.ItemIndicator></span>{children}</MenubarPrimitive.RadioItem>))MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayNameconst MenubarLabel = React.forwardRef<React.ElementRef<typeof MenubarPrimitive.Label>,React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {inset?: boolean}>(({ className, inset, ...props }, ref) => (<MenubarPrimitive.Labelref={ref}className={cn("px-2 py-1.5 text-sm font-semibold",inset && "pl-12",className)}{...props}/>))MenubarLabel.displayName = MenubarPrimitive.Label.displayNameconst MenubarSeparator = React.forwardRef<React.ElementRef<typeof MenubarPrimitive.Separator>,React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>>(({ className, ...props }, ref) => (<MenubarPrimitive.Separatorref={ref}className={cn("w-full my-1 h-px bg-outlineVariant", className)}{...props}/>))MenubarSeparator.displayName = MenubarPrimitive.Separator.displayNameconst MenubarShortcut = ({className,children,...props}: React.HTMLAttributes<HTMLSpanElement>) => {return (<Labelsize="large"className={cn("ml-auto text-onSurfaceVariant", className)}{...props}>{children}</Label>)}MenubarShortcut.displayname = "MenubarShortcut"export {Menubar,MenubarMenu,MenubarTrigger,MenubarContent,MenubarItem,MenubarSeparator,MenubarLabel,MenubarCheckboxItem,MenubarRadioGroup,MenubarRadioItem,MenubarPortal,MenubarSubContent,MenubarSubTrigger,MenubarGroup,MenubarSub,MenubarShortcut,}
Использование
Данный файл экспортирует 16 компонентов
Menubar - root компонент, содержащий стейт о том, какой MenubarMenu сейчас открыт
MenubarMenu - компонент, содержащий все части MenubarContent
MenubarTrigger - кнопка, открывающая одно из MenubarMenu
MenubarPortal - когда используется, вставляет MenubarContent в тег body. В ином случае MenubarContent будет вставляться в MenubarMenu
MenubarContent - контейнер, содержащий все элементы Menu
MenubarItem - кнопка в Menu; может быть текстом в конце (MenubarShortcut)
MenubarCheckboxItem - кнопка в Menu с функционалом чекбокса; может быть текстом в конце (MenubarShortcut)
MenubarRadioGroup - обёртка для хранения состояния радио-кнопок MenubarRadioItem
MenubarRadioItem - кнопка в Menu с функционалом радио-кнопки; может быть текстом в конце (MenubarShortcut)
MenubarSeparator - разделитель Menu на логические блоки
MenubarLabel - текст, который несёт только информативную часть (не является кнопкой)
MenubarSub - аналог MenubarMenu, но для вторичного Menu
MenubarSubContent - аналог MenubarContent, но для вторичного Menu
MenubarSubTrigger - кнопка, активирующая вторичное Menu
MenubarShortcut - текст в конце кнопок MenubarItem, MenubarCheckboxItem и MenubarRadioItem
MenubarGroup - используется для группировки нескольких MenubarItem, MenubarCheckboxItem и MenubarRadioItem
Примеры
Ниже - код для примера в начале страницы.
"use client"import React from "react"import {Menubar,MenubarCheckboxItem,MenubarContent,MenubarItem,MenubarMenu,MenubarRadioGroup,MenubarRadioItem,MenubarSeparator,MenubarShortcut,MenubarSub,MenubarSubContent,MenubarSubTrigger,MenubarTrigger,} from "@/shared/ui/Menubar"export function MenubarExample() {const [profile, setProfile] = React.useState("benoit")return (<Menubar><MenubarMenu><MenubarTrigger>File</MenubarTrigger><MenubarContent><MenubarItem>New Tab <MenubarShortcut>⌘+T</MenubarShortcut></MenubarItem><MenubarItem>New Window <MenubarShortcut>⌘+N</MenubarShortcut></MenubarItem><MenubarItem disabled>New Incognito Window</MenubarItem><MenubarSeparator /><MenubarSub><MenubarSubTrigger>Share</MenubarSubTrigger><MenubarSubContent><MenubarItem>Email link</MenubarItem><MenubarItem>Messages</MenubarItem><MenubarItem>Notes</MenubarItem></MenubarSubContent></MenubarSub><MenubarSeparator /><MenubarItem>Print... <MenubarShortcut>⌘+P</MenubarShortcut></MenubarItem></MenubarContent></MenubarMenu><MenubarMenu><MenubarTrigger>Edit</MenubarTrigger><MenubarContent><MenubarItem>Undo <MenubarShortcut>⌘+Z</MenubarShortcut></MenubarItem><MenubarItem>Redo <MenubarShortcut>⇧⌘+Z</MenubarShortcut></MenubarItem><MenubarSeparator /><MenubarSub><MenubarSubTrigger>Find</MenubarSubTrigger><MenubarSubContent><MenubarItem>Search the web</MenubarItem><MenubarSeparator /><MenubarItem>Find...</MenubarItem><MenubarItem>Find Next</MenubarItem><MenubarItem>Find Previous</MenubarItem></MenubarSubContent></MenubarSub><MenubarSeparator /><MenubarItem>Cut</MenubarItem><MenubarItem>Copy</MenubarItem><MenubarItem>Paste</MenubarItem></MenubarContent></MenubarMenu><MenubarMenu><MenubarTrigger>View</MenubarTrigger><MenubarContent><MenubarCheckboxItem>Always Show Bookmarks Bar</MenubarCheckboxItem><MenubarCheckboxItem checked>Always Show Full URLs</MenubarCheckboxItem><MenubarSeparator /><MenubarItem inset>Reload <MenubarShortcut>⌘+R</MenubarShortcut></MenubarItem><MenubarItem disabled inset>Force Reload <MenubarShortcut>⇧⌘+R</MenubarShortcut></MenubarItem><MenubarSeparator /><MenubarItem inset>Toggle Fullscreen</MenubarItem><MenubarSeparator /><MenubarItem inset>Hide Sidebar</MenubarItem></MenubarContent></MenubarMenu><MenubarMenu><MenubarTrigger>Profiles</MenubarTrigger><MenubarContent><MenubarRadioGroup value={profile} onValueChange={setProfile}><MenubarRadioItem value="andy">Andy</MenubarRadioItem><MenubarRadioItem value="benoit">Benoit</MenubarRadioItem><MenubarRadioItem value="Luis">Luis</MenubarRadioItem></MenubarRadioGroup><MenubarSeparator /><MenubarItem inset>Edit...</MenubarItem><MenubarSeparator /><MenubarItem inset>Add Profile...</MenubarItem></MenubarContent></MenubarMenu></Menubar>)}