From 2b9bd1b65a1463626462403662ddfed2860c2a65 Mon Sep 17 00:00:00 2001 From: Robert Penner Date: Mon, 26 Jan 2026 20:42:54 +0000 Subject: [PATCH 1/4] fix(ToggleButton): keep `outline` toggle from increasing the button size --- .../useToggleButtonStyles.styles.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/react-components/react-button/library/src/components/ToggleButton/useToggleButtonStyles.styles.ts b/packages/react-components/react-button/library/src/components/ToggleButton/useToggleButtonStyles.styles.ts index 631abe51d3391..7670522fc8b01 100644 --- a/packages/react-components/react-button/library/src/components/ToggleButton/useToggleButtonStyles.styles.ts +++ b/packages/react-components/react-button/library/src/components/ToggleButton/useToggleButtonStyles.styles.ts @@ -14,6 +14,14 @@ export const toggleButtonClassNames: SlotClassNames = { icon: 'fui-ToggleButton__icon', }; +const useRootAppearanceStyles = makeStyles({ + // Appearance variations that apply regardless of checked state + outline: { + // Ensure box-shadow transitions in both directions (checked <-> unchecked) + transitionProperty: 'background, border, color, box-shadow', + }, +}); + const useRootCheckedStyles = makeStyles({ // Base styles base: { @@ -74,18 +82,22 @@ const useRootCheckedStyles = makeStyles({ outline: { backgroundColor: tokens.colorTransparentBackgroundSelected, ...shorthands.borderColor(tokens.colorNeutralStroke1), - ...shorthands.borderWidth(tokens.strokeWidthThicker), + // Use inset box-shadow to create thicker border visual without affecting layout + boxShadow: `0 0 0 ${tokens.strokeWidthThick} ${tokens.colorNeutralStroke1} inset`, ':hover': { backgroundColor: tokens.colorTransparentBackgroundHover, + boxShadow: `0 0 0 ${tokens.strokeWidthThick} ${tokens.colorNeutralStroke1Hover} inset`, }, ':hover:active,:active:focus-visible': { backgroundColor: tokens.colorTransparentBackgroundPressed, + boxShadow: `0 0 0 ${tokens.strokeWidthThick} ${tokens.colorNeutralStroke1Pressed} inset`, }, ...createCustomFocusIndicatorStyle({ ...shorthands.borderColor(tokens.colorNeutralStroke1), + boxShadow: `0 0 0 ${tokens.strokeWidthThick} ${tokens.colorNeutralStroke1} inset, 0 0 0 ${tokens.strokeWidthThick} ${tokens.colorStrokeFocus2} inset`, }), }, primary: { @@ -252,6 +264,7 @@ const usePrimaryHighContrastStyles = makeStyles({ export const useToggleButtonStyles_unstable = (state: ToggleButtonState): ToggleButtonState => { 'use no memo'; + const rootAppearanceStyles = useRootAppearanceStyles(); const rootCheckedStyles = useRootCheckedStyles(); const rootDisabledStyles = useRootDisabledStyles(); const iconCheckedStyles = useIconCheckedStyles(); @@ -262,6 +275,9 @@ export const useToggleButtonStyles_unstable = (state: ToggleButtonState): Toggle state.root.className = mergeClasses( toggleButtonClassNames.root, + // Appearance base styles (applies to both checked and unchecked) + appearance && rootAppearanceStyles[appearance], + // Primary high contrast styles appearance === 'primary' && primaryHighContrastStyles.base, appearance === 'primary' && (disabled || disabledFocusable) && primaryHighContrastStyles.disabled, From d28e1774a72a4739e7f7370614ffd1f78f084e42 Mon Sep 17 00:00:00 2001 From: Robert Penner Date: Mon, 26 Jan 2026 21:06:01 +0000 Subject: [PATCH 2/4] chore: yarn change --- ...-react-button-01f35392-a207-47c2-9914-bcd12d1e85ce.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@fluentui-react-button-01f35392-a207-47c2-9914-bcd12d1e85ce.json diff --git a/change/@fluentui-react-button-01f35392-a207-47c2-9914-bcd12d1e85ce.json b/change/@fluentui-react-button-01f35392-a207-47c2-9914-bcd12d1e85ce.json new file mode 100644 index 0000000000000..9b56d5c1fd554 --- /dev/null +++ b/change/@fluentui-react-button-01f35392-a207-47c2-9914-bcd12d1e85ce.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "fix(toggle-button): prevent outline toggle from increasing button size", + "packageName": "@fluentui/react-button", + "email": "robertpenner@microsoft.com", + "dependentChangeType": "patch" +} From 5836159b15abbc7343ebab13d51e89e290ec0971 Mon Sep 17 00:00:00 2001 From: Robert Penner Date: Mon, 26 Jan 2026 21:19:14 +0000 Subject: [PATCH 3/4] fix(ToggleButton): restrict outline appearance styles to only apply when outline is selected --- .../src/components/ToggleButton/useToggleButtonStyles.styles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-components/react-button/library/src/components/ToggleButton/useToggleButtonStyles.styles.ts b/packages/react-components/react-button/library/src/components/ToggleButton/useToggleButtonStyles.styles.ts index 7670522fc8b01..dce4be4c6b34e 100644 --- a/packages/react-components/react-button/library/src/components/ToggleButton/useToggleButtonStyles.styles.ts +++ b/packages/react-components/react-button/library/src/components/ToggleButton/useToggleButtonStyles.styles.ts @@ -276,7 +276,7 @@ export const useToggleButtonStyles_unstable = (state: ToggleButtonState): Toggle toggleButtonClassNames.root, // Appearance base styles (applies to both checked and unchecked) - appearance && rootAppearanceStyles[appearance], + appearance === 'outline' && rootAppearanceStyles.outline, // Primary high contrast styles appearance === 'primary' && primaryHighContrastStyles.base, From 35a47040a19c9c1034e5479fa771a70bbf947935 Mon Sep 17 00:00:00 2001 From: Robert Penner Date: Wed, 28 Jan 2026 16:22:57 +0000 Subject: [PATCH 4/4] fix(react-button): restore focus indicator on outline ToggleButton Use strokeWidthThin for focus shadow to layer correctly over strokeWidthThick border shadow when checked. --- .../components/ToggleButton/useToggleButtonStyles.styles.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/react-components/react-button/library/src/components/ToggleButton/useToggleButtonStyles.styles.ts b/packages/react-components/react-button/library/src/components/ToggleButton/useToggleButtonStyles.styles.ts index dce4be4c6b34e..6df2f10cc65b0 100644 --- a/packages/react-components/react-button/library/src/components/ToggleButton/useToggleButtonStyles.styles.ts +++ b/packages/react-components/react-button/library/src/components/ToggleButton/useToggleButtonStyles.styles.ts @@ -96,8 +96,9 @@ const useRootCheckedStyles = makeStyles({ }, ...createCustomFocusIndicatorStyle({ - ...shorthands.borderColor(tokens.colorNeutralStroke1), - boxShadow: `0 0 0 ${tokens.strokeWidthThick} ${tokens.colorNeutralStroke1} inset, 0 0 0 ${tokens.strokeWidthThick} ${tokens.colorStrokeFocus2} inset`, + ...shorthands.borderColor(tokens.colorStrokeFocus2), + // Stack focus indicator (strokeWidthThin) on top of the grey border (strokeWidthThick) + boxShadow: `0 0 0 ${tokens.strokeWidthThin} ${tokens.colorStrokeFocus2} inset, 0 0 0 ${tokens.strokeWidthThick} ${tokens.colorNeutralStroke1} inset`, }), }, primary: {