import type { Snippet } from 'svelte'; import type { HTMLAttributes } from 'svelte/elements'; import type { MintProp } from '../../mint/index.js'; import type { ButtonVariants, MenuVariants } from '../index.js'; import type { AnimationProps } from '../../utils/index.js'; import type { Placement } from '../../utils/floating.js'; import type { InteractiveTier } from '../../utils/tier-context.js'; import type { MenuSlots } from './menu.variants.js'; /** * Menu-specific props. The catalog JSDoc (`@description`/`@tag`/`@related`) * lives on `MenuProps` below — the interface docs-gen actually picks up — * so it is not duplicated here. * * @example Items array with `onSelect` callbacks * ```svelte * edit() }, * { label: 'Duplicate', onSelect: () => duplicate() }, * { type: 'section', label: 'Danger' }, * { label: 'Delete', onSelect: () => confirmDelete() } * ]} /> * ``` * * @example Declarative children with MenuItem * ```svelte * * * rename()}>Rename * duplicate()}>Duplicate * * confirmDelete()}>Delete * * ``` * * @example Selectable settings — `checked` renders `menuitemradio` rows, `detail` shows the current value * ```svelte * (sortBy = 'Name') }, * { label: 'Date', checked: sortBy === 'Date', onSelect: () => (sortBy = 'Date') } * ] * }, * { label: 'Refresh', onSelect: () => refresh() } * ]} /> * ``` * * @example Icon-only trigger via customTrigger * ```svelte * * {#snippet customTrigger(toggle, open)} * * {/snippet} * * ``` */ export interface MenuSpecificProps { /** Array of menu items. Each item's `onSelect` runs when activated. */ items?: TItem[]; /** Declarative children mode — use `` / `` / ``. */ children?: Snippet; /** * Remove the default variant classes. Only user-supplied classes apply. * @default false */ unstyled?: boolean; /** * Per-slot class overrides merged with the variant styles. * Slots: base | trigger | triggerText | chevron | content | header | section | * group | divider | items | item | indicator | detail | submenu | footer */ slotClasses?: Partial>; /** * Apply a named preset registered via ``. * Prefer this over `class` overrides when the requested look falls outside the * semantic intent palette — presets keep hover/active/dark-mode logic coherent * and make the custom look reusable across the project. */ preset?: string; /** * Placeholder text shown on the default trigger. Acts as the trigger's * accessible name unless `aria-label` is supplied. Typical values: "Actions", * "More", "Options". Ignored when `customTrigger` is provided. * @summary Text on the default trigger, which doubles as its accessible name. */ placeholder?: string; /** Optional mapping functions for custom item shapes. */ getItemLabel?: (item: TItem) => string; getItemId?: (item: TItem) => string; getItemDisabled?: (item: TItem) => boolean; getItemChildren?: (item: TItem) => TItem[] | undefined; /** Optional icon resolver for items in array mode. */ getItemIcon?: (item: TItem) => unknown; /** Optional per-item class resolver for items in array mode. */ getItemClass?: (item: TItem) => string | undefined; /** Optional checked-state resolver for items in array mode (`undefined` = plain action item). */ getItemChecked?: (item: TItem) => boolean | undefined; /** Optional right-aligned detail-text resolver for items in array mode. */ getItemDetail?: (item: TItem) => string | undefined; /** Section detection override. Applies to full union, not just TItem. */ isSection?: (item: MenuItemType) => boolean; /** Section label override. Accepts concrete section header type. */ getSectionLabel?: (item: MenuSectionHeader) => string; /** * Where the menu panel appears relative to the trigger. Uses floating-ui * placement. @default 'bottom-start' */ placement?: Placement; /** * Syncs the width of the menu panel with the trigger element. * @default true */ syncWidth?: boolean; /** * Render menu content in a portal for better positioning. * Prevents menu from being clipped by overflow containers. * @default true */ usePortal?: boolean; /** * Controls the open state of the menu. Supports `bind:open`. * @default false */ open?: boolean; /** * Fires when the menu opens or closes from user interaction (trigger * click, item activation, Escape, Tab-out, outside click). Receives the * new open state. Not called when the consumer writes `bind:open` directly. */ onOpenChange?: (open: boolean) => void; /** * Button variant applied to the default trigger button. * @default 'outlined' */ variant?: ButtonVariants['variant']; /** * Button size applied to the default trigger button. * @default 'md' */ size?: ButtonVariants['size']; /** * Size of the menu list items, independent from the trigger size. * When not set, item size is derived from the trigger `size` prop. * @default undefined */ itemSize?: 'sm' | 'md' | 'lg'; /** * Button intent applied to the default trigger button. * @default 'neutral' */ intent?: ButtonVariants['intent']; /** * Semantic radius tier applied to the default trigger button. Menu is an * Action surface, so the default is `commit` (pill) to match the Action * family — consistent with `