Skip to content

Commit

Permalink
[Badge][base] Drop component prop (#37028)
Browse files Browse the repository at this point in the history
  • Loading branch information
hbjORbj authored Apr 28, 2023
1 parent 7e8b4f4 commit 590c1b3
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 34 deletions.
34 changes: 19 additions & 15 deletions docs/data/base/components/badge/badge.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,27 +59,17 @@ The Badge component is composed of a root `<span>` that houses the element that
</span>
```

### Slot props
### Custom structure

:::info
The following props are available on all non-utility Base components.
See [Usage](/base/getting-started/usage/) for full details.
:::

Use the `component` prop to override the root slot with a custom element:

```jsx
<Badge component="div" />
```

Use the `slots` prop to override any interior slots in addition to the root:
Use the `slots` prop to override the root or any other interior slot:

```jsx
<Badge slots={{ root: 'div', badge: 'div' }} />
```

:::warning
If the root element is customized with both the `component` and `slots` props, then `component` will take precedence.
:::info
The `slots` prop is available on all non-utility Base components.
See [Overriding component structure](/base/guides/overriding-component-structure/) for full details.
:::

Use the `slotProps` prop to pass custom props to internal slots.
Expand All @@ -89,6 +79,20 @@ The following code snippet applies a CSS class called `my-badge` to the badge sl
<Badge slotProps={{ badge: { className: 'my-badge' } }} />
```

#### Usage with TypeScript

In TypeScript, you can specify the custom component type used in the `slots.root` as a generic parameter of the unstyled component. This way, you can safely provide the custom root's props directly on the component:

```tsx
<Badge<typeof CustomComponent> slots={{ root: CustomComponent }} customProp />
```

The same applies for props specific to custom primitive elements:

```tsx
<Badge<'img'> slots={{ root: 'img' }} src="badge.png" />
```

## Hook

```jsx
Expand Down
2 changes: 1 addition & 1 deletion docs/data/base/components/button/button.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Similarly, `<Button slots={{ root: "span" }} type="reset">` will not reset its p

#### Usage with TypeScript

In TypeScript, you can specify the custom component type used in the `slots.root` as a generic to the unstyled component. This way, you can safely provide the custom compoenent's props directly on the compnent:
In TypeScript, you can specify the custom component type used in the `slots.root` as a generic parameter of the unstyled component. This way, you can safely provide the custom root's props directly on the component:

```tsx
<Button<typeof CustomComponent> slots={{ root: CustomComponent }} customProp />
Expand Down
1 change: 0 additions & 1 deletion docs/pages/base/api/badge.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"props": {
"badgeContent": { "type": { "name": "node" } },
"children": { "type": { "name": "node" } },
"component": { "type": { "name": "elementType" } },
"invisible": { "type": { "name": "bool" }, "default": "false" },
"max": { "type": { "name": "number" }, "default": "99" },
"showZero": { "type": { "name": "bool" }, "default": "false" },
Expand Down
1 change: 0 additions & 1 deletion docs/translations/api-docs-base/badge/badge.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"propDescriptions": {
"badgeContent": "The content rendered within the badge.",
"children": "The badge will be added relative to this node.",
"component": "The component used for the root node. Either a string to use a HTML element or a component.",
"invisible": "If <code>true</code>, the badge is invisible.",
"max": "Max count to show.",
"showZero": "Controls whether the badge is hidden when <code>badgeContent</code> is zero.",
Expand Down
38 changes: 32 additions & 6 deletions packages/mui-base/src/Badge/Badge.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,48 @@ const polymorphicComponentTest = () => {
return <div />;
};

const CustomRoot = function CustomRoot() {
return <div />;
};

return (
<div>
{/* @ts-expect-error */}
<Badge invalidProp={0} />

<Badge component="a" href="#" />
<Badge<'a'>
slots={{
root: 'a',
}}
href="#"
/>

<Badge component={CustomComponent} stringProp="test" numberProp={0} />
{/* @ts-expect-error */}
<Badge component={CustomComponent} />
<Badge<typeof CustomComponent>
slots={{
root: CustomComponent,
}}
stringProp="test"
numberProp={0}
/>

{/* @ts-expect-error required props not specified */}
<Badge<typeof CustomComponent>
slots={{
root: CustomComponent,
}}
/>

<Badge
component="button"
slots={{
root: 'button',
}}
onClick={(e: React.MouseEvent<HTMLButtonElement>) => e.currentTarget.checkValidity()}
/>

<Badge<'button'>
component="button"
slots={{
root: 'button',
}}
ref={(elem) => {
expectType<HTMLButtonElement | null, typeof elem>(elem);
}}
Expand All @@ -52,6 +76,8 @@ const polymorphicComponentTest = () => {
e.currentTarget.checkValidity();
}}
/>

<Badge<'svg'> viewBox="" />
</div>
);
};
1 change: 1 addition & 0 deletions packages/mui-base/src/Badge/Badge.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ describe('<Badge />', () => {
expectedClassName: classes.badge,
},
},
skip: ['componentProp'],
}),
);
});
14 changes: 4 additions & 10 deletions packages/mui-base/src/Badge/Badge.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { OverridableComponent } from '@mui/types';
import { PolymorphicComponent } from '../utils/PolymorphicComponent';
import composeClasses from '../composeClasses';
import useBadge from '../useBadge';
import { getBadgeUtilityClass } from './badgeClasses';
Expand Down Expand Up @@ -40,7 +40,6 @@ const Badge = React.forwardRef(function Badge<RootComponentType extends React.El
) {
const {
badgeContent: badgeContentProp,
component,
children,
invisible: invisibleProp,
max: maxProp = 99,
Expand All @@ -65,7 +64,7 @@ const Badge = React.forwardRef(function Badge<RootComponentType extends React.El

const classes = useUtilityClasses(ownerState);

const Root = component || slots.root || 'span';
const Root = slots.root ?? 'span';
const rootProps: WithOptionalOwnerState<BadgeRootSlotProps> = useSlotProps({
elementType: Root,
externalSlotProps: slotProps.root,
Expand All @@ -77,7 +76,7 @@ const Badge = React.forwardRef(function Badge<RootComponentType extends React.El
className: classes.root,
});

const BadgeComponent = slots.badge || 'span';
const BadgeComponent = slots.badge ?? 'span';
const badgeProps: WithOptionalOwnerState<BadgeBadgeSlotProps> = useSlotProps({
elementType: BadgeComponent,
externalSlotProps: slotProps.badge,
Expand All @@ -91,7 +90,7 @@ const Badge = React.forwardRef(function Badge<RootComponentType extends React.El
<BadgeComponent {...badgeProps}>{displayValue}</BadgeComponent>
</Root>
);
}) as OverridableComponent<BadgeTypeMap>;
}) as PolymorphicComponent<BadgeTypeMap>;

Badge.propTypes /* remove-proptypes */ = {
// ----------------------------- Warning --------------------------------
Expand All @@ -106,11 +105,6 @@ Badge.propTypes /* remove-proptypes */ = {
* The badge will be added relative to this node.
*/
children: PropTypes.node,
/**
* The component used for the root node.
* Either a string to use a HTML element or a component.
*/
component: PropTypes.elementType,
/**
* If `true`, the badge is invisible.
* @default false
Expand Down

0 comments on commit 590c1b3

Please sign in to comment.