---
name: InputControl
package: '@wordpress/ui'
category: '@wordpress-ui'
status: stable
canonical: 'https://system.automattic.design/components/inputcontrol/'
storybook: 'https://wordpress.github.io/gutenberg/?path=/docs/design-system-components-form-inputcontrol--docs'
github: 'https://github.com/WordPress/gutenberg/tree/trunk/packages/ui/src/form'
---

# InputControl

A complete input field with integrated label and description.

```tsx
import { InputControl } from '@wordpress/ui';
```

## Props

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `type` | `HTMLInputTypeAttribute \| undefined` | — | The type of the input element. |
| `label` *(required)* | `string` | — | The accessible label. All controls must be labeled. |
| `description` | `string` | — | The accessible description, associated using `aria-describedby`.<br>For screen reader accessibility, this should only contain plain text, and no semantics such as links. |
| `render` | `ComponentRenderFn<HTMLAttributesWithRef<any>> \| ReactElement<Record<string, unknown>, string \| JSXElementConstructor<any>> \| undefined` | — | Replaces the component's default HTML element using a given React element, or a function that returns a React element. |
| `details` | `ReactNode` | — | Additional information about the field, which unlike a normal description, can include links and other semantic elements.<br>Do not use this prop when the content is only plain text; use `description` instead. |
| `style` | `CSSProperties` | — | CSS style to apply to the element. |
| `className` | `string` | — | CSS class name to apply to the element. |
| `defaultValue` | `string \| number \| readonly string[] \| undefined` | — | The default value to use in uncontrolled mode. |
| `prefix` | `ReactNode` | — | Element to render before the input. |
| `disabled` | `boolean` | — | Whether the field is disabled. |
| `value` | `string \| number \| readonly string[] \| undefined` | — | The value to use in controlled mode. |
| `onValueChange` | `(value: string, eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element \| undefined; }) => void` | — | Callback fired when the `value` changes. Use when controlled. |
| `size` | `"default" \| "compact"` | — | The size of the field. |
| `suffix` | `ReactNode` | — | Element to render after the input. |
| `hideLabelFromVision` | `boolean` | `false` | Whether to visually hide the label while keeping it accessible to screen readers. |


## Examples

### Default

```tsx
const Default = () => <InputControl
    label="Label"
    description="This is the description."
    placeholder="Placeholder" />;
```

### Visually Hidden Label

```tsx
const VisuallyHiddenLabel = () => <InputControl hideLabelFromVision />;
```

### With Details

```tsx
const WithDetails = () => <InputControl description={undefined} details={DETAILS_EXAMPLE} />;
```

### With Prefix

```tsx
const WithPrefix = () => <InputControl ref={undefined} />;
```

### With Suffix Control

```tsx
const WithSuffixControl = () => <InputControl ref={undefined} />;
```

### Password

```tsx
const Password = () => {
    const [ show, setShow ] = useState( false );

    return (
        <InputControl
            defaultValue="password"
            type={ show ? 'text' : 'password' }
            suffix={
                <InputLayout.Slot padding="minimal">
                    <IconButton
                        label={ show ? 'Hide password' : 'Show password' }
                        onClick={ () => setShow( ! show ) }
                        icon={ show ? unseen : seen }
                        size="small"
                        variant="minimal"
                    />
                </InputLayout.Slot>
            } />
    );
};
```

### Date

```tsx
const Date = () => <InputControl type="date" />;
```

### Number

```tsx
const Number = () => <InputControl placeholder="0" type="number" />;
```

### Number With Steppers

```tsx
const NumberWithSteppers = () => {
    const [ value, setValue ] = useState( 0 );

    return (
        <InputControl
            type="number"
            value={ value }
            onValueChange={ ( v ) => setValue( parseInt( v, 10 ) ) }
            suffix={
                <InputLayout.Slot padding="minimal">
                    <Stack direction="row" gap="xs">
                        <IconButton
                            label="Increment"
                            icon={ plus }
                            onClick={ () => setValue( value + 1 ) }
                            size="small"
                            variant="minimal"
                        />
                        <IconButton
                            label="Decrement"
                            icon={ reset }
                            onClick={ () => setValue( value - 1 ) }
                            size="small"
                            variant="minimal"
                        />
                    </Stack>
                </InputLayout.Slot>
            } />
    );
};
```

### Disabled

```tsx
const Disabled = () => <InputControl disabled />;
```
