Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions docs/pages/material-ui/api/badge.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,20 @@
},
"name": "Badge",
"imports": ["import Badge from '@mui/material/Badge';", "import { Badge } from '@mui/material';"],
"slots": [
{
"name": "root",
"description": "The component that renders the root.",
"default": "span",
"class": "MuiBadge-root"
},
{
"name": "badge",
"description": "The component that renders the badge.",
"default": "span",
"class": "MuiBadge-badge"
}
],
"classes": [
{
"key": "anchorOriginBottomLeft",
Expand Down Expand Up @@ -141,12 +155,6 @@
"description": "Styles applied to the badge `span` element if `anchorOrigin={{ 'top', 'right' }} overlap=\"rectangular\"`.",
"isGlobal": false
},
{
"key": "badge",
"className": "MuiBadge-badge",
"description": "Styles applied to the badge `span` element.",
"isGlobal": false
},
{
"key": "colorError",
"className": "MuiBadge-colorError",
Expand Down Expand Up @@ -207,12 +215,6 @@
"description": "Styles applied to the badge `span` element if `overlap=\"rectangular\"`.",
"isGlobal": false
},
{
"key": "root",
"className": "MuiBadge-root",
"description": "Styles applied to the root element.",
"isGlobal": false
},
{
"key": "standard",
"className": "MuiBadge-standard",
Expand Down
15 changes: 6 additions & 9 deletions docs/translations/api-docs/badge/badge.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@
"showZero": {
"description": "Controls whether the badge is hidden when <code>badgeContent</code> is zero."
},
"slotProps": { "description": "The props used for each slot inside the Badge." },
"slots": {
"description": "The components used for each slot inside the Badge. Either a string to use a HTML element or a component."
},
"slotProps": { "description": "The props used for each slot inside." },
"slots": { "description": "The components used for each slot inside." },
"sx": {
"description": "The system prop that allows defining system overrides as well as additional CSS styles."
},
Expand Down Expand Up @@ -91,10 +89,6 @@
"nodeName": "the badge <code>span</code> element",
"conditions": "<code>anchorOrigin={{ 'top', 'right' }} overlap=\"rectangular\"</code>"
},
"badge": {
"description": "Styles applied to {{nodeName}}.",
"nodeName": "the badge <code>span</code> element"
},
"colorError": {
"description": "Styles applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the badge <code>span</code> element",
Expand Down Expand Up @@ -145,11 +139,14 @@
"nodeName": "the badge <code>span</code> element",
"conditions": "<code>overlap=\"rectangular\"</code>"
},
"root": { "description": "Styles applied to the root element." },
"standard": {
"description": "Styles applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the badge <code>span</code> element",
"conditions": "<code>variant=\"standard\"</code>"
}
},
"slotDescriptions": {
"badge": "The component that renders the badge.",
"root": "The component that renders the root."
}
}
60 changes: 32 additions & 28 deletions packages/mui-material/src/Badge/Badge.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import { SxProps } from '@mui/system';
import { OverridableStringUnion, Simplify } from '@mui/types';
import { SlotComponentProps } from '../utils/types';
import { CreateSlotsAndSlotProps, SlotProps } from '../utils/types';
import { Theme } from '../styles';
import { OverridableComponent, OverrideProps } from '../OverridableComponent';
import { BadgeClasses } from './badgeClasses';
Expand All @@ -11,8 +11,37 @@ export interface BadgePropsColorOverrides {}
export interface BadgeRootSlotPropsOverrides {}
export interface BadgeBadgeSlotPropsOverrides {}

export interface BadgeSlots {
/**
* The component that renders the root.
* @default span
*/
root: React.ElementType;
/**
* The component that renders the badge.
* @default span
*/
badge: React.ElementType;
}

export type BadgeSlotsAndSlotProps = CreateSlotsAndSlotProps<
BadgeSlots,
{
/**
* Props forwarded to the root slot.
* By default, the avaible props are based on the span element.
*/
root: SlotProps<'span', BadgeRootSlotPropsOverrides, BadgeOwnerState>;
/**
* Props forwarded to the label slot.
* By default, the avaible props are based on the span element.
*/
badge: SlotProps<'span', BadgeBadgeSlotPropsOverrides, BadgeOwnerState>;
}
>;

