MenuItem is the compact compatibility record for a flat command, not a
standalone widget.
You encounter it when building a Menu or MenuButton. Each item describes one visible row in the menu, and it may also carry an icon source such as scalable vector graphics (SVG) content plus the action that should fire when the user selects it. Use MenuActionItem inside MenuContent when a row needs a description,
shortcut or metadata, selected state, explicit disabled state, or destructive
tone. Both APIs lower through the same retained menu recipe.
Example
use fission::prelude::*;
let items = vec![
MenuItem {
label: "Rename".into(),
icon: None,
on_select: Some(rename_action),
semantics_identifier: Some("file.rename".into()),
},
MenuItem {
label: "Duplicate".into(),
icon: None,
on_select: Some(duplicate_action),
semantics_identifier: Some("file.duplicate".into()),
},
];
These items are only data until a parent widget such as Menu turns them into visible rows.
Field table
| | | |
|---|
| | Visible text for the menu row. | Required. Keep labels short and action-oriented. |
| | Optional icon source shown before the label. | Defaults to None. Typically a scalable vector graphics (SVG) string used by the icon helper. |
| | Action dispatched when the row is chosen. | Defaults to None. An item with no action is visually present but effectively inert. |
| | Stable identifier exposed on the generated MenuItem semantic node. | Use it when labels may be duplicated or localized and tests need stable addressing. |
How action flow works here
Unlike Combobox or SegmentedControl, MenuItem does not generate actions from a closure. You hand it the final ActionEnvelope up front. That makes it a good fit for a fixed set of known actions. If the selected value must vary per item, build a different payload for each item when you construct the vector.
The parent turns the record into a semantic MenuItem whose visible label is
also its accessible name. A direct Menu retains only its first enabled row in
page-level Tab order and uses arrow keys to rove through the rest.
MenuButton keeps every popup row out of page-level Tab order and gives the
opened popup controlled focus entry; see the parent pages for arrow,
boundary-key, character matching, and dismissal behavior.
Specific advice
MenuItem has no disabled field. If on_select is None, the row still
appears and remains focusable but has no default action. For an unavailable row
that must remain visible, use MenuActionItem::disabled(true) so focus,
activation, semantics, and the design-system state agree.
Production checklist
For MenuItem, review the fields that change behavior before treating the widget as finished: label, icon, on_select, and semantics_identifier. The goal is to make the product rule visible in state and actions, not hidden inside ad-hoc construction code.
Bind on_select to explicit reducer actions and test that the reducer handles unavailable, duplicate, or invalid input safely.
Check the semantics tree for the user-facing label or role that makes this widget understandable without relying only on pixels.
Add at least one component or harness test that confirms the visible text, semantic role, action dispatch, and layout constraint that matter for this widget in context.
If a screen starts repeating the same MenuItem setup, extract a named component around this widget. That keeps the reference API small while making product code easier to read and safer for generated code to copy.