+
\ No newline at end of file
diff --git a/docs/translations/api-docs/badge-unstyled/badge-unstyled.json b/docs/translations/api-docs/badge-unstyled/badge-unstyled.json
index 311e42d8b67eba..554dfd8183d080 100644
--- a/docs/translations/api-docs/badge-unstyled/badge-unstyled.json
+++ b/docs/translations/api-docs/badge-unstyled/badge-unstyled.json
@@ -10,7 +10,6 @@
"componentsProps": "The props used for each slot inside the Badge.",
"invisible": "If true
, the badge is invisible.",
"max": "Max count to show.",
- "overlap": "Wrapped shape the badge should overlap.",
"showZero": "Controls whether the badge is hidden when badgeContent
is zero.",
"variant": "The variant to use."
},
@@ -30,45 +29,25 @@
"nodeName": "the badge `span` element",
"conditions": "variant=\"standard\"
"
},
- "anchorOriginTopRightRectangular": {
+ "anchorOriginTopRight": {
"description": "Class name applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the badge `span` element",
- "conditions": "anchorOrigin={{ 'top', 'right' }} overlap=\"rectangular\"
"
+ "conditions": "anchorOrigin={{ 'top', 'right' }}
"
},
- "anchorOriginBottomRightRectangular": {
+ "anchorOriginBottomRight": {
"description": "Class name applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the badge `span` element",
- "conditions": "anchorOrigin={{ 'bottom', 'right' }} overlap=\"rectangular\"
"
+ "conditions": "anchorOrigin={{ 'bottom', 'right' }}
"
},
- "anchorOriginTopLeftRectangular": {
+ "anchorOriginTopLeft": {
"description": "Class name applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the badge `span` element",
- "conditions": "anchorOrigin={{ 'top', 'left' }} overlap=\"rectangular\"
"
+ "conditions": "anchorOrigin={{ 'top', 'left' }}
"
},
- "anchorOriginBottomLeftRectangular": {
+ "anchorOriginBottomLeft": {
"description": "Class name applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the badge `span` element",
- "conditions": "anchorOrigin={{ 'bottom', 'left' }} overlap=\"rectangular\"
"
- },
- "anchorOriginTopRightCircular": {
- "description": "Class name applied to {{nodeName}} if {{conditions}}.",
- "nodeName": "the badge `span` element",
- "conditions": "anchorOrigin={{ 'top', 'right' }} overlap=\"circular\"
"
- },
- "anchorOriginBottomRightCircular": {
- "description": "Class name applied to {{nodeName}} if {{conditions}}.",
- "nodeName": "the badge `span` element",
- "conditions": "anchorOrigin={{ 'bottom', 'right' }} overlap=\"circular\"
"
- },
- "anchorOriginTopLeftCircular": {
- "description": "Class name applied to {{nodeName}} if {{conditions}}.",
- "nodeName": "the badge `span` element",
- "conditions": "anchorOrigin={{ 'top', 'left' }} overlap=\"circular\"
"
- },
- "anchorOriginBottomLeftCircular": {
- "description": "Class name applied to {{nodeName}} if {{conditions}}.",
- "nodeName": "the badge `span` element",
- "conditions": "anchorOrigin={{ 'bottom', 'left' }} overlap=\"circular\"
"
+ "conditions": "anchorOrigin={{ 'bottom', 'left' }}
"
},
"invisible": {
"description": "State class applied to {{nodeName}} if {{conditions}}.",
diff --git a/docs/translations/api-docs/badge/badge.json b/docs/translations/api-docs/badge/badge.json
index 7110d48ca1bca7..83ca23b6e8bf51 100644
--- a/docs/translations/api-docs/badge/badge.json
+++ b/docs/translations/api-docs/badge/badge.json
@@ -32,45 +32,25 @@
"nodeName": "the badge `span` element",
"conditions": "variant=\"standard\"
"
},
- "anchorOriginTopRightRectangular": {
+ "anchorOriginTopRight": {
"description": "Class name applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the badge `span` element",
- "conditions": "anchorOrigin={{ 'top', 'right' }} overlap=\"rectangular\"
"
+ "conditions": "anchorOrigin={{ 'top', 'right' }}
"
},
- "anchorOriginBottomRightRectangular": {
+ "anchorOriginBottomRight": {
"description": "Class name applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the badge `span` element",
- "conditions": "anchorOrigin={{ 'bottom', 'right' }} overlap=\"rectangular\"
"
+ "conditions": "anchorOrigin={{ 'bottom', 'right' }}
"
},
- "anchorOriginTopLeftRectangular": {
+ "anchorOriginTopLeft": {
"description": "Class name applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the badge `span` element",
- "conditions": "anchorOrigin={{ 'top', 'left' }} overlap=\"rectangular\"
"
+ "conditions": "anchorOrigin={{ 'top', 'left' }}
"
},
- "anchorOriginBottomLeftRectangular": {
+ "anchorOriginBottomLeft": {
"description": "Class name applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the badge `span` element",
- "conditions": "anchorOrigin={{ 'bottom', 'left' }} overlap=\"rectangular\"
"
- },
- "anchorOriginTopRightCircular": {
- "description": "Class name applied to {{nodeName}} if {{conditions}}.",
- "nodeName": "the badge `span` element",
- "conditions": "anchorOrigin={{ 'top', 'right' }} overlap=\"circular\"
"
- },
- "anchorOriginBottomRightCircular": {
- "description": "Class name applied to {{nodeName}} if {{conditions}}.",
- "nodeName": "the badge `span` element",
- "conditions": "anchorOrigin={{ 'bottom', 'right' }} overlap=\"circular\"
"
- },
- "anchorOriginTopLeftCircular": {
- "description": "Class name applied to {{nodeName}} if {{conditions}}.",
- "nodeName": "the badge `span` element",
- "conditions": "anchorOrigin={{ 'top', 'left' }} overlap=\"circular\"
"
- },
- "anchorOriginBottomLeftCircular": {
- "description": "Class name applied to {{nodeName}} if {{conditions}}.",
- "nodeName": "the badge `span` element",
- "conditions": "anchorOrigin={{ 'bottom', 'left' }} overlap=\"circular\"
"
+ "conditions": "anchorOrigin={{ 'bottom', 'left' }}
"
},
"invisible": {
"description": "State class applied to {{nodeName}} if {{conditions}}.",
@@ -106,6 +86,56 @@
"description": "Styles applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the badge `span` element",
"conditions": "color=\"warning\"
"
+ },
+ "anchorOriginTopRightRectangular": {
+ "description": "Class name applied to {{nodeName}} if {{conditions}}.",
+ "nodeName": "the badge `span` element",
+ "conditions": "anchorOrigin={{ 'top', 'right' }} overlap=\"rectangular\"
"
+ },
+ "anchorOriginBottomRightRectangular": {
+ "description": "Class name applied to {{nodeName}} if {{conditions}}.",
+ "nodeName": "the badge `span` element",
+ "conditions": "anchorOrigin={{ 'bottom', 'right' }} overlap=\"rectangular\"
"
+ },
+ "anchorOriginTopLeftRectangular": {
+ "description": "Class name applied to {{nodeName}} if {{conditions}}.",
+ "nodeName": "the badge `span` element",
+ "conditions": "anchorOrigin={{ 'top', 'left' }} overlap=\"rectangular\"
"
+ },
+ "anchorOriginBottomLeftRectangular": {
+ "description": "Class name applied to {{nodeName}} if {{conditions}}.",
+ "nodeName": "the badge `span` element",
+ "conditions": "anchorOrigin={{ 'bottom', 'left' }} overlap=\"rectangular\"
"
+ },
+ "anchorOriginTopRightCircular": {
+ "description": "Class name applied to {{nodeName}} if {{conditions}}.",
+ "nodeName": "the badge `span` element",
+ "conditions": "anchorOrigin={{ 'top', 'right' }} overlap=\"circular\"
"
+ },
+ "anchorOriginBottomRightCircular": {
+ "description": "Class name applied to {{nodeName}} if {{conditions}}.",
+ "nodeName": "the badge `span` element",
+ "conditions": "anchorOrigin={{ 'bottom', 'right' }} overlap=\"circular\"
"
+ },
+ "anchorOriginTopLeftCircular": {
+ "description": "Class name applied to {{nodeName}} if {{conditions}}.",
+ "nodeName": "the badge `span` element",
+ "conditions": "anchorOrigin={{ 'top', 'left' }} overlap=\"circular\"
"
+ },
+ "anchorOriginBottomLeftCircular": {
+ "description": "Class name applied to {{nodeName}} if {{conditions}}.",
+ "nodeName": "the badge `span` element",
+ "conditions": "anchorOrigin={{ 'bottom', 'left' }} overlap=\"circular\"
"
+ },
+ "overlapRectangular": {
+ "description": "Class name applied to {{nodeName}} if {{conditions}}.",
+ "nodeName": "the badge `span` element",
+ "conditions": "overlap=\"rectangular\"
"
+ },
+ "overlapCircular": {
+ "description": "Class name applied to {{nodeName}} if {{conditions}}.",
+ "nodeName": "the badge `span` element",
+ "conditions": "overlap=\"circular\"
"
}
}
}
diff --git a/packages/mui-base/src/BadgeUnstyled/BadgeUnstyled.d.ts b/packages/mui-base/src/BadgeUnstyled/BadgeUnstyled.d.ts
index 6ebfb8d4bd6b15..fefd2b2d99fd88 100644
--- a/packages/mui-base/src/BadgeUnstyled/BadgeUnstyled.d.ts
+++ b/packages/mui-base/src/BadgeUnstyled/BadgeUnstyled.d.ts
@@ -1,88 +1,5 @@
-import * as React from 'react';
-import { OverridableComponent, OverridableTypeMap, OverrideProps } from '@mui/types';
-import { BadgeUnstyledClasses } from './badgeUnstyledClasses';
-
-export interface BadgeOrigin {
- vertical: 'top' | 'bottom';
- horizontal: 'left' | 'right';
-}
-
-export interface BadgeUnstyledComponentsPropsOverrides {}
-
-export interface BadgeUnstyledTypeMap {
- props: P & {
- /**
- * The anchor of the badge.
- * @default {
- * vertical: 'top',
- * horizontal: 'right',
- * }
- */
- anchorOrigin?: BadgeOrigin;
- /**
- * The components used for each slot inside the Badge.
- * Either a string to use a HTML element or a component.
- * @default {}
- */
- components?: {
- Root?: React.ElementType;
- Badge?: React.ElementType;
- };
- /**
- * The props used for each slot inside the Badge.
- * @default {}
- */
- componentsProps?: {
- root?: React.HTMLAttributes & BadgeUnstyledComponentsPropsOverrides;
- badge?: React.HTMLAttributes & BadgeUnstyledComponentsPropsOverrides;
- };
- /**
- * Wrapped shape the badge should overlap.
- * @default 'rectangular'
- */
- overlap?: 'rectangular' | 'circular';
- /**
- * The content rendered within the badge.
- */
- badgeContent?: React.ReactNode;
- /**
- * The badge will be added relative to this node.
- */
- children?: React.ReactNode;
- /**
- * Override or extend the styles applied to the component.
- */
- classes?: Partial;
- /**
- * If `true`, the badge is invisible.
- */
- invisible?: boolean;
- /**
- * Max count to show.
- * @default 99
- */
- max?: number;
- /**
- * Controls whether the badge is hidden when `badgeContent` is zero.
- * @default false
- */
- showZero?: boolean;
- /**
- * The variant to use.
- * @default 'standard'
- */
- variant?: string;
- };
- defaultComponent: D;
-}
-
-/**
- * Utility to create component types that inherit props from BadgeUnstyled.
- */
-export interface ExtendBadgeUnstyledTypeMap {
- props: M['props'] & BadgeUnstyledTypeMap['props'];
- defaultComponent: M['defaultComponent'];
-}
+import { OverridableComponent, OverridableTypeMap } from '@mui/types';
+import { ExtendBadgeUnstyledTypeMap, BadgeUnstyledTypeMap } from './BadgeUnstyledProps';
export type ExtendBadgeUnstyled = OverridableComponent<
ExtendBadgeUnstyledTypeMap
@@ -100,9 +17,4 @@ export type ExtendBadgeUnstyled = OverridableCompo
*/
declare const BadgeUnstyled: OverridableComponent;
-export type BadgeUnstyledProps<
- D extends React.ElementType = BadgeUnstyledTypeMap['defaultComponent'],
- P = {},
-> = OverrideProps, D>;
-
export default BadgeUnstyled;
diff --git a/packages/mui-base/src/BadgeUnstyled/BadgeUnstyled.js b/packages/mui-base/src/BadgeUnstyled/BadgeUnstyled.js
index d680bf5517cdda..3a7e5f9a18b686 100644
--- a/packages/mui-base/src/BadgeUnstyled/BadgeUnstyled.js
+++ b/packages/mui-base/src/BadgeUnstyled/BadgeUnstyled.js
@@ -1,22 +1,21 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
-import { unstable_capitalize as capitalize, usePreviousProps } from '@mui/utils';
+import { unstable_capitalize as capitalize } from '@mui/utils';
import composeClasses from '../composeClasses';
import appendOwnerState from '../utils/appendOwnerState';
+import useBadge from './useBadge';
import { getBadgeUtilityClass } from './badgeUnstyledClasses';
const useUtilityClasses = (ownerState) => {
- const { variant, anchorOrigin, overlap, invisible, classes } = ownerState;
+ const { variant, anchorOrigin, invisible, classes } = ownerState;
const slots = {
root: ['root'],
badge: [
'badge',
variant,
- `anchorOrigin${capitalize(anchorOrigin.vertical)}${capitalize(
- anchorOrigin.horizontal,
- )}${capitalize(overlap)}`,
+ `anchorOrigin${capitalize(anchorOrigin.vertical)}${capitalize(anchorOrigin.horizontal)}`,
invisible && 'invisible',
],
};
@@ -39,39 +38,18 @@ const BadgeUnstyled = React.forwardRef(function BadgeUnstyled(props, ref) {
componentsProps = {},
invisible: invisibleProp,
max: maxProp = 99,
- overlap: overlapProp = 'rectangular',
showZero = false,
variant: variantProp = 'standard',
- /* eslint-disable react/prop-types */
- theme,
...other
} = props;
- const prevProps = usePreviousProps({
+ const { anchorOrigin, badgeContent, max, variant, displayValue, invisible } = useBadge({
+ ...props,
anchorOrigin: anchorOriginProp,
- badgeContent: badgeContentProp,
max: maxProp,
- overlap: overlapProp,
variant: variantProp,
});
- let invisible = invisibleProp;
-
- if (
- invisibleProp == null &&
- ((badgeContentProp === 0 && !showZero) || (badgeContentProp == null && variantProp !== 'dot'))
- ) {
- invisible = true;
- }
-
- const {
- anchorOrigin = anchorOriginProp,
- badgeContent,
- max = maxProp,
- overlap = overlapProp,
- variant = variantProp,
- } = invisible ? prevProps : props;
-
const ownerState = {
...props,
anchorOrigin,
@@ -79,16 +57,10 @@ const BadgeUnstyled = React.forwardRef(function BadgeUnstyled(props, ref) {
classes: classesProp,
invisible,
max,
- overlap,
variant,
+ showZero,
};
- let displayValue = '';
-
- if (variant !== 'dot') {
- displayValue = badgeContent > max ? `${max}+` : badgeContent;
- }
-
const classes = useUtilityClasses(ownerState);
const Root = component || components.Root || 'span';
@@ -172,11 +144,6 @@ BadgeUnstyled.propTypes /* remove-proptypes */ = {
* @default 99
*/
max: PropTypes.number,
- /**
- * Wrapped shape the badge should overlap.
- * @default 'rectangular'
- */
- overlap: PropTypes.oneOf(['circular', 'rectangular']),
/**
* Controls whether the badge is hidden when `badgeContent` is zero.
* @default false
diff --git a/packages/mui-base/src/BadgeUnstyled/BadgeUnstyledProps.ts b/packages/mui-base/src/BadgeUnstyled/BadgeUnstyledProps.ts
new file mode 100644
index 00000000000000..5a9fbfec94588a
--- /dev/null
+++ b/packages/mui-base/src/BadgeUnstyled/BadgeUnstyledProps.ts
@@ -0,0 +1,87 @@
+import * as React from 'react';
+import { OverrideProps, OverridableTypeMap } from '@mui/types';
+import { BadgeUnstyledClasses } from './badgeUnstyledClasses';
+
+export interface BadgeOrigin {
+ vertical: 'top' | 'bottom';
+ horizontal: 'left' | 'right';
+}
+
+export interface BadgeUnstyledComponentsPropsOverrides {}
+
+export interface BadgeUnstyledTypeMap {
+ props: P & {
+ /**
+ * The anchor of the badge.
+ * @default {
+ * vertical: 'top',
+ * horizontal: 'right',
+ * }
+ */
+ anchorOrigin?: BadgeOrigin;
+ /**
+ * The components used for each slot inside the Badge.
+ * Either a string to use a HTML element or a component.
+ * @default {}
+ */
+ components?: {
+ Root?: React.ElementType;
+ Badge?: React.ElementType;
+ };
+ /**
+ * The props used for each slot inside the Badge.
+ * @default {}
+ */
+ componentsProps?: {
+ root?: React.HTMLAttributes & BadgeUnstyledComponentsPropsOverrides;
+ badge?: React.HTMLAttributes & BadgeUnstyledComponentsPropsOverrides;
+ };
+ /**
+ * The content rendered within the badge.
+ */
+ badgeContent?: React.ReactNode;
+ /**
+ * The badge will be added relative to this node.
+ */
+ children?: React.ReactNode;
+ /**
+ * Override or extend the styles applied to the component.
+ */
+ classes?: Partial;
+ /**
+ * If `true`, the badge is invisible.
+ */
+ invisible?: boolean;
+ /**
+ * Max count to show.
+ * @default 99
+ */
+ max?: number;
+ /**
+ * Controls whether the badge is hidden when `badgeContent` is zero.
+ * @default false
+ */
+ showZero?: boolean;
+ /**
+ * The variant to use.
+ * @default 'standard'
+ */
+ variant?: string;
+ };
+ defaultComponent: D;
+}
+
+/**
+ * Utility to create component types that inherit props from BadgeUnstyled.
+ */
+export interface ExtendBadgeUnstyledTypeMap {
+ props: M['props'] & BadgeUnstyledTypeMap['props'];
+ defaultComponent: M['defaultComponent'];
+}
+
+type BadgeUnstyledProps<
+ D extends React.ElementType = BadgeUnstyledTypeMap['defaultComponent'],
+ P = {},
+> = OverrideProps, D>;
+
+export default BadgeUnstyledProps;
diff --git a/packages/mui-base/src/BadgeUnstyled/badgeUnstyledClasses.ts b/packages/mui-base/src/BadgeUnstyled/badgeUnstyledClasses.ts
index 48b66ee50cdda5..92382836a8205d 100644
--- a/packages/mui-base/src/BadgeUnstyled/badgeUnstyledClasses.ts
+++ b/packages/mui-base/src/BadgeUnstyled/badgeUnstyledClasses.ts
@@ -10,22 +10,14 @@ export interface BadgeUnstyledClasses {
dot: string;
/** Class name applied to the badge `span` element if `variant="standard"`. */
standard: string;
- /** Class name applied to the badge `span` element if `anchorOrigin={{ 'top', 'right' }} overlap="rectangular"`. */
- anchorOriginTopRightRectangular: string;
- /** Class name applied to the badge `span` element if `anchorOrigin={{ 'bottom', 'right' }} overlap="rectangular"`. */
- anchorOriginBottomRightRectangular: string;
- /** Class name applied to the badge `span` element if `anchorOrigin={{ 'top', 'left' }} overlap="rectangular"`. */
- anchorOriginTopLeftRectangular: string;
- /** Class name applied to the badge `span` element if `anchorOrigin={{ 'bottom', 'left' }} overlap="rectangular"`. */
- anchorOriginBottomLeftRectangular: string;
- /** Class name applied to the badge `span` element if `anchorOrigin={{ 'top', 'right' }} overlap="circular"`. */
- anchorOriginTopRightCircular: string;
- /** Class name applied to the badge `span` element if `anchorOrigin={{ 'bottom', 'right' }} overlap="circular"`. */
- anchorOriginBottomRightCircular: string;
- /** Class name applied to the badge `span` element if `anchorOrigin={{ 'top', 'left' }} overlap="circular"`. */
- anchorOriginTopLeftCircular: string;
- /** Class name applied to the badge `span` element if `anchorOrigin={{ 'bottom', 'left' }} overlap="circular"`. */
- anchorOriginBottomLeftCircular: string;
+ /** Class name applied to the badge `span` element if `anchorOrigin={{ 'top', 'right' }}`. */
+ anchorOriginTopRight: string;
+ /** Class name applied to the badge `span` element if `anchorOrigin={{ 'bottom', 'right' }}`. */
+ anchorOriginBottomRight: string;
+ /** Class name applied to the badge `span` element if `anchorOrigin={{ 'top', 'left' }}`. */
+ anchorOriginTopLeft: string;
+ /** Class name applied to the badge `span` element if `anchorOrigin={{ 'bottom', 'left' }}`. */
+ anchorOriginBottomLeft: string;
/** State class applied to the badge `span` element if `invisible={true}`. */
invisible: string;
}
@@ -41,14 +33,10 @@ const badgeUnstyledClasses: BadgeUnstyledClasses = generateUtilityClasses('MuiBa
'badge',
'dot',
'standard',
- 'anchorOriginTopLeftCircular',
- 'anchorOriginTopLeftRectangular',
- 'anchorOriginTopRightCircular',
- 'anchorOriginTopRightRectangular',
- 'anchorOriginBottomLeftCircular',
- 'anchorOriginBottomLeftRectangular',
- 'anchorOriginBottomRightCircular',
- 'anchorOriginBottomRightRectangular',
+ 'anchorOriginTopLeft',
+ 'anchorOriginTopRight',
+ 'anchorOriginBottomLeft',
+ 'anchorOriginBottomRight',
'invisible',
]);
diff --git a/packages/mui-base/src/BadgeUnstyled/index.d.ts b/packages/mui-base/src/BadgeUnstyled/index.d.ts
index 179d10d6514903..0f472bdce5332b 100644
--- a/packages/mui-base/src/BadgeUnstyled/index.d.ts
+++ b/packages/mui-base/src/BadgeUnstyled/index.d.ts
@@ -1,5 +1,11 @@
export { default } from './BadgeUnstyled';
export * from './BadgeUnstyled';
+export { default as useBadge } from './useBadge';
+export * from './useBadge';
+
+export { default as BadgeUnstyledProps } from './BadgeUnstyledProps';
+export * from './BadgeUnstyledProps';
+
export { default as badgeUnstyledClasses } from './badgeUnstyledClasses';
export * from './badgeUnstyledClasses';
diff --git a/packages/mui-base/src/BadgeUnstyled/index.js b/packages/mui-base/src/BadgeUnstyled/index.js
index 1b99c3b126d89c..4aa33b06390b8f 100644
--- a/packages/mui-base/src/BadgeUnstyled/index.js
+++ b/packages/mui-base/src/BadgeUnstyled/index.js
@@ -1,2 +1,3 @@
export { default } from './BadgeUnstyled';
+export { default as useBadge } from './useBadge';
export { default as badgeUnstyledClasses, getBadgeUtilityClass } from './badgeUnstyledClasses';
diff --git a/packages/mui-base/src/BadgeUnstyled/useBadge.ts b/packages/mui-base/src/BadgeUnstyled/useBadge.ts
new file mode 100644
index 00000000000000..ac5c2f5990f11c
--- /dev/null
+++ b/packages/mui-base/src/BadgeUnstyled/useBadge.ts
@@ -0,0 +1,64 @@
+import * as React from 'react';
+import { usePreviousProps } from '@mui/utils';
+import BadgeUnstyledProps from './BadgeUnstyledProps';
+
+export interface UseBadgeProps {
+ anchorOrigin: BadgeUnstyledProps['anchorOrigin'];
+ badgeContent: BadgeUnstyledProps['badgeContent'];
+ invisible: BadgeUnstyledProps['invisible'];
+ max: BadgeUnstyledProps['max'];
+ showZero: BadgeUnstyledProps['showZero'];
+ variant: BadgeUnstyledProps['variant'];
+}
+
+export default function useBadge(props: UseBadgeProps) {
+ const {
+ anchorOrigin: anchorOriginProp = {
+ vertical: 'top',
+ horizontal: 'right',
+ },
+ badgeContent: badgeContentProp,
+ invisible: invisibleProp,
+ max: maxProp = 99,
+ showZero = false,
+ variant: variantProp = 'standard',
+ } = props;
+
+ const prevProps: Partial = usePreviousProps({
+ anchorOrigin: anchorOriginProp,
+ badgeContent: badgeContentProp,
+ max: maxProp,
+ variant: variantProp,
+ });
+
+ let invisible = invisibleProp;
+
+ if (
+ invisibleProp == null &&
+ ((badgeContentProp === 0 && !showZero) || (badgeContentProp == null && variantProp !== 'dot'))
+ ) {
+ invisible = true;
+ }
+
+ const {
+ anchorOrigin = anchorOriginProp,
+ badgeContent,
+ max = maxProp,
+ variant = variantProp,
+ } = invisible ? prevProps : props;
+
+ let displayValue: React.ReactNode = '';
+
+ if (variant !== 'dot') {
+ displayValue = badgeContent && Number(badgeContent) > max ? `${max}+` : badgeContent;
+ }
+
+ return {
+ anchorOrigin,
+ badgeContent,
+ invisible,
+ max,
+ variant,
+ displayValue,
+ };
+}
diff --git a/packages/mui-material/src/Badge/Badge.d.ts b/packages/mui-material/src/Badge/Badge.d.ts
index 0627880c6fec6b..99c1ad1df5f4e7 100644
--- a/packages/mui-material/src/Badge/Badge.d.ts
+++ b/packages/mui-material/src/Badge/Badge.d.ts
@@ -30,6 +30,26 @@ export type BadgeTypeMap<
colorSuccess?: string;
/** Styles applied to the badge `span` element if `color="warning"`. */
colorWarning?: string;
+ /** Class name applied to the badge `span` element if `anchorOrigin={{ 'top', 'right' }} overlap="rectangular"`. */
+ anchorOriginTopRightRectangular: string;
+ /** Class name applied to the badge `span` element if `anchorOrigin={{ 'bottom', 'right' }} overlap="rectangular"`. */
+ anchorOriginBottomRightRectangular: string;
+ /** Class name applied to the badge `span` element if `anchorOrigin={{ 'top', 'left' }} overlap="rectangular"`. */
+ anchorOriginTopLeftRectangular: string;
+ /** Class name applied to the badge `span` element if `anchorOrigin={{ 'bottom', 'left' }} overlap="rectangular"`. */
+ anchorOriginBottomLeftRectangular: string;
+ /** Class name applied to the badge `span` element if `anchorOrigin={{ 'top', 'right' }} overlap="circular"`. */
+ anchorOriginTopRightCircular: string;
+ /** Class name applied to the badge `span` element if `anchorOrigin={{ 'bottom', 'right' }} overlap="circular"`. */
+ anchorOriginBottomRightCircular: string;
+ /** Class name applied to the badge `span` element if `anchorOrigin={{ 'top', 'left' }} overlap="circular"`. */
+ anchorOriginTopLeftCircular: string;
+ /** Class name applied to the badge `span` element if `anchorOrigin={{ 'bottom', 'left' }} overlap="circular"`. */
+ anchorOriginBottomLeftCircular: string;
+ /** Class name applied to the badge `span` element if `overlap="rectangular"`. */
+ overlapRectangular: string;
+ /** Class name applied to the badge `span` element if `overlap="circular"`. */
+ overlapCircular: string;
};
/**
* The color of the component. It supports those theme colors that make sense for this component.
@@ -39,6 +59,11 @@ export type BadgeTypeMap<
'primary' | 'secondary' | 'default' | 'error' | 'info' | 'success' | 'warning',
BadgePropsColorOverrides
>;
+ /**
+ * Wrapped shape the badge should overlap.
+ * @default 'rectangular'
+ */
+ overlap?: 'rectangular' | 'circular';
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
diff --git a/packages/mui-material/src/Badge/Badge.js b/packages/mui-material/src/Badge/Badge.js
index c670f55e6f1033..3144241c90d65a 100644
--- a/packages/mui-material/src/Badge/Badge.js
+++ b/packages/mui-material/src/Badge/Badge.js
@@ -17,6 +17,17 @@ export const badgeClasses = {
'colorSecondary',
'colorSuccess',
'colorWarning',
+ 'overlapRectangular',
+ 'overlapCircular',
+ // TODO: v6 remove the overlap value from these class keys
+ 'anchorOriginTopLeftCircular',
+ 'anchorOriginTopLeftRectangular',
+ 'anchorOriginTopRightCircular',
+ 'anchorOriginTopRightRectangular',
+ 'anchorOriginBottomLeftCircular',
+ 'anchorOriginBottomLeftRectangular',
+ 'anchorOriginBottomRightCircular',
+ 'anchorOriginBottomRightRectangular',
]),
};
@@ -24,14 +35,23 @@ const RADIUS_STANDARD = 10;
const RADIUS_DOT = 4;
const extendUtilityClasses = (ownerState) => {
- const { color, classes = {} } = ownerState;
+ const { color, anchorOrigin, overlap, classes = {} } = ownerState;
return {
...classes,
- badge: clsx(classes.badge, {
- [getBadgeUtilityClass(`color${capitalize(color)}`)]: color !== 'default',
- [classes[`color${capitalize(color)}`]]: color !== 'default',
- }),
+ badge: clsx(
+ classes.badge,
+ getBadgeUtilityClass(
+ `anchorOrigin${capitalize(anchorOrigin.vertical)}${capitalize(
+ anchorOrigin.horizontal,
+ )}${capitalize(overlap)}`,
+ ),
+ getBadgeUtilityClass(`overlap${capitalize(overlap)}`),
+ {
+ [getBadgeUtilityClass(`color${capitalize(color)}`)]: color !== 'default',
+ [classes[`color${capitalize(color)}`]]: color !== 'default',
+ },
+ ),
};
};
@@ -200,9 +220,14 @@ const shouldSpreadAdditionalProps = (Slot) => {
const Badge = React.forwardRef(function Badge(inProps, ref) {
const props = useThemeProps({ props: inProps, name: 'MuiBadge' });
const {
+ anchorOrigin: anchorOriginProp = {
+ vertical: 'top',
+ horizontal: 'right',
+ },
component = 'span',
components = {},
componentsProps = {},
+ overlap: overlapProp = 'rectangular',
color: colorProp = 'default',
invisible: invisibleProp,
badgeContent: badgeContentProp,
@@ -212,7 +237,9 @@ const Badge = React.forwardRef(function Badge(inProps, ref) {
} = props;
const prevProps = usePreviousProps({
+ anchorOrigin: anchorOriginProp,
color: colorProp,
+ overlap: overlapProp,
});
let invisible = invisibleProp;
@@ -224,13 +251,18 @@ const Badge = React.forwardRef(function Badge(inProps, ref) {
invisible = true;
}
- const { color = colorProp } = invisible ? prevProps : props;
+ const {
+ color = colorProp,
+ overlap = overlapProp,
+ anchorOrigin = anchorOriginProp,
+ } = invisible ? prevProps : props;
- const ownerState = { ...props, invisible, color };
+ const ownerState = { ...props, anchorOrigin, invisible, color, overlap };
const classes = extendUtilityClasses(ownerState);
return (
{
const isExternal = filename !== tsFile;
- const implementedByUnstyledVariant = filename === unstyledFile;
+ const implementedByUnstyledVariant =
+ filename === unstyledFile || filename === unstyledPropsFile;
if (!isExternal || implementedByUnstyledVariant) {
shouldDocument = true;
}