diff --git a/apps/vr-tests-react-components/src/stories/PresenceBadge.stories.tsx b/apps/vr-tests-react-components/src/stories/PresenceBadge.stories.tsx
index 537d44061f264..bb430a79932ea 100644
--- a/apps/vr-tests-react-components/src/stories/PresenceBadge.stories.tsx
+++ b/apps/vr-tests-react-components/src/stories/PresenceBadge.stories.tsx
@@ -1,16 +1,12 @@
import { storiesOf } from '@storybook/react';
import * as React from 'react';
-import { PresenceBadge, PresenceBadgeProps } from '@fluentui/react-badge';
+import { PresenceBadge } from '@fluentui/react-badge';
+import { tokens } from '@fluentui/react-theme';
+import { Steps, StoryWright } from 'storywright';
+import { TestWrapperDecorator } from '../utilities/TestWrapperDecorator';
-const statuses: PresenceBadgeProps['status'][] = [
- 'available',
- 'away',
- 'busy',
- 'do-not-disturb',
- 'offline',
- 'out-of-office',
- 'unknown',
-];
+const statuses = ['available', 'away', 'busy', 'do-not-disturb', 'offline', 'out-of-office', 'unknown'] as const;
+const sizes = ['tiny', 'extra-small', 'small', 'medium', 'large', 'extra-large'] as const;
storiesOf('PresenceBadge Converged - status', module).addStory(
'default',
@@ -40,12 +36,43 @@ storiesOf('PresenceBadge Converged - sizes', module).addStory(
'default',
() => (
- {(['tiny', 'extra-small', 'small', 'medium', 'large', 'extra-large'] as PresenceBadgeProps['size'][]).map(
- size => (
-
- ),
- )}
+ {sizes.map(size => (
+
+ ))}
),
{ includeRtl: true },
);
+
+storiesOf('PresenceBadge Converged - inverted background', module)
+ .addDecorator(TestWrapperDecorator)
+ .addDecorator(story => (
+ {story()}
+ ))
+ .addStory(
+ 'default',
+ () => (
+
+ {sizes.map(size => (
+ <>
+ {statuses.map(status => (
+
+ ))}
+ {statuses.map(status => (
+
+ ))}
+ >
+ ))}
+
+ ),
+ { includeHighContrast: true, includeDarkMode: true },
+ );
diff --git a/change/@fluentui-react-badge-4df99d1f-b2d8-4ebd-a8c8-defa2b7568f2.json b/change/@fluentui-react-badge-4df99d1f-b2d8-4ebd-a8c8-defa2b7568f2.json
new file mode 100644
index 0000000000000..f87b9b22f9b97
--- /dev/null
+++ b/change/@fluentui-react-badge-4df99d1f-b2d8-4ebd-a8c8-defa2b7568f2.json
@@ -0,0 +1,7 @@
+{
+ "type": "patch",
+ "comment": "fix: Remove white border around presence badge when on a dark background",
+ "packageName": "@fluentui/react-badge",
+ "email": "behowell@microsoft.com",
+ "dependentChangeType": "patch"
+}
diff --git a/packages/react-components/react-badge/src/components/PresenceBadge/usePresenceBadgeStyles.styles.ts b/packages/react-components/react-badge/src/components/PresenceBadge/usePresenceBadgeStyles.styles.ts
index aa2e505d68174..599edae2e48f8 100644
--- a/packages/react-components/react-badge/src/components/PresenceBadge/usePresenceBadgeStyles.styles.ts
+++ b/packages/react-components/react-badge/src/components/PresenceBadge/usePresenceBadgeStyles.styles.ts
@@ -18,17 +18,25 @@ const getIsBusy = (status: PresenceBadgeStatus): boolean => {
};
const useRootClassName = makeResetStyles({
- padding: 0,
display: 'inline-flex',
boxSizing: 'border-box',
alignItems: 'center',
justifyContent: 'center',
- '& span': {
- display: 'flex',
- },
borderRadius: tokens.borderRadiusCircular,
backgroundColor: tokens.colorNeutralBackground1,
+
+ // The background color bleeds around the edge of the icon due to antialiasing on the svg and element background.
+ // Since all presence icons have a border around the edge that is at least 1px wide*, we can inset the background
+ // using padding and backgroundClip. The icon has margin: -1px to account for the padding.
+ // (* except size="tiny", where backgroundClip is unset)
+ padding: '1px',
+ backgroundClip: 'content-box',
+});
+
+const useIconClassName = makeResetStyles({
+ display: 'flex',
+ margin: '-1px',
});
const useStyles = makeStyles({
@@ -69,6 +77,7 @@ const useStyles = makeStyles({
tiny: {
aspectRatio: '1',
width: '6px',
+ backgroundClip: 'unset', // tiny icons have a border less than 1px wide, and can't use the backgroundClip fix
'& svg': {
width: '6px !important',
height: '6px !important',
@@ -97,6 +106,7 @@ const useStyles = makeStyles({
*/
export const usePresenceBadgeStyles_unstable = (state: PresenceBadgeState): PresenceBadgeState => {
const rootClassName = useRootClassName();
+ const iconClassName = useIconClassName();
const styles = useStyles();
const isBusy = getIsBusy(state.status);
state.root.className = mergeClasses(
@@ -122,7 +132,7 @@ export const usePresenceBadgeStyles_unstable = (state: PresenceBadgeState): Pres
);
if (state.icon) {
- state.icon.className = mergeClasses(presenceBadgeClassNames.icon, state.icon.className);
+ state.icon.className = mergeClasses(presenceBadgeClassNames.icon, iconClassName, state.icon.className);
}
return state;