export type BadgeOwnerState = Simplify<
BadgeOwnProps & {
Omit<BadgeOwnProps, 'slotProps' | 'slots'> & {
badgeContent: React.ReactNode;
invisible: boolean;
max: number;
Expand All @@ -33,7 +62,7 @@ export interface BadgeOrigin {
horizontal?: 'left' | 'right';
}

export interface BadgeOwnProps {
export interface BadgeOwnProps extends BadgeSlotsAndSlotProps {
/**
* The anchor of the badge.
* @default {
Expand Down Expand Up @@ -103,31 +132,6 @@ export interface BadgeOwnProps {
* @default 'rectangular'
*/
overlap?: 'rectangular' | 'circular';
/**
* The props used for each slot inside the Badge.
* @default {}
*/
slotProps?: {
root?: SlotComponentProps<'span', BadgeRootSlotPropsOverrides, BadgeOwnerState>;
badge?: SlotComponentProps<'span', BadgeBadgeSlotPropsOverrides, BadgeOwnerState>;
};
/**
* The components used for each slot inside the Badge.
* Either a string to use a HTML element or a component.
* @default {}
*/
slots?: {
/**
* The component that renders the root.
* @default 'span'
*/
root?: React.ElementType;
/**
* The component that renders the badge.
* @default 'span'
*/
badge?: React.ElementType;
};
/**
* Controls whether the badge is hidden when `badgeContent` is zero.
* @default false
Expand Down
46 changes: 26 additions & 20 deletions packages/mui-material/src/Badge/Badge.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import PropTypes from 'prop-types';
import clsx from 'clsx';
import usePreviousProps from '@mui/utils/usePreviousProps';
import composeClasses from '@mui/utils/composeClasses';
import useSlotProps from '@mui/utils/useSlotProps';
import useBadge from './useBadge';
import { styled } from '../zero-styled';
import memoTheme from '../utils/memoTheme';
import createSimplePaletteValueFilter from '../utils/createSimplePaletteValueFilter';
import { useDefaultProps } from '../DefaultPropsProvider';
import capitalize from '../utils/capitalize';
import badgeClasses, { getBadgeUtilityClass } from './badgeClasses';
import useSlot from '../utils/useSlot';

const RADIUS_STANDARD = 10;
const RADIUS_DOT = 4;
Expand Down Expand Up @@ -319,29 +319,36 @@ const Badge = React.forwardRef(function Badge(inProps, ref) {
const classes = useUtilityClasses(ownerState);

// support both `slots` and `components` for backward compatibility
const RootSlot = slots?.root ?? components.Root ?? BadgeRoot;
const BadgeSlot = slots?.badge ?? components.Badge ?? BadgeBadge;

const rootSlotProps = slotProps?.root ?? componentsProps.root;
const badgeSlotProps = slotProps?.badge ?? componentsProps.badge;
const externalForwardedProps = {
slots: {
root: slots?.root ?? components.Root,
badge: slots?.badge ?? components.Badge,
},
slotProps: {
root: slotProps?.root ?? componentsProps.root,
badge: slotProps?.badge ?? componentsProps.badge,
},
};

const rootProps = useSlotProps({
elementType: RootSlot,
externalSlotProps: rootSlotProps,
externalForwardedProps: other,
const [RootSlot, rootProps] = useSlot('root', {
elementType: BadgeRoot,
externalForwardedProps: {
...externalForwardedProps,
...other,
},
ownerState,
className: clsx(classes.root, className),
ref,
additionalProps: {
ref,
as: component,
},
ownerState,
className: clsx(rootSlotProps?.className, classes.root, className),
});

const badgeProps = useSlotProps({
elementType: BadgeSlot,
externalSlotProps: badgeSlotProps,
const [BadgeSlot, badgeProps] = useSlot('badge', {
elementType: BadgeBadge,
externalForwardedProps,
ownerState,
className: clsx(classes.badge, badgeSlotProps?.className),
className: classes.badge,
});

return (
Expand Down Expand Up @@ -443,16 +450,15 @@ Badge.propTypes /* remove-proptypes */ = {
*/
showZero: PropTypes.bool,
/**
* The props used for each slot inside the Badge.
* The props used for each slot inside.
* @default {}
*/
slotProps: PropTypes.shape({
badge: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
root: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
}),
/**
* The components used for each slot inside the Badge.
* Either a string to use a HTML element or a component.
* The components used for each slot inside.
* @default {}
*/
slots: PropTypes.shape({
Expand Down
9 changes: 9 additions & 0 deletions packages/mui-material/src/Badge/Badge.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,12 @@ function classesTest() {

<Badge anchorOrigin={{ vertical: 'bottom' }} />;
<Badge anchorOrigin={{ horizontal: 'left' }} />;
<Badge
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Test for #45867

slotProps={{
badge: {
sx: {
color: 'red',
},
},
}}
/>;
8 changes: 8 additions & 0 deletions packages/mui-material/src/Badge/Badge.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ describe('<Badge />', () => {
refInstanceof: window.HTMLSpanElement,
muiName: 'MuiBadge',
testVariantProps: { color: 'secondary', variant: 'dot' },
slots: {
root: {
expectedClassName: classes.root,
},
badge: {
expectedClassName: classes.badge,
},
},
}),
);

Expand Down
Loading