Skip to content

Commit

Permalink
[Switch][base] Drop component prop (mui#37053)
Browse files Browse the repository at this point in the history
  • Loading branch information
hbjORbj authored and binh1298 committed May 17, 2023
1 parent 7c97a80 commit d5a8479
Show file tree
Hide file tree
Showing 13 changed files with 162 additions and 62 deletions.
32 changes: 28 additions & 4 deletions docs/data/base/components/switch/UnstyledSwitchIntroduction.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,34 @@ export default function UnstyledSwitches() {

return (
<div>
<Switch component={Root} {...label} defaultChecked />
<Switch component={Root} {...label} />
<Switch component={Root} {...label} defaultChecked disabled />
<Switch component={Root} {...label} disabled />
<Switch
slots={{
root: Root,
}}
{...label}
defaultChecked
/>
<Switch
slots={{
root: Root,
}}
{...label}
/>
<Switch
slots={{
root: Root,
}}
{...label}
defaultChecked
disabled
/>
<Switch
slots={{
root: Root,
}}
{...label}
disabled
/>
</div>
);
}
Expand Down
32 changes: 28 additions & 4 deletions docs/data/base/components/switch/UnstyledSwitchIntroduction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,34 @@ export default function UnstyledSwitches() {

return (
<div>
<Switch component={Root} {...label} defaultChecked />
<Switch component={Root} {...label} />
<Switch component={Root} {...label} defaultChecked disabled />
<Switch component={Root} {...label} disabled />
<Switch
slots={{
root: Root,
}}
{...label}
defaultChecked
/>
<Switch
slots={{
root: Root,
}}
{...label}
/>
<Switch
slots={{
root: Root,
}}
{...label}
defaultChecked
disabled
/>
<Switch
slots={{
root: Root,
}}
{...label}
disabled
/>
</div>
);
}
Expand Down

This file was deleted.

32 changes: 28 additions & 4 deletions docs/data/base/components/switch/UnstyledSwitches.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,34 @@ export default function UnstyledSwitches() {

return (
<div>
<Switch component={Root} {...label} defaultChecked />
<Switch component={Root} {...label} />
<Switch component={Root} {...label} defaultChecked disabled />
<Switch component={Root} {...label} disabled />
<Switch
slots={{
root: Root,
}}
{...label}
defaultChecked
/>
<Switch
slots={{
root: Root,
}}
{...label}
/>
<Switch
slots={{
root: Root,
}}
{...label}
defaultChecked
disabled
/>
<Switch
slots={{
root: Root,
}}
{...label}
disabled
/>
</div>
);
}
Expand Down
32 changes: 28 additions & 4 deletions docs/data/base/components/switch/UnstyledSwitches.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,34 @@ export default function UnstyledSwitches() {

return (
<div>
<Switch component={Root} {...label} defaultChecked />
<Switch component={Root} {...label} />
<Switch component={Root} {...label} defaultChecked disabled />
<Switch component={Root} {...label} disabled />
<Switch
slots={{
root: Root,
}}
{...label}
defaultChecked
/>
<Switch
slots={{
root: Root,
}}
{...label}
/>
<Switch
slots={{
root: Root,
}}
{...label}
defaultChecked
disabled
/>
<Switch
slots={{
root: Root,
}}
{...label}
disabled
/>
</div>
);
}
Expand Down
4 changes: 0 additions & 4 deletions docs/data/base/components/switch/UnstyledSwitches.tsx.preview

This file was deleted.

26 changes: 18 additions & 8 deletions docs/data/base/components/switch/switch.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,17 @@ The Switch component is composed of a root `<span>` that houses three interior s
</span>
```

### Slot props

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

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

```jsx
<Switch slots={{ root: 'div', track: '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 @@ -77,6 +73,20 @@ The following code snippet applies a CSS class called `my-thumb` to the thumb sl
<Switch slotProps={{ thumb: { className: 'my-thumb' } }} />
```

#### 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
<Switch<typeof CustomComponent> slots={{ root: CustomComponent }} customProp />
```

The same applies for props specific to custom primitive elements:

```tsx
<Switch<'input'> slots={{ root: 'input' }} autoFocus={true} />
```

## Hook

```js
Expand Down
1 change: 0 additions & 1 deletion docs/pages/base/api/switch.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"props": {
"checked": { "type": { "name": "bool" } },
"component": { "type": { "name": "elementType" } },
"defaultChecked": { "type": { "name": "bool" } },
"disabled": { "type": { "name": "bool" } },
"onChange": { "type": { "name": "func" } },
Expand Down
1 change: 0 additions & 1 deletion docs/translations/api-docs-base/switch/switch.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"componentDescription": "The foundation for building custom-styled switches.",
"propDescriptions": {
"checked": "If <code>true</code>, the component is checked.",
"component": "The component used for the root node. Either a string to use a HTML element or a component.",
"defaultChecked": "The default checked state. Use when the component is not controlled.",
"disabled": "If <code>true</code>, the component is disabled.",
"onChange": "Callback fired when the state is changed.<br><br><strong>Signature:</strong><br><code>function(event: React.ChangeEvent&lt;HTMLInputElement&gt;) =&gt; void</code><br><em>event:</em> The event source of the callback. You can pull out the new value by accessing <code>event.target.value</code> (string). You can pull out the new checked state by accessing <code>event.target.checked</code> (boolean).",
Expand Down
31 changes: 25 additions & 6 deletions packages/mui-base/src/Switch/Switch.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,38 @@ const polymorphicComponentTest = () => {
{/* @ts-expect-error */}
<Switch invalidProp={0} />

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

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

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

<Switch<'button'>
component="button"
slots={{
root: 'button',
}}
ref={(elem) => {
expectType<HTMLButtonElement | null, typeof elem>(elem);
}}
Expand Down
1 change: 1 addition & 0 deletions packages/mui-base/src/Switch/Switch.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ describe('<Switch />', () => {
isOptional: true,
},
},
skip: ['componentProp'],
}));

describe('componentState', () => {
Expand Down
20 changes: 3 additions & 17 deletions packages/mui-base/src/Switch/Switch.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 useSwitch from '../useSwitch';
import {
Expand Down Expand Up @@ -52,7 +52,6 @@ const Switch = React.forwardRef(function Switch<RootComponentType extends React.
) {
const {
checked: checkedProp,
component,
defaultChecked,
disabled: disabledProp,
onBlur,
Expand Down Expand Up @@ -89,7 +88,7 @@ const Switch = React.forwardRef(function Switch<RootComponentType extends React.

const classes = useUtilityClasses(ownerState);

const Root: React.ElementType = component ?? slots.root ?? 'span';
const Root: React.ElementType = slots.root ?? 'span';
const rootProps: WithOptionalOwnerState<SwitchRootSlotProps> = useSlotProps({
elementType: Root,
externalSlotProps: slotProps.root,
Expand Down Expand Up @@ -133,7 +132,7 @@ const Switch = React.forwardRef(function Switch<RootComponentType extends React.
<Input {...inputProps} />
</Root>
);
}) as OverridableComponent<SwitchTypeMap>;
}) as PolymorphicComponent<SwitchTypeMap>;

Switch.propTypes /* remove-proptypes */ = {
// ----------------------------- Warning --------------------------------
Expand All @@ -144,15 +143,6 @@ Switch.propTypes /* remove-proptypes */ = {
* If `true`, the component is checked.
*/
checked: PropTypes.bool,
/**
* @ignore
*/
children: PropTypes.node,
/**
* The component used for the root node.
* Either a string to use a HTML element or a component.
*/
component: PropTypes.elementType,
/**
* The default checked state. Use when the component is not controlled.
*/
Expand All @@ -161,10 +151,6 @@ Switch.propTypes /* remove-proptypes */ = {
* If `true`, the component is disabled.
*/
disabled: PropTypes.bool,
/**
* @ignore
*/
id: PropTypes.string,
/**
* @ignore
*/
Expand Down
8 changes: 3 additions & 5 deletions packages/mui-base/src/Switch/Switch.types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { OverrideProps, Simplify } from '@mui/types';
import { SlotComponentProps } from '../utils';
import { Simplify } from '@mui/types';
import { PolymorphicProps, SlotComponentProps } from '../utils';
import { UseSwitchInputSlotProps, UseSwitchParameters } from '../useSwitch';

export interface SwitchRootSlotPropsOverrides {}
Expand Down Expand Up @@ -63,9 +63,7 @@ export interface SwitchTypeMap<

export type SwitchProps<
RootComponentType extends React.ElementType = SwitchTypeMap['defaultComponent'],
> = OverrideProps<SwitchTypeMap<{}, RootComponentType>, RootComponentType> & {
component?: RootComponentType;
};
> = PolymorphicProps<SwitchTypeMap<{}, RootComponentType>, RootComponentType>;

export type SwitchOwnerState = Simplify<
SwitchOwnProps & {
Expand Down

0 comments on commit d5a8479

Please sign in to comment.