ข้ามไปเนื้อหา
WhereUI

ค้นหาในเอกสาร

ค้นหาชื่อ component หรือหน้าเอกสาร

Menubar

จาก shadcn

แถบเมนูแนวนอนแบบโปรแกรมสำนักงาน เช่น ไฟล์ มุมมอง ที่เปิดเมนูย่อยรายการ พร้อมรายการกาติ๊กและวิทยุสำหรับตัวเลือกมุมมอง

ติดตั้ง

Terminal
pnpm dlx shadcn@latest add @whereui/menubar

ต้องผูก registry และติดตั้ง @whereui/theme นำหน้าเสมอเมื่อติดตั้งครั้งแรก

การใช้งาน

import { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarTrigger } from "@/components/ui/menubar"<Menubar>  <MenubarMenu>    <MenubarTrigger>ไฟล์</MenubarTrigger>    <MenubarContent>      <MenubarItem>สร้างคำขอใหม่</MenubarItem>    </MenubarContent>  </MenubarMenu></Menubar>

ข้อควรรู้

  • เมนูแต่ละอันใช้คีย์บอร์ดได้เต็มรูปแบบ: ลูกศรซ้าย–ขวาสลับเมนู, ขึ้น–ลงเลื่อนรายการ, Esc ปิด
  • บนจอแคบควรใส่ overflow-x-auto ให้แถบเลื่อนได้ หรือพิจารณาใช้ DropdownMenu แทน

ซอร์สโค้ด

