Skip to content

Commit

Permalink
[Input][base] Drop component prop (mui#37057)
Browse files Browse the repository at this point in the history
hbjORbj authored and binh1298 committed May 17, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 8ec3176 commit 7c97a80
Showing 7 changed files with 52 additions and 46 deletions.
36 changes: 20 additions & 16 deletions docs/data/base/components/input/input.md
Original file line number Diff line number Diff line change
@@ -54,27 +54,17 @@ The Input component is composed of a root `<div>` slot that houses one interior
</div>
```

### 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
<Input component="aside" />
```

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
<Input slots={{ root: 'aside' }} />
<Input slots={{ root: 'aside', input: CustomInput }} />
```

:::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.
@@ -84,6 +74,20 @@ The following code snippet applies a CSS class called `my-input` to the input sl
<Input slotProps={{ input: { className: 'my-input' } }} />
```

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

The same applies for props specific to custom primitive elements:

```tsx
<Input<'textarea'> slots={{ root: 'textarea' }} rows={2} />
```

## Hook

```js
1 change: 0 additions & 1 deletion docs/pages/base/api/input.json
Original file line number Diff line number Diff line change
@@ -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" } },
1 change: 0 additions & 1 deletion docs/translations/api-docs-base/input/input.json
Original file line number Diff line number Diff line change
@@ -4,7 +4,6 @@
"autoComplete": "This prop helps users to fill forms faster, especially on mobile devices. The name can be confusing, as it&#39;s more like an autofill. You can learn more about it <a href=\"https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill\">following the specification</a>.",
"autoFocus": "If <code>true</code>, the <code>input</code> 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 <code>true</code>, the component is disabled. The prop defaults to the value (<code>false</code>) inherited from the parent FormControl component.",
"endAdornment": "Trailing adornment for this input.",
31 changes: 25 additions & 6 deletions packages/mui-base/src/Input/Input.spec.tsx
Original file line number Diff line number Diff line change
@@ -31,19 +31,38 @@ const polymorphicComponentTest = () => {
{/* @ts-expect-error */}
<Input invalidProp={0} />

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

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

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

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

it('should render textarea without any console errors when multiline=true', () => {
20 changes: 3 additions & 17 deletions packages/mui-base/src/Input/Input.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 isHostComponent from '../utils/isHostComponent';
import { getInputUtilityClass } from './inputClasses';
import {
@@ -57,7 +57,6 @@ const Input = React.forwardRef(function Input<RootComponentType extends React.El
autoComplete,
autoFocus,
className,
component,
defaultValue,
disabled,
endAdornment,
@@ -133,7 +132,7 @@ const Input = React.forwardRef(function Input<RootComponentType extends React.El
type,
};

const Root = component ?? slots.root ?? 'div';
const Root = slots.root ?? 'div';
const rootProps: WithOptionalOwnerState<InputRootSlotProps> = useSlotProps({
elementType: Root,
getSlotProps: getRootProps,
@@ -182,7 +181,7 @@ const Input = React.forwardRef(function Input<RootComponentType extends React.El
{endAdornment}
</Root>
);
}) as OverridableComponent<InputTypeMap>;
}) as PolymorphicComponent<InputTypeMap>;

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.
*/
8 changes: 3 additions & 5 deletions packages/mui-base/src/Input/Input.types.ts
Original file line number Diff line number Diff line change
@@ -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<InputTypeMap<{}, RootComponentType>, RootComponentType> & {
component?: RootComponentType;
};
> = PolymorphicProps<InputTypeMap<{}, RootComponentType>, RootComponentType>;

export type InputOwnerState = Simplify<
InputOwnProps & {

0 comments on commit 7c97a80

Please sign in to comment.