Inputpolymorphic

Base component to create custom inputs
Import

Disclaimer

!important: In most cases, you should not use Input component in your application. Input component is a base for other inputs and was not designed to be used directly.

// Incorrect usage, input is not accessible
<Input.Wrapper label="Input label">
<Input />
</Input.Wrapper>
// Use TextInput instead of Input everywhere you want to use Input,
// it is accessible by default and includes Input.Wrapper
<TextInput label="Input label" description="Input description" />

Usage

Input component is used as base for some other inputs (Select, TextInput, Textarea, etc.). The purpose of Input is to provide shared styles and features to other inputs:

Variant
Radius
xs
sm
md
lg
xl
Size
xs
sm
md
lg
xl
import { Input } from '@mantine/core';
import { IconAt } from '@tabler/icons';
function Demo() {
return (
<Input
icon={<IconAt />}
placeholder="Your email"
/>
);
}

Icon and right section

import { Input, Tooltip } from '@mantine/core';
import { IconBrandTwitter, IconAlertCircle } from '@tabler/icons';
function Demo() {
return (
<Input
icon={<IconBrandTwitter size={16} />}
placeholder="Your twitter"
rightSection={
<Tooltip label="This is public" position="top-end" withArrow>
<div>
<IconAlertCircle size={18} style={{ display: 'block', opacity: 0.5 }} />
</div>
</Tooltip>
}
/>
);
}

Custom component

Input is a polymorphic component, you can change the root element with component prop:

import { Input } from '@mantine/core';
import { IconChevronDown } from '@tabler/icons';
function Demo() {
return (
<>
<Input component="button">Button input</Input>
<Input component="select" rightSection={<IconChevronDown size={14} stroke={1.5} />}>
<option value="1">1</option>
<option value="2">2</option>
</Input>
</>
);
}

You can use Input and Input.Wrapper components to build custom inputs with third-party libraries, example with react-input-mask:

import { Input } from '@mantine/core';
import { useId } from '@mantine/hooks';
import InputMask from 'react-input-mask';
function Demo() {
const id = useId();
return (
<Input.Wrapper id={id} label="Your phone" required>
<Input component={InputMask} mask="+7 (999) 999-99-99" id={id} placeholder="Your phone" />
</Input.Wrapper>
);
}

Input.Wrapper component

Input.Wrapper component is used in all other inputs (TextInput, Autocomplete, MultiSelect, etc.) under the hood, you do not need to wrap your inputs with it, as it is already included in all of them. Use Input.Wrapper only when you want to create custom inputs.

Please enter your credit card information, we need some money
Your credit card expired
Size
xs
sm
md
lg
xl
import { Input } from '@mantine/core';
function Demo() {
return (
<Input.Wrapper
id="input-demo"
withAsterisk
label="Credit card information"
description="Please enter your credit card information, we need some money"
error="Your credit card expired"
>
<Input id="input-demo" placeholder="Your email" />
</Input.Wrapper>
);
}

inputContainer

With inputContainer prop you can enhance inputs that use Input.Wrapper under the hood, for example, you can add Tooltip to TextInput when the input is focused:

Tooltip will be relative to the input
import { useState } from 'react';
import { TextInput, Tooltip } from '@mantine/core';
function Demo() {
const [focused, setFocused] = useState(false);
return (
<TextInput
label="TextInput with tooltip"
description="Tooltip will be relative to the input"
placeholder="Focus me to see tooltip"
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}
inputContainer={(children) => (
<Tooltip label="Additional information" position="top-start" opened={focused}>
{children}
</Tooltip>
)}
/>
);
}

inputWrapperOrder

inputWrapperOrder prop allows to define the order of Input.Wrapper parts:

Description below the input
Error and description are
both below the input
import { TextInput } from '@mantine/core';
function Demo() {
return (
<>
<TextInput
label="Custom layout"
placeholder="Custom layout"
description="Description below the input"
inputWrapperOrder={['label', 'error', 'input', 'description']}
/>
<TextInput
mt="xl"
label="Custom layout"
placeholder="Custom layout"
description="Error and description are"
error="both below the input"
inputWrapperOrder={['label', 'input', 'description', 'error']}
/>
</>
);
}