components/ui/menubar.tsx
"use client"import * as React from "react"import { Menu as MenuPrimitive } from "@base-ui/react/menu"import { Menubar as MenubarPrimitive } from "@base-ui/react/menubar"import { cn } from "cn"import {  DropdownMenu,  DropdownMenuContent,  DropdownMenuGroup,  DropdownMenuItem,  DropdownMenuLabel,  DropdownMenuPortal,  DropdownMenuRadioGroup,  DropdownMenuSeparator,  DropdownMenuShortcut,  DropdownMenuSub,  DropdownMenuSubContent,  DropdownMenuSubTrigger,  DropdownMenuTrigger,} from "@/components/ui/dropdown-menu"import { CheckIcon } from "lucide-react"function Menubar({ className, ...props }: MenubarPrimitive.Props) {  return (    <MenubarPrimitive      data-slot="menubar"      className={cn(        "flex h-8 items-center gap-0.5 rounded-lg border p-[3px]",        className      )}      {...props}    />  )}function MenubarMenu({ ...props }: React.ComponentProps<typeof DropdownMenu>) {  return <DropdownMenu data-slot="menubar-menu" {...props} />}function MenubarGroup({  ...props}: React.ComponentProps<typeof DropdownMenuGroup>) {  return <DropdownMenuGroup data-slot="menubar-group" {...props} />}function MenubarPortal({  ...props}: React.ComponentProps<typeof DropdownMenuPortal>) {  return <DropdownMenuPortal data-slot="menubar-portal" {...props} />}function MenubarTrigger({  className,  ...props}: React.ComponentProps<typeof DropdownMenuTrigger>) {  return (    <DropdownMenuTrigger      data-slot="menubar-trigger"      className={cn(        "flex items-center rounded-sm px-1.5 py-[2px] text-sm font-medium outline-hidden select-none hover:bg-muted aria-expanded:bg-muted",        className      )}      {...props}    />  )}function MenubarContent({  className,  align = "start",  alignOffset = -4,  sideOffset = 8,  ...props}: React.ComponentProps<typeof DropdownMenuContent>) {  return (    <DropdownMenuContent      data-slot="menubar-content"      align={align}      alignOffset={alignOffset}      sideOffset={sideOffset}      className={cn("min-w-36 rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95", className )}      {...props}    />  )}function MenubarItem({  className,  inset,  variant = "default",  ...props}: React.ComponentProps<typeof DropdownMenuItem>) {  return (    <DropdownMenuItem      data-slot="menubar-item"      data-inset={inset}      data-variant={variant}      className={cn(        "group/menubar-item gap-1.5 rounded-md px-1.5 py-1 text-sm focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:opacity-50 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive!",        className      )}      {...props}    />  )}function MenubarCheckboxItem({  className,  children,  checked,  inset,  ...props}: MenuPrimitive.CheckboxItem.Props & {  inset?: boolean}) {  return (    <MenuPrimitive.CheckboxItem      data-slot="menubar-checkbox-item"      data-inset={inset}      className={cn(        "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-1.5 pl-7 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",        className      )}      checked={checked}      {...props}    >      <span className="pointer-events-none absolute left-1.5 flex size-4 items-center justify-center [&_svg:not([class*='size-'])]:size-4">        <MenuPrimitive.CheckboxItemIndicator>          <CheckIcon          />        </MenuPrimitive.CheckboxItemIndicator>      </span>      {children}    </MenuPrimitive.CheckboxItem>  )}function MenubarRadioGroup({  ...props}: React.ComponentProps<typeof DropdownMenuRadioGroup>) {  return <DropdownMenuRadioGroup data-slot="menubar-radio-group" {...props} />}function MenubarRadioItem({  className,  children,  inset,  ...props}: MenuPrimitive.RadioItem.Props & {  inset?: boolean}) {  return (    <MenuPrimitive.RadioItem      data-slot="menubar-radio-item"      data-inset={inset}      className={cn(        "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-1.5 pl-7 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",        className      )}      {...props}    >      <span className="pointer-events-none absolute left-1.5 flex size-4 items-center justify-center [&_svg:not([class*='size-'])]:size-4">        <MenuPrimitive.RadioItemIndicator>          <CheckIcon          />        </MenuPrimitive.RadioItemIndicator>      </span>      {children}    </MenuPrimitive.RadioItem>  )}function MenubarLabel({  className,  inset,  ...props}: React.ComponentProps<typeof DropdownMenuLabel> & {  inset?: boolean}) {  return (    <DropdownMenuLabel      data-slot="menubar-label"      data-inset={inset}      className={cn(        "px-1.5 py-1 text-sm font-medium data-inset:pl-7",        className      )}      {...props}    />  )}function MenubarSeparator({  className,  ...props}: React.ComponentProps<typeof DropdownMenuSeparator>) {  return (    <DropdownMenuSeparator      data-slot="menubar-separator"      className={cn("-mx-1 my-1 h-px bg-border", className)}      {...props}    />  )}function MenubarShortcut({  className,  ...props}: React.ComponentProps<typeof DropdownMenuShortcut>) {  return (    <DropdownMenuShortcut      data-slot="menubar-shortcut"      className={cn(        "ml-auto text-xs tracking-widest text-muted-foreground group-focus/menubar-item:text-accent-foreground",        className      )}      {...props}    />  )}function MenubarSub({  ...props}: React.ComponentProps<typeof DropdownMenuSub>) {  return <DropdownMenuSub data-slot="menubar-sub" {...props} />}function MenubarSubTrigger({  className,  inset,  ...props}: React.ComponentProps<typeof DropdownMenuSubTrigger> & {  inset?: boolean}) {  return (    <DropdownMenuSubTrigger      data-slot="menubar-sub-trigger"      data-inset={inset}      className={cn(        "gap-1.5 rounded-md px-1.5 py-1 text-sm focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-open:bg-accent data-open:text-accent-foreground [&_svg:not([class*='size-'])]:size-4",        className      )}      {...props}    />  )}function MenubarSubContent({  className,  ...props}: React.ComponentProps<typeof DropdownMenuSubContent>) {  return (    <DropdownMenuSubContent      data-slot="menubar-sub-content"      className={cn("min-w-32 rounded-lg bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className )}      {...props}    />  )}export {  Menubar,  MenubarPortal,  MenubarMenu,  MenubarTrigger,  MenubarContent,  MenubarGroup,  MenubarSeparator,  MenubarLabel,  MenubarItem,  MenubarShortcut,  MenubarCheckboxItem,  MenubarRadioGroup,  MenubarRadioItem,  MenubarSub,  MenubarSubTrigger,  MenubarSubContent,}