# TextInput

Import: `import { TextInput } from '@neo4j-ndl/react'`

## Props

### TextInput

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `errorText` | `ReactNode` |  |  | Error message displayed below the input. When provided, it overrides `helpText` and shows an error icon |
| `helpText` | `ReactNode` |  |  | Assistive text displayed below the input |
| `isClearable` | `boolean` |  | `false` | Whether to show the clear button |
| `isDisabled` | `boolean` |  |  | Whether the input is disabled |
| `isFluid` | `boolean` |  |  | Whether the input should take the full available width |
| `isLoading` | `boolean` |  | `false` | Whether to show the loading spinner |
| `isReadOnly` | `boolean` |  |  | Whether the input is read-only |
| `isRequired` | `boolean` |  |  | Whether the input is required |
| `isSkeletonLoading` | `boolean` |  | `false` | Whether to render skeletons instead of content |
| `label` | `ReactNode` |  |  | The label displayed above the input |
| `leadingElement` | `ReactElement<unknown, string \| JSXElementConstructor<any>>` |  |  | Leading element rendered inside the input |
| `moreInformationText` | `ReactNode` |  |  | Text displayed in the information tooltip shown next to the label |
| `onChange` | `ChangeEventHandler<HTMLInputElement, HTMLInputElement>` |  |  | Callback function triggered when the input value changes |
| `placeholder` | `string` |  |  | Placeholder text displayed when the input is empty |
| `ref` | `Ref<HTMLInputElement>` |  |  | A ref to apply to the root element. |
| `showRequiredOrOptionalLabel` | `boolean` |  | `false` | Whether to display the Required/Optional label next to the field label. Shows Required if isRequired is true, otherwise shows Optional. |
| `size` | `'large' \| 'medium' \| 'small'` |  | `medium` | Size of the input |
| `skeletonProps` | `(SkeletonProps & { as?: ElementType<any, keyof IntrinsicElements>; } & BaseProps<ElementType<any, keyof IntrinsicElements>>)` |  |  | Additional props forwarded to the underlying Skeleton components |
| `tooltipProps` | `TooltipObjectProps` |  |  | Props for the Tooltip component used by the information icon |
| `trailingElement` | `ReactElement<unknown, string \| JSXElementConstructor<any>>` |  |  | Trailing element rendered inside the input |
| `value` | `string \| number \| readonly string[]` |  |  | The current value of the input |

When `moreInformationText` is provided, a tooltip is rendered next to the label, and the `tooltipProps` prop is used to configure the tooltip. The `TooltipObjectProps` type is defined as: `{ root?: Partial<React.ComponentProps<typeof Tooltip>>; trigger?: Partial<React.ComponentProps<typeof Tooltip.Trigger>>; content?: Partial<React.ComponentProps<typeof Tooltip.Content>>; }`, see the Tooltip component for more details.

When `isSkeletonLoading` is true, the input is rendered as a loading skeleton and the `skeletonProps` prop is used to configure the skeleton. For more information, see the Skeleton documentation.

## Accessibility

## Implementation guidelines

If you omit the label or provide a non-string custom label, supply an `aria-label` via `htmlAttributes` to keep the component accessible for screen readers.

## Examples

### Default

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { TextInput } from '@neo4j-ndl/react';

const Component = () => {
  return (
    <TextInput
      label="Label"
      helpText="Help text"
      htmlAttributes={{ id: 'text-input' }}
    />
  );
};

export default Component;
```

### Clearable

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { TextInput } from '@neo4j-ndl/react';

const Component = () => {
  return (
    <TextInput
      label="Clearable"
      isClearable
      placeholder="Type something"
      htmlAttributes={{ id: 'text-input' }}
    />
  );
};

export default Component;
```

### Disabled

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { TextInput } from '@neo4j-ndl/react';

const Component = () => {
  return (
    <TextInput
      label="Label"
      isDisabled
      helpText="Help text"
      value="Value"
      htmlAttributes={{ id: 'text-input' }}
    />
  );
};

export default Component;
```

### Email

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { TextInput } from '@neo4j-ndl/react';

const Component = () => {
  return (
    <TextInput
      label="Email Address"
      isRequired
      placeholder="user@example.com"
      htmlAttributes={{
        id: 'text-input',
        type: 'email',
      }}
    />
  );
};

export default Component;
```

### Error

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { TextInput } from '@neo4j-ndl/react';

const Component = () => {
  return (
    <TextInput
      label="Label"
      errorText="Error text"
      htmlAttributes={{ id: 'text-input' }}
    />
  );
};

export default Component;
```

### Full

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { CleanIconButton, TextInput } from '@neo4j-ndl/react';
import { UserIconOutline, XMarkIconOutline } from '@neo4j-ndl/react/icons';
import { useState } from 'react';

const Component = () => {
  const [textValue, setTextValue] = useState('');

  return (
    <TextInput
      label="Label"
      helpText="Help text"
      placeholder="Placeholder"
      value={textValue}
      onChange={(e) => setTextValue(e.target.value)}
      leadingElement={<UserIconOutline />}
      trailingElement={
        <CleanIconButton
          onClick={() => setTextValue('')}
          description="clear text"
        >
          <XMarkIconOutline />
        </CleanIconButton>
      }
      size="medium"
      moreInformationText="Information icon text"
      tooltipProps={{
        root: { placement: 'top' },
      }}
      isRequired={false}
      showRequiredOrOptionalLabel={true}
      isDisabled={false}
      isReadOnly={false}
      isFluid={false}
      isSkeletonLoading={false}
      skeletonProps={{
        onBackground: 'weak',
        shape: 'rectangular',
      }}
      htmlAttributes={{ id: 'text-input' }}
    />
  );
};

export default Component;
```

