Skip to content

Menu flyout

A menu item that opens a submenu in a flyout next to it, rather than expanding inline like a Collapsible. Use it inside any Menu — a Context menu, a dropdown, or a plain menu in a pane. Submenus may be nested arbitrarily deep.

The flyout opens on hover and on ArrowRight, Enter or click, and keeps itself within the browser window: when there is no room on the chosen side it flips to the opposite side and is clamped to the viewport.

A prediction cone keeps the submenu open while the pointer moves diagonally towards it, even when the cursor briefly passes over a sibling item — so reaching a submenu no longer requires a perfectly straight path. A matching return cone does the same on the way back, so heading from the submenu to its opener does not drop the submenu or activate the items in between. The cone can be visualised for debugging with the debug-cone prop on the surrounding Context menu or Menu.

Prediction cone

Required icons

angle-right

Props

disabled?: boolean
Disable the flyout trigger.

icon?: FluxIconName
An optional leading icon shown on the trigger.

is-active?: boolean
Renders the trigger in its active state.

is-destructive?: boolean
Renders the trigger in its destructive state.

label?: string
The label of the trigger.

position?: "right-top" | "left-top" | "…"
The side the submenu opens to. When there is no room it flips to the opposite side and is clamped to the viewport.
Default: right-top

Slots

default
The submenu content. Place a Menu with items (or more flyouts) here.

trigger
Replaces the trigger label with custom content.

Examples

Basic

A menu item that opens a submenu on hover or with the keyboard.

Prediction cone

<template>
    <div style="display: flex; flex-flow: column; gap: 15px">
        <div style="display: flex; align-items: center; gap: 9px">
            <FluxToggle
                v-model="showCone"/>

            Prediction cone
        </div>

        <FluxPane style="width: 300px">
            <FluxMenu :debug-cone="showCone">
                <FluxMenuGroup>
                    <FluxMenuItem
                        icon-leading="plus"
                        label="New file"/>

                    <FluxMenuFlyout
                        icon="arrow-up-from-square"
                        label="Export as">
                        <FluxMenu>
                            <FluxMenuGroup>
                                <FluxMenuItem label="PDF"/>

                                <FluxMenuItem label="PNG"/>

                                <FluxMenuItem label="SVG"/>
                            </FluxMenuGroup>
                        </FluxMenu>
                    </FluxMenuFlyout>
                </FluxMenuGroup>
            </FluxMenu>
        </FluxPane>
    </div>
</template>

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

    const showCone = ref(false);
</script>

Nested

A submenu inside a submenu. There is no depth limit.

Prediction cone

<template>
    <div style="display: flex; flex-flow: column; gap: 15px">
        <div style="display: flex; align-items: center; gap: 9px">
            <FluxToggle
                v-model="showCone"/>

            Prediction cone
        </div>

        <FluxPane style="width: 300px">
            <FluxMenu :debug-cone="showCone">
                <FluxMenuGroup>
                    <FluxMenuItem
                        icon-leading="pen"
                        label="Edit"/>

                    <FluxMenuFlyout
                        icon="arrow-up-from-square"
                        label="Share">
                        <FluxMenu>
                            <FluxMenuGroup>
                                <FluxMenuItem
                                    icon-leading="paper-plane"
                                    label="Email"/>

                                <FluxMenuFlyout
                                    icon="users"
                                    label="Social">
                                    <FluxMenu>
                                        <FluxMenuGroup>
                                            <FluxMenuItem label="Mastodon"/>

                                            <FluxMenuItem label="Bluesky"/>

                                            <FluxMenuItem label="LinkedIn"/>
                                        </FluxMenuGroup>
                                    </FluxMenu>
                                </FluxMenuFlyout>

                                <FluxMenuItem
                                    icon-leading="copy"
                                    label="Copy link"/>
                            </FluxMenuGroup>
                        </FluxMenu>
                    </FluxMenuFlyout>
                </FluxMenuGroup>
            </FluxMenu>
        </FluxPane>
    </div>
</template>

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

    const showCone = ref(false);
</script>

Stacked

Several submenu openers under each other, like a Format menu in an editor.

Prediction cone

<template>
    <div style="display: flex; flex-flow: column; gap: 15px">
        <div style="display: flex; align-items: center; gap: 9px">
            <FluxToggle
                v-model="showCone"/>

            Prediction cone
        </div>

        <FluxPane style="width: 320px">
            <FluxMenu :debug-cone="showCone">
                <FluxMenuGroup>
                    <FluxMenuFlyout
                        icon="align-left"
                        label="Align">
                        <FluxMenu>
                            <FluxMenuGroup>
                                <FluxMenuItem
                                    icon-leading="align-left"
                                    label="Left"/>

                                <FluxMenuItem
                                    icon-leading="align-center"
                                    label="Center"/>

                                <FluxMenuItem
                                    icon-leading="align-right"
                                    label="Right"/>

                                <FluxMenuItem
                                    icon-leading="align-justify"
                                    label="Justify"/>
                            </FluxMenuGroup>
                        </FluxMenu>
                    </FluxMenuFlyout>

                    <FluxMenuFlyout
                        icon="list-ul"
                        label="List">
                        <FluxMenu>
                            <FluxMenuGroup>
                                <FluxMenuItem
                                    icon-leading="list-ul"
                                    label="Bulleted"/>

                                <FluxMenuItem
                                    icon-leading="list-ol"
                                    label="Numbered"/>
                            </FluxMenuGroup>
                        </FluxMenu>
                    </FluxMenuFlyout>

                    <FluxMenuFlyout
                        icon="indent"
                        label="Indentation">
                        <FluxMenu>
                            <FluxMenuGroup>
                                <FluxMenuItem
                                    icon-leading="indent"
                                    label="Increase"/>

                                <FluxMenuItem
                                    icon-leading="outdent"
                                    label="Decrease"/>
                            </FluxMenuGroup>
                        </FluxMenu>
                    </FluxMenuFlyout>

                    <FluxMenuFlyout
                        icon="image"
                        label="Insert">
                        <FluxMenu>
                            <FluxMenuGroup>
                                <FluxMenuItem
                                    icon-leading="image"
                                    label="Image"/>

                                <FluxMenuItem
                                    icon-leading="play"
                                    label="Video"/>
                            </FluxMenuGroup>
                        </FluxMenu>
                    </FluxMenuFlyout>
                </FluxMenuGroup>
            </FluxMenu>
        </FluxPane>
    </div>
</template>

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

    const showCone = ref(false);
</script>

Used components