# Menu ## Basic example Menus are built using a combination of the `Menu`, `MenuButton`, `MenuItems`, and `MenuItem` components: ```svelte More Account settings Documentation Invite a friend (coming soon!) ``` ## Styling [See here](general-concepts#component-styling) for some general notes on styling the components in this library. ### Active item To style the active `MenuItem`, you can use the `active` slot prop that it provides, which tells you whether or not that menu item is currently focused via the mouse or keyboard. You can use this state to conditionally apply whatever active/focus styles you wish. ```svelte More Account settings ``` If necessary, you can also style the `MenuItem` itself by passing a function to `class`: ```svelte More (active ? "active" : "inactive")}> Account settings ``` ## Showing/hiding the menu By default, the `MenuItems` instance will be shown and hidden automatically based on the internal `open` state tracked by the `Menu` component itself. If you'd rather handle this yourself (perhaps because you need to add an extra wrapper element for one reason or another), you can add a `static` prop to the `MenuItems` component to tell it to always render, and use the `open` slot prop provided by the `Menu` to show or hide the menu yourself. ```svelte More {#if open} {/if} ``` You can also choose to have the `Menu` merely hide the `MenuItems` when the `Menu` is closed, instead of removing it from the DOM entirely, by using the `unmount` prop. This may be useful for performance reasons if rendering the `MenuItems` is expensive. ```svelte More ``` ## Disabling an item Use the `disabled` prop to disable a `MenuItem`. This will make it unselectable via keyboard navigation, and it will be skipped when pressing the up/down arrows. ```svelte More Invite a friend (coming soon!) ``` ## Transitions To animate the opening and closing of the menu, you can use [this library's Transition component](/docs/latest/transition) or Svelte's built-in transition engine. See that page for a comparison. ### Using the `Transition` component To use the `Transition` component, all you need to do is wrap the `MenuItems` in a ``, and the transition will be applied automatically. ```svelte More ``` The components in this library communicate with each other, so the Transition will be managed automatically when the Menu is opened/closed. If you require more control over this behavior, you may use a more explicit version: ```svelte More ``` ### Using Svelte transitions The last example above also provides a blueprint for using Svelte transitions: ```svelte More {#if open}
{/if}
``` Make sure to use the `static` prop, or else the exit transitions won't work correctly. ## Rendering additional content The accessibility semantics of role="menu" are fairly strict, and any children of a Menu besides MenuItem components will be automatically hidden from assistive technology to make sure the menu works the way screen reader users expect. For this reason, rendering any children other than MenuItem components is discouraged, as that content will be inaccessible to people using assistive technology. If you want to build a dropdown with more flexible content, consider using Popover instead. ## When to use a `Menu` Menus are best for UI elements that resemble things like the menus you'd find in the title bar of most operating systems. They have specific accessibility semantics, and their content should be restricted to a list of links or buttons. Focus is trapped in an open menu, so you cannot tab through the content or away from the menu. Instead, the arrow keys navigate through a `Menu`'s items. Here's when you might use other similar components from Headless UI: - Popover: Popovers are general-purpose floating menus. They appear near the button that triggers them, and you can put arbitrary markup in them like images or non-clickable content. The Tab key navigates the contents of a Popover like it would any other normal markup. They're great for building header nav items with expandable content and flyout panels. - Disclosure: Disclosures are useful for elements that expand to reveal additional information, like a toggleable FAQ section. They are typically rendered inline and reflow the document when they're shown or hidden. - Dialog: Dialogs are meant to grab the user's full attention. They typically render a floating panel in the center of the screen, and use a backdrop to dim the rest of the application's contents. They also capture focus and prevent tabbing away from the Dialog's contents until the Dialog is dismissed. ## Accessibility notes ### Focus management Clicking the `MenuButton` toggles the menu and focuses the `MenuItems` component. Focus is trapped within the open menu until Escape is pressed or the user clicks outside the menu. Closing the menu returns focus to the `MenuButton`. ### Mouse interaction Clicking a `MenuButton` toggles the menu. Clicking anywhere outside of an open menu will close that menu. ### Keyboard interaction | Command | Description | | -------------------------------------------------------- | --------------------------------------------------- | | `` / `` when `MenuButton` is focused | Opens menu and focuses first non-disabled item | | `` / `` when `MenuButton` is focused | Opens menu and focuses first/last non-disabled item | | `` when menu is open | Closes any open Menus | | `` / `` when menu is open | Focuses next/previous non-disabled item | | `` / `` when menu is open | Focuses first/last non-disabled item | | `` / `` when menu is open | Activates/clicks the current menu item | | `` when menu is open | Focuses next item that matches keyboard input | ### Other All relevant ARIA attributes are automatically managed. For a full reference on all accessibility features implemented in `Menu`, see the ARIA spec on Menus. ## Component API ### Menu | Prop | Default | Type | Description | | ---- | ------- | -------- | --------------------------------------- | | `as` | `div` | `string` | The element the `Menu` should render as | | Slot prop | Type | Description | | --------- | --------- | ------------------------------- | | `open` | `boolean` | Whether or not the menu is open | ### MenuButton | Prop | Default | Type | Description | | ---- | -------- | -------- | --------------------------------------------- | | `as` | `button` | `string` | The element the `MenuButton` should render as | | Slot prop | Type | Description | | --------- | --------- | ------------------------------- | | `open` | `boolean` | Whether or not the menu is open | ### MenuItems | Prop | Default | Type | Description | | --------- | ------- | --------- | ----------------------------------------------------------------------------------------------- | | `as` | `div` | `string` | The element the `MenuItems` should render as | | `static` | `false` | `boolean` | Whether the element should ignore the internally managed open/closed state | | `unmount` | `true` | `boolean` | Whether the element should be unmounted, instead of just hidden, based on the open/closed state | Note that `static` and `unmount` cannot be used together. | Slot prop | Type | Description | | --------- | --------- | ------------------------------- | | `open` | `boolean` | Whether or not the menu is open | ### MenuItem | Prop | Default | Type | Description | | ---------- | ------- | --------- | ----------------------------------------------------------------------------- | | `as` | `a` | `string` | The element the `MenuItem` should render as | | `disabled` | `false` | `boolean` | Whether the item should be disabled for keyboard navigation and ARIA purposes | | Slot prop | Type | Description | | ---------- | --------- | ---------------------------------------------------------------------- | | `active` | `boolean` | Whether the option is active (using the mouse or keyboard) | | `disabled` | `boolean` | Whether the item is disabled for keyboard navigation and ARIA purposes |