### Information Icon

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { TextInput } from '@neo4j-ndl/react';

const Component = () => {
  return (
    <TextInput
      label="Label"
      moreInformationText="Information icon text"
      htmlAttributes={{ id: 'text-input' }}
    />
  );
};

export default Component;
```

### Loading

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { TextInput } from '@neo4j-ndl/react';

const Component = () => {
  return (
    <TextInput
      label="Label"
      helpText="Help text"
      isSkeletonLoading={true}
      skeletonProps={{
        onBackground: 'weak',
        shape: 'rectangular',
      }}
      htmlAttributes={{ id: 'text-input' }}
    />
  );
};

export default Component;
```

### Loading Spinner

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { TextInput } from '@neo4j-ndl/react';
import { CalendarDaysIconOutline } from '@neo4j-ndl/react/icons';

const Component = () => {
  return (
    <div className="n-flex n-flex-col n-gap-token-16">
      <TextInput
        label="Default loading"
        isLoading
        placeholder="Placeholder"
        htmlAttributes={{ id: 'text-input-loading' }}
      />
      <TextInput
        label="With leading element"
        isLoading
        leadingElement={<CalendarDaysIconOutline />}
        placeholder="Placeholder"
        htmlAttributes={{ id: 'text-input-loading-leading' }}
      />
      <TextInput
        label="With trailing element"
        isLoading
        trailingElement={<CalendarDaysIconOutline />}
        placeholder="Placeholder"
        htmlAttributes={{ id: 'text-input-loading-trailing' }}
      />
      <TextInput
        label="With leading and trailing element"
        isLoading
        leadingElement={<CalendarDaysIconOutline />}
        trailingElement={<CalendarDaysIconOutline />}
        placeholder="Placeholder"
        htmlAttributes={{ id: 'text-input-loading-both' }}
      />
    </div>
  );
};

export default Component;
```

### Number

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { TextInput } from '@neo4j-ndl/react';

const Component = () => {
  return (
    <TextInput
      label="Age"
      htmlAttributes={{
        id: 'text-input',
        max: '100',
        min: '0',
        type: 'number',
      }}
    />
  );
};

export default Component;
```

### Optional

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { TextInput } from '@neo4j-ndl/react';

const Component = () => {
  return (
    <TextInput
      label="Label"
      helpText="Help text"
      showRequiredOrOptionalLabel
      htmlAttributes={{ id: 'text-input' }}
    />
  );
};

export default Component;
```

### Password

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { CleanIconButton, TextInput } from '@neo4j-ndl/react';
import { EyeIconOutline, EyeSlashIconOutline } from '@neo4j-ndl/react/icons';
import { useState } from 'react';

const Component = () => {
  const [isPasswordVisible, setIsPasswordVisible] = useState(false);

  return (
    <TextInput
      label="Password"
      trailingElement={
        <CleanIconButton
          onClick={() => setIsPasswordVisible(!isPasswordVisible)}
          description="toggle password visibility"
        >
          {isPasswordVisible ? <EyeIconOutline /> : <EyeSlashIconOutline />}
        </CleanIconButton>
      }
      placeholder="Enter password"
      htmlAttributes={{
        id: 'text-input',
        type: isPasswordVisible ? 'text' : 'password',
      }}
    />
  );
};

export default Component;
```

### Readonly

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { TextInput } from '@neo4j-ndl/react';

const Component = () => {
  return (
    <TextInput
      label="Label"
      isReadOnly
      helpText="Help text"
      value="Value"
      htmlAttributes={{ id: 'text-input' }}
    />
  );
};

export default Component;
```

### Required

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { TextInput } from '@neo4j-ndl/react';

const Component = () => {
  return (
    <TextInput
      label="Label"
      isRequired
      helpText="Help text"
      showRequiredOrOptionalLabel
      htmlAttributes={{ id: 'text-input' }}
    />
  );
};

export default Component;
```

### Sizes

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { TextInput } from '@neo4j-ndl/react';

const Component = () => {
  return (
    <div className="n-flex n-gap-token-16">
      <TextInput
        label="Small Input"
        size="small"
        htmlAttributes={{ id: 'text-input-small' }}
      />
      <TextInput
        label="Medium Input"
        size="medium"
        htmlAttributes={{ id: 'text-input-medium' }}
      />
      <TextInput
        label="Large Input"
        size="large"
        htmlAttributes={{ id: 'text-input-large' }}
      />
    </div>
  );
};

export default Component;
```

### With Icons

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { TextInput } from '@neo4j-ndl/react';
import { DatabasePlugIcon, DatabasePlusIcon } from '@neo4j-ndl/react/icons';
import { useState } from 'react';

const Component = () => {
  const [searchValue, setSearchValue] = useState('');

  return (
    <TextInput
      label="With icons"
      leadingElement={<DatabasePlugIcon />}
      trailingElement={<DatabasePlusIcon />}
      value={searchValue}
      onChange={(e) => setSearchValue(e.target.value)}
      htmlAttributes={{ id: 'text-input' }}
    />
  );
};

export default Component;
```
