Skip to content

[menu][checkbox][radio][switch] Share selection indicators, menu item wiring, and checked state mapping - #6166

Open
hoanle0126 wants to merge 1 commit into
mui:masterfrom
hoanle0126:perf/share-selection-indicators-and-menu-items
Open

hoanle0126 wants to merge 1 commit into
mui:masterfrom
hoanle0126:perf/share-selection-indicators-and-menu-items

Conversation

@hoanle0126

Copy link
Copy Markdown

Menu.CheckboxItemIndicator, Menu.RadioItemIndicator, Checkbox.Indicator, Radio.Indicator, and the shared ItemIndicator used by Select.ItemIndicator and Combobox.ItemIndicator all implement the same transition-mounted <span> indicator pattern (useTransitionStatus + useOpenChangeComplete + useRenderElement). Likewise, Menu.Item, Menu.CheckboxItem, and Menu.RadioItem repeat the same composite list registration, store subscription, and useMenuItem wiring, and Menu, Checkbox, Radio, and Switch each define their own checked -> data-checked / data-unchecked attribute mapper.

This PR consolidates those shared patterns:

  • Extract useSelectionIndicator in packages/react/src/utils/ItemIndicator.tsx and reuse it across ItemIndicator, MenuCheckboxItemIndicator, MenuRadioItemIndicator, RadioIndicator, and CheckboxIndicator (also passing enabled: keepMounted || mounted to useRenderElement in RadioIndicator and CheckboxIndicator so disabled indicators skip prop resolution before returning null).
  • Extract useRegularMenuItem and useSelectableMenuItem in packages/react/src/menu/item/useMenuItem.ts to share the common item setup across MenuItem, MenuCheckboxItem, and MenuRadioItem.
  • Extract mapCheckedStateAttribute in packages/react/src/internals/stateAttributesMapping.ts and reuse it in Menu, Checkbox, Radio, and Switch.

Public props, state types, and runtime behavior remain unchanged.

Bundle size

Measured locally on master (cf696d6) vs. this branch using bundle-size-checker (all values in bytes):

Bundle Parsed before Parsed after Parsed delta Gzip before Gzip after Gzip delta
@base-ui/react 517,437 515,651 -1,786 167,721 167,422 -299
@base-ui/react/menu 176,588 175,681 -907 58,722 58,412 -310
@base-ui/react/context-menu 142,102 141,185 -917 47,976 47,670 -306
@base-ui/react/menubar 16,537 16,537 0 6,317 6,317 0
@base-ui/react/checkbox 19,737 19,834 +97 7,872 7,872 0
@base-ui/react/radio 18,887 18,989 +102 7,508 7,525 +17
@base-ui/react/radio-group 18,688 18,688 0 7,227 7,227 0
@base-ui/react/switch 14,096 14,148 +52 5,742 5,742 0
@base-ui/react/select 125,988 126,095 +107 44,071 44,119 +48
@base-ui/react/combobox 145,652 145,759 +107 50,196 50,239 +43

@pkg-pr-new

pkg-pr-new Bot commented Nov 2, 2026

Copy link
Copy Markdown

commit: 14b8271

@code-infra-dashboard

code-infra-dashboard Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Bundle size

Bundle Parsed size Gzip size
@base-ui/react ▼-1.79KB(-0.35%) ▼-299B(-0.18%)

Details of bundle changes

Performance

No regressions in 36 benchmarks · ran 3m 49s · details


Check out the code infra dashboard for more information about this PR.

@netlify

netlify Bot commented Nov 2, 2026

Copy link
Copy Markdown

✅ Deploy Preview for base-ui ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 14b8271
🔍 Latest deploy log https://app.netlify.com/projects/base-ui/deploys/6ae91e3435d858667f77d47f
😎 Deploy Preview https://deploy-preview-6166--base-ui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@zannager zannager added the scope: all components Widespread work has an impact on almost all components. label Nov 3, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: all components Widespread work has an impact on almost all components.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants