> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Input

> A text input with native attributes, field integration, and two sizes.

export const StoryEmbed = ({storyId, title, height = 120}) => <>
    <Tabs>
      <Tab title="Light">
        <iframe title={`${title} (light)`} src={`https://storybook.twenty.com/iframe.html?id=${storyId}&viewMode=story&globals=colorScheme:light`} width="100%" height={height} loading="lazy" allow="clipboard-write" style={{
  border: 0
}} />
      </Tab>
      <Tab title="Dark">
        <iframe title={`${title} (dark)`} src={`https://storybook.twenty.com/iframe.html?id=${storyId}&viewMode=story&globals=colorScheme:dark`} width="100%" height={height} loading="lazy" allow="clipboard-write" style={{
  border: 0
}} />
      </Tab>
    </Tabs>
    <a href={`https://storybook.twenty.com/?path=/story/${storyId}`}>
      Open in Storybook
    </a>
  </>;

`Input` renders a text input and accepts native input attributes such as `type`, `name`, `required`, `disabled`, and `autoComplete`.

<StoryEmbed storyId="ui-input-input--display" title="Input example" height={140} />

## Usage

### Uncontrolled state

Use `defaultValue` to set the initial email address. The input owns subsequent changes.

```tsx theme={null}
import { Field, Input } from 'twenty-ui/primitives/input';

export const EmailField = () => (
  <Field.Root>
    <Field.Label>Email</Field.Label>
    <Input
      name="email"
      type="email"
      autoComplete="email"
      defaultValue="alex@example.com"
    />
    <Field.Description>Use your work email address.</Field.Description>
  </Field.Root>
);
```

## Visual choices

Compare small and medium inputs in their default, focused, invalid, and disabled states. Use validation feedback alongside invalid styling.

<StoryEmbed storyId="ui-input-input--catalog" title="Visual choices for input" height={380} />

## Controlled state

Pass `value` and update it with `onValueChange` to own the same email address in React state. The callback receives the next string value and event details.

```tsx theme={null}
import { useState } from 'react';
import { Field, Input } from 'twenty-ui/primitives/input';

export const EmailField = () => {
  const [email, setEmail] = useState('alex@example.com');

  return (
    <Field.Root>
      <Field.Label>Email</Field.Label>
      <Input
        name="email"
        type="email"
        autoComplete="email"
        value={email}
        onValueChange={setEmail}
      />
      <Field.Description>Use your work email address.</Field.Description>
    </Field.Root>
  );
};
```

## Add an adornment

`InputGroup` owns the surrounding border and layout height. Input size resolves from the explicit child `size`, then the group default, then `md`. The grouped input stretches within the shared border, so use the group's `size` to change the overall field height.

```tsx theme={null}
import { IconSearch } from 'twenty-ui/icon';
import { Input, InputGroup } from 'twenty-ui/primitives/input';

export const CompactSearch = () => (
  <InputGroup size="sm" startElement={<IconSearch size={16} aria-hidden />}>
    <Input aria-label="Search contacts" />
  </InputGroup>
);
```

## Native control and wrapper customization

Native attributes, handlers, `className`, `style`, and `ref` target the input. The ref receives an `HTMLInputElement`. Use `render` to compose another input component and forward the supplied props and ref to its native input.

`onChange` receives a React change event for the native input. `onValueChange(value, details)` receives the next string and Base UI event details, including `event`, `reason`, `cancel`, and `allowPropagation`. The event targets the input. Canceling the details preserves Base UI's validation policy; it does not undo a native edit. Controlled callers decide which value to commit.

Put layout styles, attributes, and refs on `InputGroup` when customizing the surrounding wrapper. The group owns no value. Native `name`, `form`, `required`, `readOnly`, `disabled`, submission, and reset behavior remain on the input, with Field naming and validation supplied through `Field.Root`.

## Props

The reference includes component-specific and inherited Base UI props. Native input attributes are also accepted. A standalone input defaults to `md`; inside a group, an omitted input `size` inherits the group's size.

<ParamField body="className" type="string | ((state: InputState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="defaultValue" type="string | number | readonly string[]">
  The default value of the input. Use when uncontrolled.
</ParamField>

<ParamField body="onValueChange" type="((value: string, eventDetails: { reason: &#x22;none&#x22;; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void)">
  Receives the next string value and Base UI details, including the native event, reason and cancellation methods.
</ParamField>

<ParamField body="ref" type="Ref<HTMLInputElement>">
  Ref to the native input element.
</ParamField>

<ParamField body="render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, InputState>">
  Composes the native input with a custom element or render callback. Forward the supplied props and ref to an input.
</ParamField>

<ParamField body="size" type="&#x22;md&#x22; | &#x22;sm&#x22;">
  Visual size. Explicit input size takes precedence over the InputGroup default, then md applies. Group layout still sets the surrounding height.
</ParamField>

<ParamField body="style" type="CSSProperties | ((state: InputState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

<ParamField body="value" type="string | number | readonly string[]">
  The value of the input. Use when controlled.
</ParamField>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.