// Copyright (c) Meta Platforms, Inc. and affiliates. 'use client'; /** * @file MoreMenu.tsx * @input Uses DropdownMenu, getIcon * @output Exports MoreMenu component and MoreMenuProps type * @position Core implementation; consumed by index.ts * * Overflow menu with a three-dot icon trigger. A thin wrapper around * DropdownMenu with icon-only button defaults. * * SYNC: When modified, update these files to stay in sync: * - /packages/core/src/MoreMenu/MoreMenu.test.tsx * - /packages/core/src/MoreMenu/index.ts * - /apps/storybook/stories/MoreMenu.stories.tsx * - /packages/cli/assets/templates/blocks/components/MoreMenu/ (showcase blocks) */ import type { ReactNode } from 'react'; import { useIcon } from "../Icon/index.js"; import { DropdownMenu } from "../DropdownMenu/DropdownMenu.js"; import { useSize } from "../SizeContext/SizeContext.js"; import type { DropdownMenuOption, DropdownMenuPresentation } from "../DropdownMenu/index.js"; import type { LayerAlignment, LayerPlacement } from "../Layer/index.js"; import type { ButtonVariant, ButtonSize } from "../Button/index.js"; import type { BaseProps } from "../BaseProps.js"; import { stableClassName } from "../naming.js"; import { useTranslator } from "../i18n/index.js"; export interface MoreMenuProps extends Pick { /** Ref forwarded to the trigger button */ ref?: React.Ref; /** * Menu items \u2014 data array of actions, dividers, and sections. * Same type as DropdownMenu's `items` prop. */ items: DropdownMenuOption[]; /** * Accessible label for the trigger button. * Always used as aria-label (the button is always icon-only). * @default 'More options' */ label?: string; /** * Visual style variant of the trigger button. * @default 'ghost' */ variant?: ButtonVariant; /** * Size of the trigger button. * @default 'md' */ size?: ButtonSize; /** * Override the default three-dot icon. * @default Three horizontal dots from the icon registry ('moreHorizontal') */ icon?: ReactNode; /** * Whether the menu trigger is disabled. * @default false */ isDisabled?: boolean; /** * Position of the menu relative to the trigger button. * Forwarded to DropdownMenu, which owns the default. * @default 'below' */ placement?: LayerPlacement; /** * Alignment of the menu along the placement axis. * Forwarded to DropdownMenu, which owns the default. * @default 'start' */ alignment?: LayerAlignment; /** * Menu presentation policy. `adaptive` uses a BottomSheet on compact * coarse-pointer viewports and an anchored popover elsewhere. * @default 'popover' */ presentation?: DropdownMenuPresentation; /** * Controlled open state for the menu. */ isMenuOpen?: boolean; /** * Callback fired when the menu visibility changes. */ onOpenChange?: (isOpen: boolean) => void; /** Test ID for testing frameworks. */ 'data-testid'?: string; } /** * Overflow menu with a three-dot icon trigger. * * A convenience wrapper around DropdownMenu with icon-only button defaults. * * @example * ``` * * ``` */ export function MoreMenu({ items, label: labelFromProps, variant = 'ghost', size: sizeProp, icon, isDisabled = false, placement, alignment, presentation, isMenuOpen, onOpenChange, xstyle, className: classNameProp, style, 'data-testid': testId, ref }: MoreMenuProps) { const t = useTranslator(); const label = labelFromProps ?? t('@astryx.moreMenu.label'); const size = useSize(sizeProp, 'md'); const moreIcon = useIcon('moreHorizontal'); return ; } MoreMenu.displayName = 'MoreMenu';