From fb29877857dc2cb5be954662b0a075ed0128c41b Mon Sep 17 00:00:00 2001 From: Benny Joo Date: Thu, 27 Apr 2023 10:56:20 +0100 Subject: [PATCH 1/4] [Input][base] Drop component prop --- docs/data/base/components/input/input.md | 33 ++++++++++++------- docs/pages/base/api/input.json | 1 - .../api-docs-base/input/input.json | 1 - packages/mui-base/src/Input/Input.spec.tsx | 31 +++++++++++++---- packages/mui-base/src/Input/Input.test.tsx | 1 + packages/mui-base/src/Input/Input.tsx | 20 ++--------- packages/mui-base/src/Input/Input.types.ts | 8 ++--- 7 files changed, 53 insertions(+), 42 deletions(-) diff --git a/docs/data/base/components/input/input.md b/docs/data/base/components/input/input.md index 6100658cbe7f75..810dcf1796e1f1 100644 --- a/docs/data/base/components/input/input.md +++ b/docs/data/base/components/input/input.md @@ -54,28 +54,23 @@ The Input component is composed of a root `
` slot that houses one interior
``` -### 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: +Use the `slots.root` prop to override the root slot with a custom element: ```jsx - + ``` Use the `slots` prop to override any interior slots in addition to the root: ```jsx - + ``` -:::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. The following code snippet applies a CSS class called `my-input` to the input slot: @@ -84,6 +79,20 @@ The following code snippet applies a CSS class called `my-input` to the input sl ``` +#### 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 + slots={{ root: CustomComponent }} customProp /> +``` + +The same applies for props specific to custom primitive elements: + +```tsx + slots={{ root: 'textarea' }} rows={2} /> +``` + ## Hook ```js diff --git a/docs/pages/base/api/input.json b/docs/pages/base/api/input.json index f35a4b3eaf4a6a..980af136f07548 100644 --- a/docs/pages/base/api/input.json +++ b/docs/pages/base/api/input.json @@ -3,7 +3,6 @@ "autoComplete": { "type": { "name": "string" } }, "autoFocus": { "type": { "name": "bool" } }, "className": { "type": { "name": "string" } }, - "component": { "type": { "name": "elementType" } }, "defaultValue": { "type": { "name": "any" } }, "disabled": { "type": { "name": "bool" } }, "endAdornment": { "type": { "name": "node" } }, diff --git a/docs/translations/api-docs-base/input/input.json b/docs/translations/api-docs-base/input/input.json index 2853be93336b60..604e11cb95e78e 100644 --- a/docs/translations/api-docs-base/input/input.json +++ b/docs/translations/api-docs-base/input/input.json @@ -4,7 +4,6 @@ "autoComplete": "This prop helps users to fill forms faster, especially on mobile devices. The name can be confusing, as it's more like an autofill. You can learn more about it following the specification.", "autoFocus": "If true, the input element is focused during the first mount.", "className": "Class name applied to the root element.", - "component": "The component used for the root node. Either a string to use a HTML element or a component.", "defaultValue": "The default value. Use when the component is not controlled.", "disabled": "If true, the component is disabled. The prop defaults to the value (false) inherited from the parent FormControl component.", "endAdornment": "Trailing adornment for this input.", diff --git a/packages/mui-base/src/Input/Input.spec.tsx b/packages/mui-base/src/Input/Input.spec.tsx index f75c39e22835d7..1fe1463fef4c8b 100644 --- a/packages/mui-base/src/Input/Input.spec.tsx +++ b/packages/mui-base/src/Input/Input.spec.tsx @@ -31,19 +31,38 @@ const polymorphicComponentTest = () => { {/* @ts-expect-error */} - + + slots={{ + root: 'a', + }} + href="#" + /> - + + slots={{ + root: CustomComponent, + }} + stringProp="test" + numberProp={0} + /> {/* @ts-expect-error */} - + + slots={{ + root: CustomComponent, + }} + /> - + slots={{ + root: 'button', + }} onClick={(e: React.MouseEvent) => e.currentTarget.checkValidity()} /> - component="button" + slots={{ + root: 'button', + }} ref={(elem) => { expectType(elem); }} diff --git a/packages/mui-base/src/Input/Input.test.tsx b/packages/mui-base/src/Input/Input.test.tsx index 6a0e92ca71acf4..b7c537c132a048 100644 --- a/packages/mui-base/src/Input/Input.test.tsx +++ b/packages/mui-base/src/Input/Input.test.tsx @@ -23,6 +23,7 @@ describe('', () => { testWithElement: 'input', }, }, + skip: ['componentProp'], })); it('should render textarea without any console errors when multiline=true', () => { diff --git a/packages/mui-base/src/Input/Input.tsx b/packages/mui-base/src/Input/Input.tsx index 2ce2cad7adc565..2929059bd48c32 100644 --- a/packages/mui-base/src/Input/Input.tsx +++ b/packages/mui-base/src/Input/Input.tsx @@ -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 isHostComponent from '../utils/isHostComponent'; import { getInputUtilityClass } from './inputClasses'; import { @@ -57,7 +57,6 @@ const Input = React.forwardRef(function Input = useSlotProps({ elementType: Root, getSlotProps: getRootProps, @@ -182,7 +181,7 @@ const Input = React.forwardRef(function Input ); -}) as OverridableComponent; +}) as PolymorphicComponent; Input.propTypes /* remove-proptypes */ = { // ----------------------------- Warning -------------------------------- @@ -211,23 +210,10 @@ Input.propTypes /* remove-proptypes */ = { * If `true`, the `input` element is focused during the first mount. */ autoFocus: PropTypes.bool, - /** - * @ignore - */ - children: PropTypes.node, /** * Class name applied to the root element. */ className: PropTypes.string, - /** - * @ignore - */ - color: PropTypes.string, - /** - * The component used for the root node. - * Either a string to use a HTML element or a component. - */ - component: PropTypes.elementType, /** * The default value. Use when the component is not controlled. */ diff --git a/packages/mui-base/src/Input/Input.types.ts b/packages/mui-base/src/Input/Input.types.ts index 71d142d22defe5..e2b0a9e0ae96c0 100644 --- a/packages/mui-base/src/Input/Input.types.ts +++ b/packages/mui-base/src/Input/Input.types.ts @@ -1,8 +1,8 @@ import * as React from 'react'; -import { OverrideProps, Simplify } from '@mui/types'; +import { Simplify } from '@mui/types'; import { FormControlState } from '../FormControl'; import { UseInputParameters, UseInputRootSlotProps } from '../useInput'; -import { SlotComponentProps } from '../utils'; +import { PolymorphicProps, SlotComponentProps } from '../utils'; export interface InputRootSlotPropsOverrides {} export interface InputInputSlotPropsOverrides {} @@ -156,9 +156,7 @@ export interface InputTypeMap< export type InputProps< RootComponentType extends React.ElementType = InputTypeMap['defaultComponent'], -> = OverrideProps, RootComponentType> & { - component?: RootComponentType; -}; +> = PolymorphicProps, RootComponentType>; export type InputOwnerState = Simplify< InputOwnProps & { From a43da1ad315ff12ba26059c46c0b86e9a7bfe155 Mon Sep 17 00:00:00 2001 From: Benny Joo Date: Fri, 28 Apr 2023 10:19:12 +0100 Subject: [PATCH 2/4] improve markdown --- docs/data/base/components/input/input.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/docs/data/base/components/input/input.md b/docs/data/base/components/input/input.md index 810dcf1796e1f1..bb0e6d5111b9bb 100644 --- a/docs/data/base/components/input/input.md +++ b/docs/data/base/components/input/input.md @@ -56,13 +56,7 @@ The Input component is composed of a root `
` slot that houses one interior ### Custom structure -Use the `slots.root` prop to override the root slot with a custom element: - -```jsx - -``` - -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 From 2bd3b65c622d6af4b7686403d8efe1f8b2004f74 Mon Sep 17 00:00:00 2001 From: Benny Joo Date: Fri, 28 Apr 2023 12:41:25 +0100 Subject: [PATCH 3/4] fix markdown --- docs/data/base/components/input/input.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/data/base/components/input/input.md b/docs/data/base/components/input/input.md index bb0e6d5111b9bb..8edc8b032727cf 100644 --- a/docs/data/base/components/input/input.md +++ b/docs/data/base/components/input/input.md @@ -65,6 +65,7 @@ Use the `slots` prop to override the root or any other interior slot: :::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. The following code snippet applies a CSS class called `my-input` to the input slot: From 6f251642c0ddfacf5486dc17e182d62962462311 Mon Sep 17 00:00:00 2001 From: Benny Joo Date: Fri, 28 Apr 2023 14:28:17 +0100 Subject: [PATCH 4/4] address comment --- docs/data/base/components/input/input.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/data/base/components/input/input.md b/docs/data/base/components/input/input.md index 8edc8b032727cf..f42d11590e2139 100644 --- a/docs/data/base/components/input/input.md +++ b/docs/data/base/components/input/input.md @@ -59,7 +59,7 @@ The Input component is composed of a root `
` slot that houses one interior Use the `slots` prop to override the root or any other interior slot: ```jsx - + ``` :::info