feat(react-tag-picker): add portal-free base render - #36512
Draft
Hotell wants to merge 1 commit into
Draft
Conversation
renderTagPicker_unstable statically imports Portal, so @fluentui/react-portal is bundled by any consumer of the render - including the headless TagPicker, which sets inline: true and never portals at runtime. Moves the shared JSX into renderTagPickerBase, which keeps the popover in DOM order, and leaves portaling in the styled render. Headless re-exports the base render. Keeping the base in its own module is what removes the static import; sharing a file would re-introduce it.
|
Pull request demo site: URL |
📊 Bundle size reportUnchanged fixtures
|
| @@ -0,0 +1,7 @@ | |||
| { | |||
There was a problem hiding this comment.
🕵🏾♀️ visual changes to review in the Visual Change Report
vr-tests-react-components/Avatar Converged 1 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-react-components/Avatar Converged.badgeMask.normal.chromium.png | 5 | Changed |
vr-tests-react-components/Menu 1 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| 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 | 599 | 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.chromium.png | 503 | Changed |
| vr-tests-react-components/Positioning.Positioning end.updated 2 times.chromium.png | 864 | Changed |
vr-tests-react-components/ProgressBar converged 3 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-react-components/ProgressBar converged.Indeterminate + thickness - Dark Mode.default.chromium.png | 42 | Changed |
| vr-tests-react-components/ProgressBar converged.Indeterminate + thickness - High Contrast.default.chromium.png | 45 | Changed |
| vr-tests-react-components/ProgressBar converged.Indeterminate + thickness.default.chromium.png | 39 | Changed |
vr-tests-react-components/TagPicker 3 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 - High Contrast.chromium.png | 1319 | Changed |
| vr-tests-react-components/TagPicker.disabled - RTL.disabled input hover.chromium.png | 635 | Changed |
There were 3 duplicate changes discarded. Check the build logs for more information.
Hotell
added a commit
to Hotell/fluentui
that referenced
this pull request
Aug 5, 2026
…n TagPicker fixture microsoft#36503 merged, adding TagPicker.fixture.js. It retains @griffel/core and @griffel/react through the portal that ./tag-picker mounts, which the check correctly reports as a regression because the fixture is new and nothing allowlisted it. Records it as tracked debt so the branch is green against current master. microsoft#36512 removes the leak, and the entry has to be deleted in the same change - the allowlist is shrink-only, so a fixed leak keeps failing until its entry goes. The same merge also shrank the AllComponents icon leak: react-icons now survives only through ./teaching-popover, since the tag picker no longer ships a default icon.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Previous Behavior
renderTagPicker_unstablestatically importsPortal:Because the import is static,
@fluentui/react-portal— and through its mount-node styles, Griffel — is bundled by every consumer of this render, regardless of theinlinebranch taken at runtime.The headless TagPicker is affected even though it can never portal:
useTagPickersetsinline: true, andinlineis deliberately omitted fromTagPickerBaseProps. So headless ships portal code it cannot execute.New Behavior
The shared JSX moves into
renderTagPickerBase, which keeps the popover in DOM order and imports no portal. The styled render keeps portaling and delegates:Headless re-exports the base render, so nothing about its rendered output changes:
Keeping the base in its own module is what removes the static import — sharing a file would re-introduce it. This mirrors the base-hook split used by #36503 and #36504.
Bundle size
Measured with
nx run react-headless-components-preview:bundle-size --skip-nx-cache.Standalone, on this branch:
The full win needs the icon PRs. Stacked on #36503 + #36504, where
react-iconsno longer drags Griffel in through a second path:/tag-pickerWith all three applied, the headless bundle contains no
react-portal,@griffel/*or@fluentui/react-iconsmodules — verified by grepping the emitted bundle and by the check in #36511.Notes for reviewers
inline: true; only the unreachable import is removed.TagPickeris unchanged — same JSX, same portal branch.renderTagPickerContentis module-internal and not exported from the package.react-tag-pickerandreact-headless-components-preview.Related Issue(s)