Menu pane
A container that lets you drop a full interactive component — a Color picker, a slider or a small form — into a Menu, a Menu flyout submenu or a Context menu.
A plain Menu runs a roving focus zone: arrow keys move between its items and only one item sits in the tab order at a time. Wrapping custom content in a Menu pane opts that subtree out of the focus zone, so the embedded component keeps its own keyboard behaviour — arrow keys drive its sliders and steppers and Tab reaches every control. Arrow navigation across the surrounding menu items simply skips over the pane; reach it with Tab.
Clicking inside a pane never closes the menu, so the embedded component stays usable while the menu is open.
Slots
default
The custom content to embed in the menu, such as a color picker, slider or small form.
Examples
Color picker
Embed a full color picker in a menu flyout submenu. Drag the saturation field, use the sliders and type into the inputs without the menu interfering.
<template>
<FluxPane style="width: 240px">
<FluxMenu>
<FluxMenuGroup>
<FluxMenuItem
icon-leading="bold"
label="Bold"/>
<FluxMenuItem
icon-leading="italic"
label="Italic"/>
<FluxMenuFlyout
icon="palette"
label="Text color">
<FluxMenu>
<FluxMenuPane>
<FluxColorPicker v-model="color"/>
</FluxMenuPane>
</FluxMenu>
</FluxMenuFlyout>
</FluxMenuGroup>
</FluxMenu>
</FluxPane>
</template>
<script
lang="ts"
setup>
import { FluxColorPicker, FluxMenu, FluxMenuFlyout, FluxMenuGroup, FluxMenuItem, FluxMenuPane, FluxPane } from '@flux-ui/components';
import { ref } from 'vue';
const color = ref('#22c55e');
</script>Slider
A single control such as a slider. Focus it with `Tab`, then the arrow keys adjust the value instead of moving between menu items.
<template>
<FluxPane style="width: 240px">
<FluxMenu>
<FluxMenuGroup>
<FluxMenuItem
icon-leading="moon"
label="Night shift"/>
<FluxMenuFlyout
icon="sun"
label="Brightness">
<FluxMenu>
<FluxMenuPane>
<FluxFormSlider
v-model="brightness"
aria-label="Brightness"
is-ticks-visible/>
</FluxMenuPane>
</FluxMenu>
</FluxMenuFlyout>
</FluxMenuGroup>
</FluxMenu>
</FluxPane>
</template>
<script
lang="ts"
setup>
import { FluxFormSlider, FluxMenu, FluxMenuFlyout, FluxMenuGroup, FluxMenuItem, FluxMenuPane, FluxPane } from '@flux-ui/components';
import { ref } from 'vue';
const brightness = ref(60);
</script>Range slider
A two-thumb range. Each thumb is its own focus stop and the arrow keys move it without disturbing the menu.
<template>
<FluxPane style="width: 240px">
<FluxMenu>
<FluxMenuGroup>
<FluxMenuItem
icon-leading="arrow-down-a-z"
label="Sort"/>
<FluxMenuFlyout
icon="money-bill"
label="Price range">
<FluxMenu>
<FluxMenuPane>
<FluxFormRangeSlider
v-model="price"
is-ticks-visible
:max="1000"
:min="0"
:step="50"/>
</FluxMenuPane>
</FluxMenu>
</FluxMenuFlyout>
</FluxMenuGroup>
</FluxMenu>
</FluxPane>
</template>
<script
lang="ts"
setup>
import { FluxFormRangeSlider, FluxMenu, FluxMenuFlyout, FluxMenuGroup, FluxMenuItem, FluxMenuPane, FluxPane } from '@flux-ui/components';
import { ref } from 'vue';
const price = ref<[number, number]>([200, 800]);
</script>Text area
A multi-line input. Typing, Enter and the arrow keys for the caret all stay inside the field.
<template>
<FluxPane style="width: 240px">
<FluxMenu>
<FluxMenuGroup>
<FluxMenuItem
icon-leading="star"
label="Add to favorites"/>
<FluxMenuFlyout
icon="message"
label="Add note">
<FluxMenu>
<FluxMenuPane>
<FluxFormTextArea
v-model="note"
placeholder="Write a note..."
:rows="3"/>
</FluxMenuPane>
</FluxMenu>
</FluxMenuFlyout>
</FluxMenuGroup>
</FluxMenu>
</FluxPane>
</template>
<script
lang="ts"
setup>
import { FluxFormTextArea, FluxMenu, FluxMenuFlyout, FluxMenuGroup, FluxMenuItem, FluxMenuPane, FluxPane } from '@flux-ui/components';
import { ref } from 'vue';
const note = ref('');
</script>Filter
A search field that filters the items below it. Typing — including the arrow keys for the caret — stays inside the input.
<template>
<FluxPane style="width: 240px">
<FluxMenu>
<FluxMenuGroup>
<FluxMenuItem
icon-leading="plus"
label="New file"/>
<FluxMenuFlyout
icon="filter"
label="Actions">
<FluxMenu>
<FluxMenuPane>
<FluxFormInput
v-model="query"
type="search"
icon-leading="magnifying-glass"
placeholder="Filter actions..."/>
</FluxMenuPane>
<FluxMenuGroup>
<FluxMenuItem
v-for="action of filtered"
:key="action.label"
:icon-leading="action.icon"
:label="action.label"/>
<FluxMenuSubHeader
v-if="filtered.length === 0"
label="No matches"/>
</FluxMenuGroup>
</FluxMenu>
</FluxMenuFlyout>
</FluxMenuGroup>
</FluxMenu>
</FluxPane>
</template>
<script
lang="ts"
setup>
import type { FluxIconName } from '@flux-ui/types';
import { FluxFormInput, FluxMenu, FluxMenuFlyout, FluxMenuGroup, FluxMenuItem, FluxMenuPane, FluxMenuSubHeader, FluxPane } from '@flux-ui/components';
import { computed, ref } from 'vue';
const actions: { readonly icon: FluxIconName; readonly label: string; }[] = [
{icon: 'scissors', label: 'Cut'},
{icon: 'copy', label: 'Copy'},
{icon: 'paste', label: 'Paste'},
{icon: 'clone', label: 'Duplicate'},
{icon: 'pen', label: 'Rename'},
{icon: 'trash', label: 'Delete'}
];
const query = ref('');
const filtered = computed(() => actions.filter(action => action.label.toLowerCase().includes(query.value.toLowerCase())));
</script>Settings
Several controls in one pane. `Tab` reaches every toggle, and toggling one never closes the menu.
<template>
<FluxPane style="width: 240px">
<FluxMenu>
<FluxMenuGroup>
<FluxMenuItem
icon-leading="user"
label="Account"/>
<FluxMenuFlyout
icon="bell"
label="Notifications">
<FluxMenu>
<FluxMenuPane>
<label style="display: flex; align-items: center; justify-content: space-between; gap: 12px">
Email
<FluxToggle v-model="email"/>
</label>
<label style="display: flex; align-items: center; justify-content: space-between; gap: 12px">
Push
<FluxToggle v-model="push"/>
</label>
</FluxMenuPane>
</FluxMenu>
</FluxMenuFlyout>
</FluxMenuGroup>
</FluxMenu>
</FluxPane>
</template>
<script
lang="ts"
setup>
import { FluxMenu, FluxMenuFlyout, FluxMenuGroup, FluxMenuItem, FluxMenuPane, FluxPane, FluxToggle } from '@flux-ui/components';
import { ref } from 'vue';
const email = ref(true);
const push = ref(false);
</script>