Skip to content

Menu options

This component provides a container for grouping menu items that behave like options, allowing only one to be selected at a time. Its layout can be adjusted based on the isHorizontal prop. When set to horizontal, it applies a specific style; otherwise, it defaults to a vertical layout.

Selection is tracked by identity rather than position: each item is matched on its vnode :key when it has one, falling back to its index for keyless static lists. Give items an explicit :key so the selection survives conditional or reordered items.

Props

model-value: string | number
Identifies the highlighted or selected option. Matches the option's vnode key (:key) when present, falling back to its position for keyless static lists.

is-horizontal?: boolean
Indicates that the items should flow horizontally.

is-persistent?: boolean
Keeps the surrounding menu open after an option is clicked. Defaults to true, since options menus are meant to stay open while selecting. Set to false to close the menu on selection.
Default: true

mode?: "highlight" | "select"
The active mode of the option.
Default: highlight

Emits

update:model-value: [string, number]
Triggered when the active option changes. Emits the option's vnode key when it has one, otherwise its index.

Slots

default
The content of the options group.

Examples

Alignment

Horizontal option menus can be used to allow users to select an alignment.

Result = left

<template>
    <FluxFlex
        direction="vertical"
        :gap="12">
        <FluxPane style="width: 270px">
            <FluxMenu>
                <FluxMenuOptions
                    v-model="alignment"
                    is-horizontal>
                    <FluxMenuItem icon-leading="align-left"/>
                    <FluxMenuItem icon-leading="align-center"/>
                    <FluxMenuItem icon-leading="align-right"/>
                    <FluxMenuItem icon-leading="align-justify"/>
                </FluxMenuOptions>
            </FluxMenu>
        </FluxPane>

        <small><kbd>Result = {{ ALIGNMENTS[alignment] }}</kbd></small>
    </FluxFlex>
</template>

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

    const ALIGNMENTS = {
        0: 'left',
        1: 'center',
        2: 'right',
        3: 'justify'
    } as const;

    const alignment = ref<keyof typeof ALIGNMENTS>(0);
</script>

Option

Vertical option menus can be used to allow the user to switch between different view modes.

Result = list

<template>
    <FluxFlex
        direction="vertical"
        :gap="12">
        <FluxPane style="width: 270px">
            <FluxMenu>
                <FluxMenuOptions
                    v-model="view"
                    mode="select">
                    <FluxMenuItem
                        key="list"
                        icon-leading="list"
                        label="List"/>

                    <FluxMenuItem
                        key="grid"
                        icon-leading="grid-2"
                        label="Grid"/>
                </FluxMenuOptions>
            </FluxMenu>
        </FluxPane>

        <small><kbd>Result = {{ view }}</kbd></small>
    </FluxFlex>
</template>

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

    const view = ref<'list' | 'grid'>('list');
</script>

Inside a flyout

Option menus stay open while selecting, even inside a flyout. Pass :is-persistent="false" if you want the menu to close on selection instead.

Selecting an option keeps the menu open

<template>
    <FluxFlex
        direction="vertical"
        :gap="12">
        <FluxFlyout>
            <template #opener="{ open }">
                <FluxSecondaryButton
                    icon-trailing="angle-down"
                    :label="`View: ${VIEWS[view]}`"
                    @click="open()"/>
            </template>

            <FluxMenu style="width: 200px">
                <FluxMenuOptions
                    v-model="view"
                    mode="select">
                    <FluxMenuItem
                        icon-leading="list"
                        label="List"/>

                    <FluxMenuItem
                        icon-leading="grid-2"
                        label="Grid"/>

                    <FluxMenuItem
                        icon-leading="image"
                        label="Gallery"/>
                </FluxMenuOptions>
            </FluxMenu>
        </FluxFlyout>

        <small><kbd>Selecting an option keeps the menu open</kbd></small>
    </FluxFlex>
</template>

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

    const VIEWS = ['List', 'Grid', 'Gallery'];

    const view = ref(0);
</script>

Used components