JGuang

Input

Input · Mantine Core

Preview
npm install @mantine/core@9.7.1 @mantine/hooks@9.7.1

Input

Install: npm install @mantine/core@9.7.1 @mantine/hooks@9.7.1

Version and compatibility

Pinned Mantine Core 9.7.1 requires React and React DOM ^19.2.0 and matching @mantine/hooks@9.7.1, from the installed npm package's peerDependencies. Do not force it into React 18 or another incompatible version. Explain upgrade impact and agree on a plan with the project owner; do not hide conflicts with --force/--legacy-peer-deps. The native Provider enables theme.respectReducedMotion and uses forceColorScheme for light/dark.

Use case

Build an input primitive with sections and states.

Native props used by this example

These props are extracted from the local typechecked JSX and grouped by their owning native component. This is not an exhaustive prop list; see pinned source signatures and inheritance below.

Component propExplanation
Input.disabledDisable user input/action; not equivalent to readOnly.
Input.readOnlyPrevent editing while preserving the read-only interaction.
Input.placeholderInput hint, not a replacement for a label.
Input.aria-labelAccessible name/state for the native element.

Interaction and state checks

Current scenarios: Default, Disabled, Read only. Check actual behavior after selecting supported disabled/error/read-only scenarios; components without those native states do not receive invented universal props. Verify keyboard focus and exits, then connect changed values through the native callback signature.

Business integration boundary

Demo content/state is local, without server persistence, authorization or fetching. A static display component is not a completed business workflow.

Host setup

Install pinned @mantine/core and @mantine/hooks, import @mantine/core/styles.css at the entry and use MantineProvider. The example's theme/variant are JGuang-authored host props, not universal native component APIs; forceColorScheme synchronizes the app theme. Native implementation source is a reading reference: use npm exports rather than copying internal engines. This batch covers Core, not dates/charts/forms extension packages. Detailed upstream prose remains English.

Runnable usage

import { useState } from 'react';
import * as M from '@mantine/core';
import '@mantine/core/styles.css';


function ComponentPreview({ variant = 'Default' }: { variant?: string }) {
const disabled = variant === "Disabled";
const readOnly = variant === "Read only";
return <M.Input disabled={disabled} readOnly={readOnly} placeholder="Enter text / 输入文字" aria-label="Demo input" />;
}
export default function Example({ variant = 'Default', theme = 'light' }: { variant?: string; theme?: 'light' | 'dark' }) {
return <M.MantineProvider forceColorScheme={theme} theme={{ respectReducedMotion: true }}><ComponentPreview variant={variant} /></M.MantineProvider>;
}

Preview states

Default, Disabled, Read only

The example uses the native Mantine API. For supported input demos, change the local variant to Disabled, Invalid or Read only; these are example labels, not new component props. Keep the documented data, controlled values, stores and compound children when adapting the example.

Disclaimer

!important: In most cases, you should not use Input in your application. Input is a base for other inputs and was not designed to be used directly. Use Input to create custom inputs. For other cases, prefer TextInput or another component.

import { Input, TextInput } from '@mantine/core';