required and withAsterisk props

All components that are based on Input.Wrapper support required and withAsterisk props. When set to true, both of these props will add red asterisk to the end of the label. The only difference is whether input element will have required attribute, example with TextInput component:

import { TextInput } from '@mantine/core';
// Will display required asterisk and add `required` attribute to the input element
function RequiredDemo() {
return <TextInput label="test-label" required />;
}
// Will only display the asterisk, `required` attribute is not added to the input element
function AsteriskDemo() {
return <TextInput label="test-label" withAsterisk />;
}

Input.Label, Input.Error and Input.Description

Input.Label, Input.Error and Input.Description components can be used to create custom form layouts if default Input.Wrapper layout does not fit your requirements.

Input description
Input error
import { Input } from '@mantine/core';
function Demo() {
return (
<>
<Input.Label required>Input label</Input.Label>
<Input.Description>Input description</Input.Description>
<Input.Error>Input error</Input.Error>
</>
);
}

InputBase component

InputBase component combines Input and Input.Wrapper components and supports component prop:

import { InputBase } from '@mantine/core';
import InputMask from 'react-input-mask';
function Demo() {
return (
<>
<InputBase
label="Input mask"
placeholder="Your phone"
component={InputMask}
mask="+7 (999) 999-99-99"
/>
<InputBase label="Custom native select" component="select" mt="md">
<option value="react">React</option>
<option value="react">Angular</option>
<option value="svelte">Svelte</option>
</InputBase>
</>
);
}

Input.Placeholder

Input.Placeholder component can be used to add placeholder to Input and InputBase components that are based on button element or do not support placeholder property natively:

import { Input } from '@mantine/core';
function Demo() {
return (
<Input component="button">
<Input.Placeholder>Placeholder content</Input.Placeholder>
</Input>
);
}
import { Input, InputBase } from '@mantine/core';
function Demo() {
return (
<InputBase component="button" label="Input base button with placeholder">
<Input.Placeholder>Placeholder content</Input.Placeholder>
</InputBase>
);
}

Default props on MantineProvider

You can add default props on MantineProvider to Input and Input.Wrapper components. These default props will be inherited by all inputs that use Input and Input.Wrapper under the hood (TextInput, Autocomplete, MultiSelect, etc.):

Description below the input
Description below the input
Description below the input
import { TextInput, MultiSelect, NumberInput, MantineProvider } from '@mantine/core';
function Demo() {
return (
<MantineProvider
theme={{
components: {
InputWrapper: {
defaultProps: {
inputWrapperOrder: ['label', 'error', 'input', 'description'],
},
},
Input: {
defaultProps: {
variant: 'filled',
},
},
},
}}
>
<TextInput
label="TextInput with custom layout"
placeholder="TextInput with custom layout"
description="Description below the input"
/>
<NumberInput
mt="xl"
label="NumberInput with custom layout"
placeholder="NumberInput with custom layout"
description="Description below the input"
/>
<MultiSelect
mt="xl"
data={['Is not that', 'awesome?']}
label="MultiSelect with custom layout"
placeholder="MultiSelect with custom layout"
description="Description below the input"
/>
</MantineProvider>
);
}

Styles on MantineProvider

Same as with default props you can use Input and Input.Wrapper Styles API on MantineProvider to add styles to all Inputs:

Description below the input
Description below the input
import { TextInput, NumberInput, MantineProvider } from '@mantine/core';
function Demo() {
return (
<MantineProvider
inherit
theme={{
components: {
InputWrapper: {
styles: (theme) => ({
label: {
backgroundColor:
theme.colorScheme === 'dark' ? 'rgba(255, 255, 255, .1)' : 'rgba(0, 0, 0, .1)',
},
}),
},
Input: {
styles: (theme) => ({
input: { borderColor: theme.colors.violet[theme.fn.primaryShade()] },
}),
},
},
}}
>
<TextInput
label="TextInput with custom styles"
placeholder="TextInput with custom styles"
description="Description below the input"
/>
<NumberInput
mt="xl"
label="NumberInput with custom styles"
placeholder="NumberInput with custom styles"
description="Description below the input"
/>
</MantineProvider>
);
}

