Skip to content

FlowMenu is a menu of options behind a single icon trigger — the composer’s “+” is this widget with the add glyph. Entries are data, not widgets: a sealed tree of FlowMenuOptions and FlowMenuDividers, so the same description renders as an anchored menu on desktop and a bottom sheet on phones.

Dividers group rows. An option with non-empty children becomes a submenu — a pushed page when presenting as a sheet. selected draws a check on modes the host has toggled on:

Groups, submenus, and a toggle
FlowMenu(
icon: Icons.add,
tooltip: 'Add to chat',
entries: [
FlowMenuOption(
id: 'files',
icon: Icons.upload_file_outlined,
label: 'Add Files or Photos',
),
FlowMenuDivider(),
// Non-empty children turn a row into a submenu — a pushed
// page when presenting as a bottom sheet.
FlowMenuOption(
id: 'skills',
icon: Icons.history_edu_outlined,
label: 'Skills',
children: [
FlowMenuOption(id: 'slides', icon: Icons.co_present_outlined,
label: 'Slide deck'),
FlowMenuOption(id: 'review', icon: Icons.rate_review_outlined,
label: 'Code review'),
],
),
FlowMenuDivider(),
// `selected` draws the check — a mode the host toggled on.
FlowMenuOption(
id: 'research',
icon: Icons.school_outlined,
label: 'Research',
selected: researchOn,
),
FlowMenuOption(
id: 'web-search',
icon: Icons.language_outlined,
label: 'Web Search',
),
],
onSelected: (id) => handle(id),
// Presentation is automatic: an anchored menu on desktop, a
// bottom sheet on iOS and Android. FlowMenuPresentation.menu /
// .sheet force either.
sheetTitle: 'Add to Chat',
)

Every selection — top level or inside a submenu — lands in the single onSelected callback with the option’s id. Toggling is host state: flip your flag and rebuild with the new selected value.

The auto default anchors a menu on desktop and presents a sheet titled with sheetTitle on iOS and Android; FlowMenuPresentation.menu / .sheet force either. Submenus become pushed pages inside the sheet, with a back affordance. The sheet rides the Material modal route, so a host not built on MaterialApp needs DefaultMaterialLocalizations.delegate among its localizationsDelegates.

FlowMenuStyle overrides the menu’s colors and metrics per instance without touching the global tokens: backgroundColor, borderColor, separatorColor, hoverColor, labelStyle, descriptionStyle, iconColor, checkColor, accentColor, menuRadius, sheetRadius, minWidth, and barrierColor. Paddings are baked spec metrics, not style fields.

  • entries — the sealed FlowMenuEntry tree: FlowMenuOption (id, icon, label, selected, enabled, children) and FlowMenuDivider.
  • onSelected — one callback, every level; receives the id.
  • icon, tooltip — the trigger; enabled: false mutes it.
  • sheetTitle, presentation — sheet form and when it’s used.
  • menuStyle — a FlowMenuStyle for per-instance retheming.