Skip to content

Menu item

This component is designed to be a flexible menu item that fits into a navigation or action menu. It leverages the properties of buttons and can display icons, images, and commands to suit various needs.

You can customize it with different states like active, selected, or highlighted, and it's capable of handling click events. Its versatility makes it easy to integrate into any menu structure, enhancing the user experience with well-defined actions and options.

Props

type?: "button" | "link" | "route" | "none"
The type of menu item.
Default: button

disabled?: boolean
Disable the menu item.

icon-leading?: FluxIconName
The icon at the start of the menu item.

icon-trailing?: FluxIconName
The icon at the end of the menu item.

is-loading?: boolean
Shows a loading state within the menu item instead of the icon at the start.

label?: string
The label that is shown in the menu item.

command?: string
The label of the menu item command.

command-icon?: FluxIconName
The icon of the menu item command.

command-loading?: boolean
Enables the loading state of the command.

image-src?: string
An image that shows instead of the before icon.

image-alt?: string
An accessible label for the image.

is-active?: boolean
Indicates that the menu item is active.

is-destructive?: boolean
Indicates that the menu item is a destructive action.

is-highlighted?: boolean
Indicates that the menu item is highlighted.

is-indented?: boolean
Indicates that the menu item is indented (e.g. in a sub-menu structure).

is-persistent?: boolean
Keeps the surrounding menu (context menu or flyout) open when this item is clicked, instead of closing it. By default a menu item closes the menu on click.

is-selectable?: boolean
Indicates that the menu item is selectable.

is-selected?: boolean
Indicates that the menu item is selected. Only works if is-selectable is also enabled.

tabindex?: string | number
The tabindex of the menu item, works exactly the same as html.

href?: string
This prop is enabled if the menu item's type is set to link. It's the same as the <a> HTML element.

rel?: string
This prop is enabled if the menu item's type is set to link. It's the same as the <a> HTML element.

target?: string
This prop is enabled if the menu item's type is set to link. It's the same as the <a> HTML element.

to?: FluxTo
This prop is enabled if the menu item's type is set to route. This integrates with Vue Router.

Emits

click: [MouseEvent]
Triggered when the menu item is clicked.

mouseenter: [MouseEvent]
Triggered when the menu item is being hovered.

mouseleave: [MouseEvent]
Triggered when the menu item is not being hovered anymore.

Slots

before
Custom content shown before the label, replacing the leading icon.

after
Custom content shown after the label, alongside the optional command label.

Examples

Basic

A simple menu item with an icon.

<template>
    <FluxPane style="width: 300px">
        <FluxMenu>
            <FluxMenuGroup>
                <FluxMenuItem
                    icon-leading="heart"
                    label="My liked videos"/>

                <FluxMenuItem
                    icon-leading="arrow-up-from-square"
                    label="My uploads"/>
            </FluxMenuGroup>
        </FluxMenu>
    </FluxPane>
</template>

<script
    lang="ts"
    setup>
    import { FluxMenu, FluxMenuGroup, FluxMenuItem, FluxPane } from '@flux-ui/components';
</script>

Selectable

Menu items can be selectable, mostly used within groups.

<template>
    <FluxPane style="width: 300px">
        <FluxMenu>
            <FluxMenuGroup>
                <template v-for="i of 3">
                    <FluxMenuItem
                        :is-selected="selected === i"
                        is-selectable
                        :label="`Item ${i}`"
                        @click="selected = i"/>
                </template>
            </FluxMenuGroup>
        </FluxMenu>
    </FluxPane>
</template>

<script
    lang="ts"
    setup>
    import { FluxMenu, FluxMenuGroup, FluxMenuItem, FluxPane } from '@flux-ui/components';
    import { ref } from 'vue';

    const selected = ref(1);
</script>

Persistent

Mark items with is-persistent to keep the surrounding menu open on click, useful for toggles and multi-select actions. Items without it (like Done) still close the menu.

<template>
    <FluxFlyout>
        <template #opener="{ open }">
            <FluxSecondaryButton
                icon-leading="filter"
                :label="active.length ? `Filters (${active.length})` : 'Filters'"
                @click="open()"/>
        </template>

        <FluxMenu style="width: 220px">
            <FluxMenuGroup>
                <template v-for="filter of FILTERS">
                    <FluxMenuItem
                        is-persistent
                        is-selectable
                        :is-selected="active.includes(filter)"
                        :label="filter"
                        @click="toggle(filter)"/>
                </template>
            </FluxMenuGroup>

            <FluxSeparator/>

            <FluxMenuGroup>
                <FluxMenuItem
                    icon-leading="check"
                    label="Done"/>
            </FluxMenuGroup>
        </FluxMenu>
    </FluxFlyout>
</template>

<script
    lang="ts"
    setup>
    import { FluxFlyout, FluxMenu, FluxMenuGroup, FluxMenuItem, FluxSecondaryButton, FluxSeparator } from '@flux-ui/components';
    import { ref } from 'vue';

    const FILTERS = ['In stock', 'On sale', 'Featured'];

    const active = ref<string[]>([]);

    function toggle(filter: string): void {
        if (active.value.includes(filter)) {
            active.value = active.value.filter(value => value !== filter);
        } else {
            active.value = [...active.value, filter];
        }
    }
</script>

Keybind

Each menu item can have a keybind (command).

<template>
    <FluxPane style="width: 300px">
        <FluxMenu>
            <FluxMenuGroup>
                <FluxMenuItem
                    command="⌘C"
                    icon-leading="clone"
                    label="Copy"/>

                <FluxMenuItem
                    command="⌘V"
                    icon-leading="clipboard"
                    label="Paste"/>
            </FluxMenuGroup>
        </FluxMenu>
    </FluxPane>
</template>

<script
    lang="ts"
    setup>
    import { FluxMenu, FluxMenuGroup, FluxMenuItem, FluxPane } from '@flux-ui/components';
</script>

A menu item can also just contain an icon at the end.

<template>
    <FluxPane style="width: 300px">
        <FluxMenu>
            <FluxMenuGroup>
                <FluxMenuItem
                    icon-leading="arrow-up-from-square"
                    icon-trailing="angle-right"
                    label="My uploads"/>
            </FluxMenuGroup>
        </FluxMenu>
    </FluxPane>
</template>

<script
    lang="ts"
    setup>
    import { FluxMenu, FluxMenuGroup, FluxMenuItem, FluxPane } from '@flux-ui/components';
</script>

Spinner

Loading states can also be applied to menu items to indicate that something is loading.

<template>
    <FluxPane style="width: 300px">
        <FluxMenu>
            <FluxMenuGroup>
                <FluxMenuItem
                    command-icon="angle-right"
                    icon-leading="heart"
                    label="My liked videos"/>

                <FluxMenuItem
                    command="42%"
                    command-icon="angle-right"
                    icon-leading="arrow-up-from-square"
                    is-loading
                    label="My uploads"/>

                <FluxMenuItem
                    command-loading
                    icon-leading="arrow-up-from-square"
                    label="My uploads"/>
            </FluxMenuGroup>
        </FluxMenu>
    </FluxPane>
</template>

<script
    lang="ts"
    setup>
    import { FluxMenu, FluxMenuGroup, FluxMenuItem, FluxPane } from '@flux-ui/components';
</script>

Used components