Customize focus styles

Input component is used as a base for other inputs (PasswordInput, Select, MultiSelect, etc.). To customize focus styles of any inputs that are built on top of the Input component, use &:focus-within selector instead of &:focus:

import { Input } from '@mantine/core';
function Demo() {
return (
<Input
placeholder="Input with custom focus styles"
styles={(theme) => ({
input: {
'&:focus-within': {
borderColor: theme.colors.orange[7],
},
},
})}
/>
);
}

Get input ref

import { useRef } from 'react';
import { Input } from '@mantine/core';
function Demo() {
const ref = useRef<HTMLInputElement>(null);
return <Input ref={ref} />;
}

Input component props

NameTypeDescription
disabled
boolean
Disabled input state
icon
ReactNode
Adds icon on the left side of input
iconWidth
Width<string | number>
Width of icon section in px
invalid
boolean
Sets border color to red and aria-invalid=true on input element
multiline
boolean
Will input have multiple lines?
pointer
boolean
Determines whether cursor on input should be pointer
radius
number | "xs" | "sm" | "md" | "lg" | "xl"
Input border-radius from theme or number to set border-radius in px
required
boolean
Sets required on input element
rightSection
ReactNode
Right section of input, similar to icon but on the right
rightSectionProps
Record<string, any>
Props spread to rightSection div element
rightSectionWidth
Width<string | number>
Width of right section, is used to calculate input padding-right
size
"xs" | "sm" | "md" | "lg" | "xl"
Input size
variant
"unstyled" | "default" | "filled"
Defines input appearance, defaults to default in light color scheme and filled in dark
wrapperProps
Record<string, any>
Properties spread to root element

Input.Wrapper component props

NameTypeDescription
children *
ReactNode
Input that should be wrapped
description
ReactNode
Input description, displayed after label
descriptionProps
Record<string, any>
Props spread to description element
error
ReactNode
Displays error message after input
errorProps
Record<string, any>
Props spread to error element
id
string
htmlFor label prop
inputContainer
(children: ReactNode) => ReactNode
Input container component, defaults to React.Fragment
inputWrapperOrder
("input" | "label" | "error" | "description")[]
Controls order of the Input.Wrapper elements
label
ReactNode
Input label, displayed before input
labelElement
"div" | "label"
Render label as label with htmlFor or as div
labelProps
Record<string, any>
Props spread to label element
required
boolean
Adds required attribute to the input and red asterisk on the right side of label
size
"xs" | "sm" | "md" | "lg" | "xl"
Controls all elements font-size
withAsterisk
boolean
Determines whether required asterisk should be rendered, overrides required prop, does not add required attribute to the input

Input.Label component props

NameTypeDescription
children
ReactNode
Label content
labelElement
"div" | "label"
Label root element
required
boolean
Determines whether required asterisk should be displayed
size
"xs" | "sm" | "md" | "lg" | "xl"
Predefined label size

Input.Description component props

NameTypeDescription
children
ReactNode
Description content
size
"xs" | "sm" | "md" | "lg" | "xl"
Predefined size

Input.Error component props

NameTypeDescription
children
ReactNode
Error content
size
"xs" | "sm" | "md" | "lg" | "xl"
Predefined size

Input component Styles API

NameStatic selectorDescription
wrapper.mantine-Input-wrapperRoot Input element
invalid.mantine-Input-invalidInvalid input modifier
disabled.mantine-Input-disabledInvalid disabled modifier
icon.mantine-Input-iconInput icon wrapper on the left side of the input, controlled by icon prop
withIcon.mantine-Input-withIconInput element styles when used with icon, controlled by icon prop
input.mantine-Input-inputMain input element
rightSection.mantine-Input-rightSectionInput right section, controlled by rightSection prop

Input.Wrapper component Styles API

NameStatic selectorDescription
root.mantine-Input.Wrapper-rootRoot element
label.mantine-Input.Wrapper-labelLabel element styles, defined by label prop
error.mantine-Input.Wrapper-errorError element styles, defined by error prop
description.mantine-Input.Wrapper-descriptionDescription element styles, defined by description prop
required.mantine-Input.Wrapper-requiredRequired asterisk element styles, defined by required prop