Bỏ qua tới nội dung
Component / 017 / NEXOFRAME

Dropdown menu

Mẫu chuẩn

Menu hành động, checklist cột, và radio cho một bộ lọc. Ô trong biểu mẫu vẫn là Select.

Radix DropdownMenuKhông variantKhông sizeLight & dark

Playground

Menu được portal ra ngoài vùng brand, nên panel theo theme của trang, không theo brand đang chọn trong playground.

LIVE PREVIEW
Chưa chọn mục nào
TSX
import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "@nexobox/ui";

<DropdownMenu>
  <DropdownMenuTrigger asChild>
    <Button>Hành động</Button>
  </DropdownMenuTrigger>
  <DropdownMenuContent align="start" side="bottom">
    <DropdownMenuLabel>Hàng 128</DropdownMenuLabel>
    <DropdownMenuGroup>
      <DropdownMenuItem onSelect={() => {}}>Sửa</DropdownMenuItem>
      <DropdownMenuItem onSelect={() => {}}>Nhân bản</DropdownMenuItem>
    </DropdownMenuGroup>
    <DropdownMenuSeparator />
    <DropdownMenuItem onSelect={() => {}}>Xuất</DropdownMenuItem>
    <DropdownMenuItem disabled>Xoá</DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>

Khi nào sử dụng

Nên dùng

Một nhóm hành động neo vào một nút: sửa, nhân bản, xuất, xoá trên một hàng; menu tài khoản.

Tránh dùng

Chọn một giá trị để gửi kèm biểu mẫu — đó là Select, không phải dropdown menu. Nội dung tự do hay một form nhỏ thì dùng Popover. Không dùng làm điều hướng chính. Menu chuột phải và menu ứng dụng: chưa có.

Anatomy

Root giữ trạng thái mở/đóng. Trigger thường asChild bọc một Button. Content portal ra document.body, lớp --nf-foundation-layer-dropdown. Item là một hành động, Label là nhãn nhóm không tương tác, Separator chia hai nhóm, Group gom nhiều Item không tự render viền.

Variants

Không có variant, không có size. Các phần dưới đây chỉ hiển thị khi menu đang mở, vì DropdownMenuContent portal ra document.body — bảng này liệt kê từng phần ở trạng thái tĩnh thay vì mở một menu thật trong khung xem trước.

PhầnTrạng tháiGhi chú
ItemMặc địnhNền trong suốt, chữ --nf-semantic-text-primary. Cao --nf-component-menu-item-height: 36 px comfortable, 32 px compact, 44 px con trỏ thô.
ItemHighlightedNền --nf-component-menu-item-hover khi được rê hoặc điều hướng bàn phím tới, qua data-[highlighted]
ItemPressedNền --nf-component-menu-item-pressed, giữ chuột xuống. Không co scale — DS-018 rút press-scale khỏi mọi primitive.
ItemFocus-visibleKhông có. data-[highlighted] là chỉ báo duy nhất — ring cộng nền highlighted đọc như hai con trỏ cùng lúc. Miễn trừ có tên trong A36, không phải khiếm khuyết.
ItemDisabledCon trỏ not-allowed, chữ --nf-component-button-disabled-foreground
LabelMặc địnhChữ --nf-semantic-text-muted, không tương tác
SeparatorMặc địnhĐường kẻ --nf-semantic-border-subtle
GroupHai mụcKhông tự render viền hay khoảng cách riêng — chỉ để gom Item cho screen reader

Checkbox giữ menu mở. Radio đóng menu. Không có submenu. Không có loading, error, empty.

Design tokens

Content đọc --nf-semantic-surface-raised, --nf-component-menu-radius, --nf-component-menu-padding, --nf-component-overlay-shadow, --nf-motion-menu-in. Item đọc --nf-component-menu-item-height, -item-hover, -item-pressed, -item-padding-inline, -item-gap, --nf-component-field-radius. Label đọc --nf-semantic-text-muted. Nhóm token --nf-component-menu-* giờ đã có — item rời thang hàng bảng cũ (48 px) và neo vào chiều cao riêng của menu; không có --nf-component-dropdown-* vì Content dùng chung nhóm menu với Select và Combobox.

API & triển khai

PropMặc địnhQuy ước
open / onOpenChange—Trên Root. Chế độ controlled.
modaltrueCủa Radix, trên Root.
asChildfalseTrên Trigger, thường bọc Button.
align / side / sideOffsetstart / bottom / 8Trên Content.
disabledfalseTrên Item. Mục không chạy được.
onSelect—Trên Item. preventDefault() để giữ menu mở.

Accessibility & nội dung

Enter, Space hoặc mũi tên xuống trên trigger mở menu và đưa tiêu điểm vào mục đầu.
Gõ chữ nhảy tới mục khớp (typeahead). Mũi tên lên/xuống di chuyển tiêu điểm.
Escape đóng menu và trả tiêu điểm về trigger. Tiêu điểm bị giam trong menu khi mở.
Mỗi Item cần tên truy cập là chữ thật — một mục chỉ có icon không có tên truy cập.