// Incorrect usage, input is not accessible
function Incorrect() {
  return (
    <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
function Correct() {
  return (
    <TextInput label="Input label" description="Input description" />
  );
}

Usage

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

Loading state

Set loading prop to display a loading indicator. By default, the loader is displayed on the right side of the input. You can change the position with the loadingPosition prop to 'left' or 'right'. This is useful for async operations like API calls, searches, or validations:

Change input element

Input is a polymorphic component, the default root element is input, but it can be changed to any other element or component.

Example of using Input as button and select:

Input.Wrapper component

The Input.Wrapper component is used in all other inputs (TextInput, NativeSelect, Textarea, 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.

inputWrapperOrder

inputWrapperOrder allows configuring the order of Input.Wrapper parts. It accepts an array of four elements: label, input, error and description. Note that it is not required to include all of them – you can use only those that you need. Parts that are not included will not be rendered.

inputContainer

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

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 a red asterisk to the end of the label. The only difference is whether the input element will have the required attribute. Example with the 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 />;
}

error prop

All inputs that use Input.Wrapper under the hood support the error prop. When set to true, it will add a red border to the input. You can also pass a React node to display an error message below the input. To only display an error message without a red border, set the error prop to a React node and withErrorStyles={false}:

success prop

All inputs that use Input.Wrapper under the hood support the success prop. When set to true, it will add a green border to the input. You can also pass a React node to display a success message below the input. If both error and success props are set, error takes precedence:

Input.Label, Input.Description and Input.Error components

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

Input.Placeholder component

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

Input.ClearButton component

Use the Input.ClearButton component to add a clear button to custom inputs based on the Input component. The size of the clear button is automatically inherited from the input:

Default props on theme

You can add default props on the theme 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, NativeSelect, Textarea, etc.):

Shared default props for all inputs

Default props on Input and Input.Wrapper cascade to every component that is built on top of them (TextInput, Textarea, NumberInput, Select, DateInput, and others). This is the easiest way to apply the same size, radius, variant, withAsterisk or any other shared prop to all inputs at once. Per-component default props always win over the shared ones, so you can still override individual components when needed:

Styles on theme

Same as with default props, you can use Input and Input.Wrapper Styles API on the theme to add styles to all inputs:

Change focus styles

Use &:focus-within selector to change inputs focus styles. You can apply these styles to one component with classNames prop or to all inputs with Styles API on theme.

InputBase component

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

Styles API

Input and Input.Wrapper components support Styles API – you can customize styles of any inner element with classNames and styles props.

Input Styles API selectors:

Input.Wrapper Styles API selectors:

Accessibility

If you use Input component without associated label element, set aria-label:

import { Input } from '@mantine/core';

// ok – the input is labelled by the aria-label
function WithAriaLabel() {
  return <Input aria-label="Your email" />;
}

// ok – the input is labelled by the label element
function WithLabel() {
  return (
    <>
      <label htmlFor="my-email">Your email</label>
      <Input id="my-email" />
    </>
  );
}

When you use Input with Input.Wrapper it is required to set id on both components to connect label and other elements with the input:

import { Input } from '@mantine/core';

function Demo() {
  return (
    <Input.Wrapper label="Your email" id="your-email">
      <Input id="your-email" />
    </Input.Wrapper>
  );
}

You can use use-id to generate unique ids:

import { Input } from '@mantine/core';
import { useId } from '@mantine/hooks';

function Demo() {
  const id = useId();
  return (
    <Input.Wrapper label="Your email" id={id}>
      <Input id={id} />
    </Input.Wrapper>
  );
}

Source-backed parameter reference

Implementation signatures and types are generated from the pinned local source. Optional props, native inherited types, union branches and never exclusions are preserved. A forwardRef implementation's ref is a React reference, not an additional business prop.

Input(_props)
type WrapperProps = React.ComponentProps<'div'> & DataAttributes;

export type InputStylesNames = 'input' | 'wrapper' | 'section' | 'bottomSection';

export type InputVariant = 'default' | 'filled' | 'unstyled';

export type InputCssVariables = {
  wrapper:
    | '--input-height'
    | '--input-fz'
    | '--input-radius'
    | '--input-left-section-width'
    | '--input-right-section-width'
    | '--input-left-section-pointer-events'
    | '--input-right-section-pointer-events'
    | '--input-padding-y'
    | '--input-margin-top'
    | '--input-margin-bottom';
};

export interface InputStylesCtx {
  offsetTop: boolean | undefined;
  offsetBottom: boolean | undefined;
}

export interface __InputProps {
  /** Content section displayed on the left side of the input */
  leftSection?: React.ReactNode;

  /** Left section width, used to set `width` of the section and input `padding-left`, by default equals to the input height */
  leftSectionWidth?: React.CSSProperties['width'];

  /** Props passed down to the `leftSection` element */
  leftSectionProps?: React.ComponentProps<'div'>;

  /** Sets `pointer-events` styles on the `leftSection` element. Use `'all'` when section contains interactive elements (buttons, links). @default 'none' */
  leftSectionPointerEvents?: React.CSSProperties['pointerEvents'];

  /** Content section displayed on the right side of the input */
  rightSection?: React.ReactNode;

  /** Right section width, used to set `width` of the section and input `padding-right`, by default equals to the input height */
  rightSectionWidth?: React.CSSProperties['width'];

  /** Props passed down to the `rightSection` element */
  rightSectionProps?: React.ComponentProps<'div'>;

  /** Sets `pointer-events` styles on the `rightSection` element. Use `'all'` when section contains interactive elements (buttons, links). @default 'none' */
  rightSectionPointerEvents?: React.CSSProperties['pointerEvents'];

  /** Sets `required` attribute on the `input` element */
  required?: boolean;

  /** Key of `theme.radius` or any valid CSS value to set `border-radius`, numbers are converted to rem @default theme.defaultRadius */
  radius?: MantineRadius;

  /** Sets `disabled` attribute on the `input` element */
  disabled?: boolean;

  /** Controls input `height`, horizontal `padding`, and `font-size` @default 'sm' */
  size?: MantineSize | (string & {});

  /** Determines whether the input should have `cursor: pointer` style. Use when input acts as a button-like trigger (e.g., `component="button"` for Select/DatePicker). @default false */
  pointer?: boolean;

  /** Determines whether the input should have red border and red text color when the `error` prop is set @default true */
  withErrorStyles?: boolean;

  /** Determines whether the input should have green border when the `success` prop is set @default true */
  withSuccessStyles?: boolean;

  /** HTML `size` attribute for the input element (number of visible characters) */
  inputSize?: string;

  /** Section to be displayed when the input is `__clearable` and `rightSection` is not defined */
  __clearSection?: React.ReactNode;

  /** Determines whether the `__clearSection` should be displayed if it is passed to the component, has no effect if `rightSection` is defined */
  __clearable?: boolean;

  /** Determines how the clear button and rightSection are rendered @default 'both' */
  __clearSectionMode?: ClearSectionMode;

  /** Right section displayed when both `__clearSection` and `rightSection` are not defined */
  __defaultRightSection?: React.ReactNode;

  /** Displays loading indicator in the left or right section @default false */
  loading?: boolean;

  /** Position of the loading indicator @default 'right' */
  loadingPosition?: 'left' | 'right';

  /** Content section displayed at the bottom of the input, inside the border */
  __bottomSection?: React.ReactNode;

  /** Props passed down to the `__bottomSection` element */
  __bottomSectionProps?: React.ComponentProps<'div'>;
}

export interface InputProps extends BoxProps, __InputProps, StylesApiProps<InputFactory> {
  __staticSelector?: string;

  /** Props passed to Styles API context, replaces `Input.Wrapper` props */
  __stylesApiProps?: Record<string, any>;

  /** Determines whether the input should have error styles and `aria-invalid` attribute */
  error?: React.ReactNode;

  /** Determines whether the input should have success styles */
  success?: React.ReactNode;

  /** Adjusts padding and sizing calculations for multiline inputs (use with `component="textarea"`). Does not make the input multiline by itself. @default false */
  multiline?: boolean;

  /** Input element id */
  id?: string;

  /** Determines whether `aria-` and other accessibility attributes should be added to the input. Only disable when implementing custom accessibility handling. @default true */
  withAria?: boolean;

  /** Props passed down to the root element of the `Input` component */
  wrapperProps?: WrapperProps;

  /** Root element ref */
  rootRef?: React.Ref<HTMLDivElement>;
}

export type InputFactory = PolymorphicFactory<{
  props: InputProps;
  defaultRef: HTMLInputElement;
  defaultComponent: 'input';
  stylesNames: InputStylesNames;
  variant: InputVariant;
  vars: InputCssVariables;
  ctx: InputStylesCtx;
  staticComponents: {
    Label: typeof InputLabel;
    Error: typeof InputError;
    Success: typeof InputSuccess;
    Description: typeof InputDescription;
    Placeholder: typeof InputPlaceholder;
    Wrapper: typeof InputWrapper;
    ClearButton: typeof InputClearButton;
  };
}>;

export type Mod = Record<string, any> | string;

export type BoxMod = Mod | Mod[] | BoxMod[];

export interface BoxProps extends MantineStyleProps {
  /** Class added to the root element, if applicable */
  className?: string | undefined;

  /** Inline style added to root component element, can subscribe to theme defined on MantineProvider */
  style?: MantineStyleProp;

  /** CSS variables defined on root component element */
  __vars?: CssVarsProp;

  /** `size` property passed down the HTML element */
  __size?: string;

  /** Breakpoint above which the component is hidden with `display: none` */
  hiddenFrom?: MantineBreakpoint;

  /** Breakpoint below which the component is hidden with `display: none` */
  visibleFrom?: MantineBreakpoint;

  /** Determines whether component should be hidden in light color scheme with `display: none` */
  lightHidden?: boolean;

  /** Determines whether component should be hidden in dark color scheme with `display: none` */
  darkHidden?: boolean;

  /** Element modifiers transformed into `data-` attributes, for example, `{ 'data-size': 'xl' }`, falsy values are removed */
  mod?: BoxMod;
}

export interface CSSProperties extends React.CSSProperties {
  [key: string]: any;
}

type MantineStyle = CSSProperties | ((theme: MantineTheme) => CSSProperties);

export type MantineStyleProp = MantineStyle | MantineStyle[] | MantineStyleProp[] | undefined;

export type CssVariable = `--${string}`;

export type CssVariables<Variable extends string = CssVariable> = Partial<Record<Variable, string>>;

export type CssVars<Variable extends string = CssVariable> =
  | CssVariables<Variable>
  | ((theme: MantineTheme) => CssVariables<Variable>)
  | CssVars<Variable>[];

export type CssVarsProp<Variable extends string = CssVariable> =
  | CssVars<Variable>
  | CssVars<Variable>[];

Native and external types

External types remain defined by React or native dependencies, not manually expanded into guessed props. The installed version's TypeScript definitions are authoritative.

PolymorphicFactory<{
  props: InputProps;
  defaultRef: HTMLInputElement;
  defaultComponent: 'input';
  stylesNames: InputStylesNames;
  variant: InputVariant;
  vars: InputCssVariables;
  ctx: InputStylesCtx;
  staticComponents: {
    Label: typeof InputLabel;
    Error: typeof InputError;
    Success: typeof InputSuccess;
    Description: typeof InputDescription;
    Placeholder: typeof InputPlaceholder;
    Wrapper: typeof InputWrapper;
    ClearButton: typeof InputClearButton;
  };
}>
MantineStyleProps
React.CSSProperties
MantineTheme
Partial<Record<Variable, string>>
Record<Variable, string>
Variable
MantineBreakpoint
Record<string, any>
React.ReactNode
React.ComponentProps<'div'>
MantineRadius
MantineSize
ClearSectionMode
StylesApiProps<InputFactory>
DataAttributes
React.Ref<HTMLDivElement>
HTMLDivElement
HTMLInputElement