Menus
Описание
Меню отображают список вариантов на временной поверхности.
Меню появляется, когда пользователи взаимодействуют с кнопкой, действием или другим элементом управления.
Они могут быть открыты с помощью различных элементов, чаще всего это Icon Buttons, Buttons и Text Fields.
Подробнее об использовании элемента читайте на официальном сайте
Примеры
Компонент
Компонент можно сохранить в src/shared/ui/Menu.tsx. Обратите внимание на необходимые зависимости: Label.
Так же данный компонент использует @radix-ui/react-dropdown-menu компонент.
yarn add @radix-ui/react-dropdown-menu
"use client"import React from "react"import * as DropdownMenu from "@radix-ui/react-dropdown-menu"import { NavArrowRight } from "iconoir-react"import Label from "@/shared/typography/Label"import { cn } from "@/lib/cn"const MenuRoot = DropdownMenu.Rootconst MenuTrigger = React.forwardRef<React.ElementRef<typeof DropdownMenu.Trigger>,React.ComponentPropsWithoutRef<typeof DropdownMenu.Trigger>>(({ children, className, ...props }, forwardedRef) => (<DropdownMenu.TriggerclassName={cn(className)}{...props}ref={forwardedRef}asChild>{children}</DropdownMenu.Trigger>))MenuTrigger.displayName = "MenuTrigger"const MenuPortal = DropdownMenu.Portalconst MenuContent = React.forwardRef<React.ElementRef<typeof DropdownMenu.Content>,React.ComponentPropsWithoutRef<typeof DropdownMenu.Content>>(({ className, children, ...props }, forwardedRef) => (<DropdownMenu.ContentclassName={cn("flex flex-col rounded bg-surfaceContainer shadow-elevation2 py-2 w-[280px] will-change-[opacity,transform] data-[side=bottom]:animate-slide-down-and-fade-in origin-top-left data-[state=closed]:animate-slide-up-and-fade-out",className)}{...props}ref={forwardedRef}align="start">{children}</DropdownMenu.Content>))MenuContent.displayName = "MenuContent"type MenuItemElement = React.ElementRef<typeof DropdownMenu.Item>type DropdownMenuProps = React.ComponentPropsWithoutRef<typeof DropdownMenu.Item>interface MenuItemProps extends DropdownMenuProps {leading?: React.ReactNodetrailing?: React.ReactNode | string}const MenuItem = React.forwardRef<MenuItemElement, MenuItemProps>(({ className, children, leading, trailing, ...props }, forwardedRef) => (<DropdownMenu.ItemclassName={cn("h-12 flex items-center gap-3 px-3 select-none outline-none text-onSurface aria-disabled:text-opacity-[0.38] data-[highlighted]:bg-onSurface/[0.12]",className)}{...props}ref={forwardedRef}>{leading && <span className="text-onSurfaceVariant">{leading}</span>}<Label size="large">{children}</Label>{typeof trailing === "string" ? (<Label size="large" className="ml-auto text-onSurfaceVariant">{trailing}</Label>) : (<span className="ml-auto text-onSurfaceVariant">{trailing}</span>)}</DropdownMenu.Item>))MenuItem.displayName = "MenuItem"const MenuSeparator = () => (<DropdownMenu.Separator className="w-full my-2 h-px bg-outlineVariant" />)const MenuSub = DropdownMenu.Subconst MenuSubTrigger = React.forwardRef<React.ElementRef<typeof DropdownMenu.SubTrigger>,React.ComponentPropsWithoutRef<typeof DropdownMenu.SubTrigger>>(({ className, children, ...props }, forwardedRef) => (<DropdownMenu.SubTriggerclassName={cn("text-onSurface h-12 flex items-center justify-between gap-3 px-3 aria-disabled:text-opacity-[0.38] select-none outline-none hover:bg-onSurface bg-opacity-0 hover:bg-opacity-[0.08] active:bg-opacity-[0.12] aria-disabled:bg-opacity-0 data-[highlighted]:bg-onSurface data-[highlighted]:bg-opacity-[0.12]",className)}ref={forwardedRef}{...props}><><Label size="large">{children}</Label><NavArrowRight /></></DropdownMenu.SubTrigger>))MenuSubTrigger.displayName = "MenuSubTrigger"const MenuSubContent = React.forwardRef<React.ElementRef<typeof DropdownMenu.SubContent>,React.ComponentPropsWithoutRef<typeof DropdownMenu.SubContent>>(({ children, className, ...props }, forwardedRef) => (<DropdownMenu.SubContentclassName={cn("flex flex-col rounded bg-surfaceContainer shadow-elevation2 py-2 w-[280px] will-change-[opacity,transform] data-[side=right]:animate-slide-down-and-fade-in origin-top-left data-[state=closed]:animate-slide-up-and-fade-out",className)}ref={forwardedRef}{...props}>{children}</DropdownMenu.SubContent>))MenuSubContent.displayName = "MenuSubContent"export {MenuRoot,MenuTrigger,MenuPortal,MenuContent,MenuItem,MenuSeparator,MenuSub,MenuSubTrigger,MenuSubContent,}
Использование
Данный файл экспортирует 9 компонентов
MenuRoot - компонент, содержащий стейт о том, открыто сейчас Menu или нет
MenuTrigger - кнопка, открывающая Menu
MenuPortal - обёртка для MenuContent
MenuContent - контейнер, содержащий все элементы Menu
MenuItem - кнопка в Menu; может быть с иконкой вначале (leading), иконкой или текстом в конце (trailing)
MenuSeparator - разделитель Menu на логические блоки
MenuSub - аналог MenuRoot, но для вторичного Menu
MenuSubTrigger - кнопка, активирующая вторичное Menu
MenuSubContent - аналог MenuContent, но для вторичного Menu
Ниже - код для примера в начале страницы.
<MenuRoot><MenuTrigger><Button appearance={"tonal"}>Trigger the menu</Button></MenuTrigger><MenuPortal><MenuContent><MenuItem leading={<Plus />}>With leading icon</MenuItem><MenuItem trailing="⌘+B" className="pl-12">With trailing text</MenuItem><MenuItem trailing={<Check />} className="pl-12">With trailing icon</MenuItem><MenuItem leading={<Plus />} trailing={<Check />}>With both</MenuItem><MenuItem leading={<Plus />} trailing="⌘+B">With both</MenuItem><MenuSeparator /><MenuItem disabled>Disabled item</MenuItem></MenuContent></MenuPortal></MenuRoot>