Skip to content

feat(react-button): expose useSplitButtonBase_unstable base hook - #36524

Open
Victor Genaev (mainframev) wants to merge 5 commits into
masterfrom
feat/split-button-base-hook
Open

feat(react-button): expose useSplitButtonBase_unstable base hook#36524
Victor Genaev (mainframev) wants to merge 5 commits into
masterfrom
feat/split-button-base-hook

Conversation

@mainframev

@mainframev Victor Genaev (mainframev) commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

PR 2 of a 3-PR stack. Base: #36523.

Extracts a design-agnostic useSplitButtonBase_unstable base hook (plus SplitButtonBaseProps/SplitButtonBaseSlots/SplitButtonBaseState) out of the styled useSplitButton_unstable, so a future headless SplitButton (PR 3) can compose the same behavior with headless Button/MenuButton instead of the styled ones.

Stack:

  1. test(react-button): add SplitButton regression test before base-hook extraction #36523 — regression tests (merged into this branch's history)
  2. this PR — @fluentui/react-button base-hook extraction
  3. feat/split-button-headless — headless SplitButton (base: this branch)

What changed

  • SplitButton.types.ts: added SplitButtonBaseSlots, SplitButtonBaseProps, SplitButtonBaseState — component-agnostic, typed against ButtonBaseProps/MenuButtonBaseProps instead of concrete Button/MenuButton. Existing styled types (SplitButtonSlots/SplitButtonProps/SplitButtonState) are unchanged.
  • useSplitButton.ts: added useSplitButtonBase_unstable, which owns all design-agnostic behavior (generated primary-action id, aria-labelledby fallback naming, disabled/disabledFocusable propagation, icon propagation). Refactored useSplitButton_unstable to call the base hook and recreate both child slots via slot.optional with the styled Button/MenuButton element types (production rendering resolves each slot's element type from its SLOT_ELEMENT_TYPE_SYMBOL metadata, not from state.components, so recreating rather than patching state.components is required).
  • Exported the new base types/hook from the component and package barrels.
  • Added useSplitButtonBase.test.tsx (16 tests) for the new base contract.
  • Added the useSplitButtonBase.fixture.js bundle-size fixture.
  • Regenerated react-button.api.md.

No behavior change to the styled SplitButton/useSplitButton_unstable — the regression tests added in #36523 continue to pass unmodified.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

Pull request demo site: URL

@mainframev
Victor Genaev (mainframev) force-pushed the feat/split-button-base-hook branch 4 times, most recently from 7b50ac1 to 9586fca Compare August 5, 2026 21:48
@mainframev
Victor Genaev (mainframev) marked this pull request as ready for review August 5, 2026 21:54
@mainframev Victor Genaev (mainframev) changed the title feat(react-button): extract useSplitButtonBase_unstable design-agnostic base hook feat(react-button): expose useSplitButtonBase_unstable base hook Aug 5, 2026
Base automatically changed from test/split-button-hook-regression-tests to master August 7, 2026 20:28
…c base hook

Splits SplitButton's internal logic into two layers:
- useSplitButtonBase_unstable: design-agnostic base hook (no appearance/shape/
  size), producing ARIA-wired root/menuButton/primaryActionButton slots with
  placeholder 'button' element metadata.
- useSplitButton_unstable: styled wrapper that composes the base hook and
  recreates both child slots via slot.optional with the concrete Button/
  MenuButton element types and styling defaults.

Also widens renderSplitButton_unstable to accept SplitButtonBaseState so it
can be reused directly by headless consumers instead of being duplicated.

Adds SplitButtonBaseProps/SplitButtonBaseSlots/SplitButtonBaseState, exported
from the SplitButton and package root barrels, together with a bundle-size
fixture. This unblocks a future headless SplitButton built directly on the
base hook.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

📊 Bundle size report

Package & Exports Baseline (minified/GZIP) PR Change
react-button
SplitButton
46.572 kB
11.521 kB
46.824 kB
11.588 kB
252 B
67 B
react-components
react-components: entire library
1.296 MB
326.595 kB
1.296 MB
326.652 kB
254 B
57 B
Unchanged fixtures
Package & Exports Size (minified/GZIP)
react-avatar
Avatar
47.22 kB
14.855 kB
react-avatar
AvatarGroup
16.254 kB
6.502 kB
react-avatar
AvatarGroupItem
60.339 kB
18.758 kB
react-breadcrumb
@fluentui/react-breadcrumb - package
103.012 kB
28.827 kB
react-button
Button
32.675 kB
8.499 kB
react-button
CompoundButton
39.557 kB
9.806 kB
react-button
MenuButton
37.621 kB
9.89 kB
react-button
ToggleButton
52.331 kB
10.633 kB
react-card
Card - All
92.93 kB
26.936 kB
react-card
Card
85.55 kB
25.023 kB
react-card
CardFooter
11.515 kB
4.599 kB
react-card
CardHeader
14.044 kB
5.422 kB
react-card
CardPreview
11.592 kB
4.711 kB
react-charts
AreaChart
405.869 kB
126.805 kB
react-charts
DeclarativeChart
757.415 kB
222.319 kB
react-charts
DonutChart
316.702 kB
97.624 kB
react-charts
FunnelChart
308.102 kB
94.401 kB
react-charts
GanttChart
389 kB
121.276 kB
react-charts
GaugeChart
316.05 kB
97.012 kB
react-charts
GroupedVerticalBarChart
397.077 kB
124.06 kB
react-charts
HeatMapChart
391.135 kB
122.31 kB
react-charts
HorizontalBarChart
296.378 kB
90.124 kB
react-charts
HorizontalBarChartWithAxis
63 B
83 B
react-charts
Legends
235.545 kB
70.669 kB
react-charts
LineChart
417.217 kB
129.946 kB
react-charts
PolarChart
344.556 kB
107.661 kB
react-charts
SankeyChart
212.76 kB
68.333 kB
react-charts
ScatterChart
396.543 kB
123.983 kB
react-charts
Sparkline
80.888 kB
26.864 kB
react-charts
VerticalBarChart
433.535 kB
128.991 kB
react-charts
VerticalStackedBarChart
403.095 kB
125.472 kB
react-checkbox
Checkbox
29.609 kB
10.527 kB
react-combobox
Combobox (including child components)
138.287 kB
44.693 kB
react-combobox
Dropdown (including child components)
138.046 kB
44.447 kB
react-components
react-components: Button, FluentProvider & webLightTheme
66.297 kB
19.006 kB
react-components
react-components: Accordion, Button, FluentProvider, Image, Menu, Popover
226.106 kB
68.067 kB
react-components
react-components: FluentProvider & webLightTheme
39.52 kB
13.116 kB
react-datepicker-compat
DatePicker Compat
216.276 kB
63.974 kB
react-dialog
Dialog (including children components)
89.951 kB
27.858 kB
react-field
Field
21.132 kB
7.881 kB
react-headless-components-preview
react-headless-components-preview: entire library
251.816 kB
73.264 kB
react-headless-components-preview
@fluentui/react-headless-components-preview/tag-picker
62.147 kB
20.587 kB
react-headless-components-preview
@fluentui/react-headless-components-preview/teaching-popover
35.416 kB
11.745 kB
react-input
Input
25.092 kB
8.212 kB
react-list
List
74.531 kB
23.01 kB
react-list
ListItem
98.023 kB
29.881 kB
react-message-bar
MessageBar (all components)
24.114 kB
8.524 kB
react-persona
Persona
54.173 kB
16.791 kB
react-portal-compat
PortalCompatProvider
5.341 kB
2.146 kB
react-progress
ProgressBar
19.063 kB
7.418 kB
react-radio
Radio
26.994 kB
8.711 kB
react-radio
RadioGroup
12.759 kB
5.176 kB
react-select
Select
24.957 kB
8.972 kB
react-slider
Slider
32.231 kB
11.086 kB
react-spinbutton
SpinButton
32.513 kB
10.584 kB
react-swatch-picker
@fluentui/react-swatch-picker - package
92.187 kB
27.315 kB
react-switch
Switch
32.231 kB
10.156 kB
react-table
DataGrid
146.769 kB
43.606 kB
react-table
Table (Primitives only)
36.893 kB
12.305 kB
react-table
Table as DataGrid
118.515 kB
33.308 kB
react-table
Table (Selection only)
65.385 kB
18.616 kB
react-table
Table (Sort only)
64.048 kB
18.227 kB
react-tag-picker
@fluentui/react-tag-picker - package
174.241 kB
54.367 kB
react-tags
InteractionTag
12.463 kB
4.942 kB
react-tags
Tag
28.376 kB
8.9 kB
react-tags
TagGroup
69.648 kB
21.404 kB
react-teaching-popover
TeachingPopover
100.758 kB
31.829 kB
react-textarea
Textarea
23.457 kB
8.478 kB
react-timepicker-compat
TimePicker
140.991 kB
46.069 kB
react-tooltip
Tooltip
53.519 kB
19.021 kB
react-tree
FlatTree
135.661 kB
40.459 kB
react-tree
PersonaFlatTree
137.524 kB
40.991 kB
react-tree
PersonaTree
133.605 kB
39.781 kB
react-tree
Tree
131.748 kB
39.265 kB
🤖 This report was generated against 141feed5e8c03581e4d49c65f476b7858786854f

@@ -0,0 +1,7 @@
{

@github-actions github-actions Bot Aug 7, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🕵🏾‍♀️ visual changes to review in the Visual Change Report

vr-tests-react-components/Menu 2 screenshots
Image Name Diff(in Pixels) Image Type
vr-tests-react-components/Menu.Nested Submenus Small Viewport Stacked.nested menu.chromium.png 1008 Changed
vr-tests-react-components/Menu.Nested Submenus Small Viewport Flipped.nested menu.chromium.png 699 Changed
vr-tests-react-components/Menu Converged - submenuIndicator slotted content 2 screenshots
Image Name Diff(in Pixels) Image Type
vr-tests-react-components/Menu Converged - submenuIndicator slotted content.default - RTL.submenus open.chromium.png 404 Changed
vr-tests-react-components/Menu Converged - submenuIndicator slotted content.default.submenus open.chromium.png 413 Changed
vr-tests-react-components/Positioning 2 screenshots
Image Name Diff(in Pixels) Image Type
vr-tests-react-components/Positioning.Positioning end.updated 2 times.chromium.png 747 Changed
vr-tests-react-components/Positioning.Positioning end.chromium.png 910 Changed
vr-tests-react-components/ProgressBar converged 2 screenshots
Image Name Diff(in Pixels) Image Type
vr-tests-react-components/ProgressBar converged.Indeterminate + thickness - High Contrast.default.chromium.png 110 Changed
vr-tests-react-components/ProgressBar converged.Indeterminate + thickness.default.chromium.png 160 Changed
vr-tests-react-components/TagPicker 2 screenshots
Image Name Diff(in Pixels) Image Type
vr-tests-react-components/TagPicker.disabled - Dark Mode.disabled input hover.chromium.png 658 Changed
vr-tests-react-components/TagPicker.disabled.disabled input hover.chromium.png 677 Changed

There were 2 duplicate changes discarded. Check the build logs for more information.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants