Component
Menu
Package version
@fluentui/react-headless-components-preview 0.2.5
React version
18.3.1
Environment
node v22.12.0
@fluentui/react-headless-components-preview 0.2.5
Current Behavior
components/Menu/MenuSplitGroup/MenuSplitGroup.tsx calls
renderMenuSplitGroup(state);
with no contexts argument. useIsInMenuSplitGroup compares the value it receives against the
module-level default by identity. With nothing provided, the default is what every descendant
reads, the identity comparison is always false, and no descendant half can tell that it is inside
a split group.
The user-visible consequence is that the gutter suppression a split group is supposed to apply —
the icon and checkmark columns that the trigger half drops — never fires, because that suppression
is gated on exactly this hook.
Expected Behavior
useIsInMenuSplitGroup returns true for descendants of a MenuSplitGroup, matching the
behaviour of the Griffel-styled MenuSplitGroup the headless one mirrors.
Reproduction
Render a headless MenuSplitGroup containing a trigger half and call useIsInMenuSplitGroup from
any descendant: it returns false. Visually, in a styled layer over the headless package, the
trigger half keeps the icon and checkmark gutters that the Griffel-styled equivalent drops.
Steps to reproduce
- Render a
MenuSplitGroup with a menu item as its trigger half.
- From a descendant, read
useIsInMenuSplitGroup().
- Observe
false.
Discovery context
Found during pixel-level verification of a styling layer built over
@fluentui/react-headless-components-preview: the styled trigger half kept the icon and checkmark
gutters that the @fluentui/react-components twin drops, and tracing the gutter rule led back to a
hook that could never return true.
Proposed fix
Provide the contexts argument, with a useMemo keyed on state.setMultiline so the identity is
stable across renders (identity stability is the whole point — an inline object literal would defeat
the comparison in the other direction, re-firing on every render):
const contexts = React.useMemo(
() => ({ menuSplitGroup: { setMultiline: state.setMultiline } }),
[state.setMultiline],
);
return renderMenuSplitGroup(state, contexts);
setMultiline itself stays the documented no-op — this changes what descendants can observe, not
what the group does.
A working implementation is included in PR #[WINDMOD-PR-NUMBER] (commit 568297d44a); happy to
split it into a standalone PR against this issue.
Suggested severity
Medium - Has workaround (a styling layer can re-declare its own split-group context, at the cost of
duplicating a contract the package already owns).
Are you willing to submit a PR to fix?
yes
Component
Menu
Package version
@fluentui/react-headless-components-preview0.2.5React version
18.3.1
Environment
Current Behavior
components/Menu/MenuSplitGroup/MenuSplitGroup.tsxcallswith no contexts argument.
useIsInMenuSplitGroupcompares the value it receives against themodule-level default by identity. With nothing provided, the default is what every descendant
reads, the identity comparison is always false, and no descendant half can tell that it is inside
a split group.
The user-visible consequence is that the gutter suppression a split group is supposed to apply —
the icon and checkmark columns that the trigger half drops — never fires, because that suppression
is gated on exactly this hook.
Expected Behavior
useIsInMenuSplitGroupreturnstruefor descendants of aMenuSplitGroup, matching thebehaviour of the Griffel-styled
MenuSplitGroupthe headless one mirrors.Reproduction
Render a headless
MenuSplitGroupcontaining a trigger half and calluseIsInMenuSplitGroupfromany descendant: it returns
false. Visually, in a styled layer over the headless package, thetrigger half keeps the icon and checkmark gutters that the Griffel-styled equivalent drops.
Steps to reproduce
MenuSplitGroupwith a menu item as its trigger half.useIsInMenuSplitGroup().false.Discovery context
Found during pixel-level verification of a styling layer built over
@fluentui/react-headless-components-preview: the styled trigger half kept the icon and checkmarkgutters that the
@fluentui/react-componentstwin drops, and tracing the gutter rule led back to ahook that could never return true.
Proposed fix
Provide the contexts argument, with a
useMemokeyed onstate.setMultilineso the identity isstable across renders (identity stability is the whole point — an inline object literal would defeat
the comparison in the other direction, re-firing on every render):
setMultilineitself stays the documented no-op — this changes what descendants can observe, notwhat the group does.
A working implementation is included in PR #[WINDMOD-PR-NUMBER] (commit
568297d44a); happy tosplit it into a standalone PR against this issue.
Suggested severity
Medium - Has workaround (a styling layer can re-declare its own split-group context, at the cost of
duplicating a contract the package already owns).
Are you willing to submit a PR to fix?
yes