Propel

Autocomplete Field

A labeled autocomplete input with a filtered suggestion popup and helper or error text.

Type or choose an image tag.

Show code
import { AutocompleteField } from "@makeplane/propel/components/autocomplete-field";
import { Icon } from "@makeplane/propel/components/icon";
import { IconButton } from "@makeplane/propel/components/icon-button";
import { ChevronsUpDown, X } from "lucide-react";

const IMAGES = ["nginx:1.29-alpine", "node:22-slim", "postgres:18", "redis:8.2.2-alpine"];

export default function BasicDemo() {
  return (
    <AutocompleteField
      name="containerImage"
      label="Container image"
      description="Type or choose an image tag."
      size="lg"
      items={IMAGES}
      placeholder="e.g. node:22-slim"
      empty="No images found"
      clear={
        <IconButton
          variant="ghost"
          size="md"
          aria-label="Clear container image"
          icon={<Icon icon={X} />}
        />
      }
      trigger={
        <IconButton
          variant="ghost"
          size="md"
          aria-label="Open container image"
          icon={<Icon icon={ChevronsUpDown} />}
        />
      }
    />
  );
}

Installation

import { AutocompleteField } from "@makeplane/propel/components/autocomplete-field";

Usage

import { AutocompleteField } from "@makeplane/propel/components/autocomplete-field";
import { Icon } from "@makeplane/propel/components/icon";
import { IconButton } from "@makeplane/propel/components/icon-button";
import { ChevronsUpDown, X } from "lucide-react";

const IMAGES = ["nginx:1.29-alpine", "node:22-slim", "postgres:18", "redis:8.2.2-alpine"];

export default function BasicDemo() {
  return (
    <AutocompleteField
      name="containerImage"
      label="Container image"
      description="Type or choose an image tag."
      size="lg"
      items={IMAGES}
      placeholder="e.g. node:22-slim"
      empty="No images found"
      clear={
        <IconButton
          variant="ghost"
          size="md"
          aria-label="Clear container image"
          icon={<Icon icon={X} />}
        />
      }
      trigger={
        <IconButton
          variant="ghost"
          size="md"
          aria-label="Open container image"
          icon={<Icon icon={ChevronsUpDown} />}
        />
      }
    />
  );
}

Examples

Sizes

size steps the label, description, and helper text together with the input group and its input text.

Type or choose an image tag.

Type or choose an image tag.

Type or choose an image tag.

Show code
import { AutocompleteField, type FieldSize } from "@makeplane/propel/components/autocomplete-field";
import { Icon } from "@makeplane/propel/components/icon";
import { IconButton, type IconButtonSize } from "@makeplane/propel/components/icon-button";
import { ChevronsUpDown, X } from "lucide-react";

const IMAGES = ["nginx:1.29-alpine", "node:22-slim", "postgres:18", "redis:8.2.2-alpine"];

const SIZES: FieldSize[] = ["lg", "xl", "2xl"];

// The icon button rung inside each field's row rung: one ladder rung down, clamped at `lg` (the
// compact scale's ceiling) once the field size outgrows it.
const ICON_BUTTON_SIZE: Record<FieldSize, IconButtonSize> = {
  lg: "md",
  xl: "lg",
  "2xl": "lg",
};

export default function SizesDemo() {
  return (
    <div className="flex flex-col gap-4">
      {SIZES.map((size) => (
        <AutocompleteField
          key={size}
          name="containerImage"
          label={size}
          description="Type or choose an image tag."
          size={size}
          items={IMAGES}
          placeholder="e.g. node:22-slim"
          empty="No images found"
          clear={
            <IconButton
              variant="ghost"
              size={ICON_BUTTON_SIZE[size]}
              aria-label="Clear container image"
              icon={<Icon icon={X} />}
            />
          }
          trigger={
            <IconButton
              variant="ghost"
              size={ICON_BUTTON_SIZE[size]}
              aria-label="Open container image"
              icon={<Icon icon={ChevronsUpDown} />}
            />
          }
        />
      ))}
    </div>
  );
}

Invalid

Setting error marks the field invalid, recolors the input group border, and replaces the description with the error text.

Enter a container image.
Show code
import { AutocompleteField } from "@makeplane/propel/components/autocomplete-field";
import { Icon } from "@makeplane/propel/components/icon";
import { IconButton } from "@makeplane/propel/components/icon-button";
import { ChevronsUpDown, X } from "lucide-react";

const IMAGES = ["nginx:1.29-alpine", "node:22-slim", "postgres:18", "redis:8.2.2-alpine"];

export default function InvalidDemo() {
  return (
    <AutocompleteField
      name="containerImage"
      label="Container image"
      size="lg"
      items={IMAGES}
      placeholder="e.g. node:22-slim"
      empty="No images found"
      error="Enter a container image."
      clear={
        <IconButton
          variant="ghost"
          size="md"
          aria-label="Clear container image"
          icon={<Icon icon={X} />}
        />
      }
      trigger={
        <IconButton
          variant="ghost"
          size="md"
          aria-label="Open container image"
          icon={<Icon icon={ChevronsUpDown} />}
        />
      }
    />
  );
}

Disabled

Type or choose an image tag.

Show code
import { AutocompleteField } from "@makeplane/propel/components/autocomplete-field";
import { Icon } from "@makeplane/propel/components/icon";
import { IconButton } from "@makeplane/propel/components/icon-button";
import { ChevronsUpDown, X } from "lucide-react";

const IMAGES = ["nginx:1.29-alpine", "node:22-slim", "postgres:18", "redis:8.2.2-alpine"];

export default function DisabledDemo() {
  return (
    <AutocompleteField
      name="containerImage"
      label="Container image"
      description="Type or choose an image tag."
      size="lg"
      disabled
      items={IMAGES}
      placeholder="e.g. node:22-slim"
      empty="No images found"
      clear={
        <IconButton
          variant="ghost"
          size="md"
          aria-label="Clear container image"
          icon={<Icon icon={X} />}
        />
      }
      trigger={
        <IconButton
          variant="ghost"
          size="md"
          aria-label="Open container image"
          icon={<Icon icon={ChevronsUpDown} />}
        />
      }
    />
  );
}

API Reference

AutocompleteField

Ready-to-use autocomplete field with label, input, popup items, and helper/error text.

PropTypeDefaultDescription
clear(required)ReactElement<unknown, string | JSXElementConstructor<any>>The clear control (e.g. an `IconButton`) carrying its own localizable `aria-label`. Required here (unlike the bare `AutocompleteInputGroup`) — a labeled field is always presented as a complete picker, not a plain search box.
trigger(required)ReactElement<unknown, string | JSXElementConstructor<any>>The popup-trigger control (e.g. an `IconButton`) carrying its own localizable `aria-label`. Required here for the same reason as `clear`.
empty(required)ReactNodeMessage rendered when no item matches.
items(required)readonly Value[]Items rendered in the popup.
label(required)stringVisible field label.
size(required)"lg" | "xl" | "2xl"Label and helper text size.
descriptionReactNodeSupporting text shown below the input. Replaced by `error` when an error is set.
errorReactNodeError text shown below the control.
hintReactNodeHelper text shown below the control. Replaced by `error` when an error is set.
placeholderstringInput placeholder.