Propel

Field

The shared labeling and validation shell for composing a custom form control with a label, description, and error text.

Shown anywhere your profile is visible.

Show code
import { Field, FieldDescription, FieldLabel } from "@makeplane/propel/components/field";
import { Input } from "@makeplane/propel/components/input";

export default function BasicDemo() {
  return (
    <Field name="displayName">
      <FieldLabel size="lg" inset={false} required>
        Display name
      </FieldLabel>
      <Input size="lg" placeholder="Ada Lovelace" required />
      <FieldDescription size="lg">Shown anywhere your profile is visible.</FieldDescription>
    </Field>
  );
}

Installation

import { Field, FieldDescription, FieldLabel } from "@makeplane/propel/components/field";
import { Input } from "@makeplane/propel/components/input";

Usage

import { Field, FieldDescription, FieldLabel } from "@makeplane/propel/components/field";
import { Input } from "@makeplane/propel/components/input";

export default function BasicDemo() {
  return (
    <Field name="displayName">
      <FieldLabel size="lg" inset={false} required>
        Display name
      </FieldLabel>
      <Input size="lg" placeholder="Ada Lovelace" required />
      <FieldDescription size="lg">Shown anywhere your profile is visible.</FieldDescription>
    </Field>
  );
}

Examples

Sizes

Pass the same size to every part of a field so the label, control, and description scale together.

Shown anywhere your profile is visible.

Shown anywhere your profile is visible.

Shown anywhere your profile is visible.

Show code
import {
  Field,
  FieldDescription,
  FieldLabel,
  type FieldSize,
} from "@makeplane/propel/components/field";
import { Input } from "@makeplane/propel/components/input";

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

export default function SizesDemo() {
  return (
    <div className="flex flex-wrap items-start gap-8">
      {SIZES.map((size) => (
        <Field key={size} name={`displayName-${size}`}>
          <FieldLabel size={size} inset={false} required>
            Display name ({size})
          </FieldLabel>
          <Input size={size} placeholder="Ada Lovelace" required />
          <FieldDescription size={size}>Shown anywhere your profile is visible.</FieldDescription>
        </Field>
      ))}
    </div>
  );
}

Invalid

Choose a different workspace slug.
Show code
import { Field, FieldError, FieldLabel } from "@makeplane/propel/components/field";
import { Input } from "@makeplane/propel/components/input";

export default function InvalidDemo() {
  return (
    <Field name="workspaceSlug" invalid>
      <FieldLabel size="lg" inset={false}>
        Workspace slug
      </FieldLabel>
      <Input size="lg" defaultValue="Already taken" />
      <FieldError size="lg" match={true}>
        Choose a different workspace slug.
      </FieldError>
    </Field>
  );
}

Required validation

Native constraint validity drives FieldError through match; with validationMode="onBlur" the message appears when the user leaves the field empty and clears once a value is committed.

Visible on your profile.

Show code
import {
  Field,
  FieldDescription,
  FieldError,
  FieldLabel,
} from "@makeplane/propel/components/field";
import { Input } from "@makeplane/propel/components/input";

export default function RequiredValidationDemo() {
  return (
    <Field name="fullName" validationMode="onBlur">
      <FieldLabel size="lg" inset={false} required>
        Full name
      </FieldLabel>
      <Input size="lg" placeholder="Ada Lovelace" required />
      <FieldError size="lg" match="valueMissing">
        Enter your full name.
      </FieldError>
      <FieldDescription size="lg">Visible on your profile.</FieldDescription>
    </Field>
  );
}

Horizontal label

FieldLabelGroup bundles the label and description into one block; with orientation="horizontal" it sits beside the control in a flex row. Supporting text is one tier below the label at every size, whether it sits under the label or under the control.

Shown across your projects.

Show code
import { Field, FieldLabelGroup } from "@makeplane/propel/components/field";
import { Input } from "@makeplane/propel/components/input";

export default function HorizontalDemo() {
  return (
    <Field name="workspaceName">
      <div className="flex items-start gap-4">
        <FieldLabelGroup
          size="lg"
          orientation="horizontal"
          required
          label="Workspace name"
          description="Shown across your projects."
        />
        <Input size="lg" placeholder="Acme Inc." />
      </div>
    </Field>
  );
}

Helper text

FieldHelperText renders the hint below the control and swaps it for the error when one is set, keeping the error-XOR-hint rule in one part.

Lowercase letters, numbers, and dashes.

Only lowercase letters, numbers, and dashes are allowed.
Show code
import { Field, FieldHelperText, FieldLabel } from "@makeplane/propel/components/field";
import { Input } from "@makeplane/propel/components/input";

export default function HelperTextDemo() {
  return (
    <div className="flex flex-wrap items-start gap-8">
      <Field name="slug">
        <FieldLabel size="lg" inset={false}>
          Slug
        </FieldLabel>
        <Input size="lg" placeholder="acme-inc" />
        <FieldHelperText size="lg" hint="Lowercase letters, numbers, and dashes." />
      </Field>
      <Field name="slugTaken">
        <FieldLabel size="lg" inset={false}>
          Slug
        </FieldLabel>
        <Input size="lg" defaultValue="acme inc" />
        <FieldHelperText
          size="lg"
          hint="Lowercase letters, numbers, and dashes."
          error="Only lowercase letters, numbers, and dashes are allowed."
        />
      </Field>
    </div>
  );
}

API Reference

Field

The shared field chrome for custom controls: Base UI's labeling/validation Field.Root behavior grafted onto the styled Field element (rule 1a). Compose it with FieldLabel, a control, FieldDescription, and FieldError.

PropTypeDefaultDescription
renderReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, FieldRootState>—Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.
size"md" | "lg" | "xl" | "2xl"—

FieldLabel

The ready-made field label: Base UI's Field.Label (auto-associated with the control) grafted onto the styled FieldLabel element (rule 1a), plus a FieldLabelRequiredMarker when required.

PropTypeDefaultDescription
size(required)"md" | "lg" | "xl" | "2xl"—
inset(required)NonNullable<boolean | null | undefined>—
renderReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, FieldLabelState>—Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.
requiredboolean—

FieldLabelGroup

The ready-made label/description block of a field: lays out an optional FieldLabel and FieldDescription inside the FieldLabelGroup container. Renders nothing when both are absent.

PropTypeDefaultDescription
orientation(required)"vertical" | "horizontal"—
size(required)"md" | "lg" | "xl" | "2xl"—
requiredboolean—
labelstring—
descriptionReactNode—

FieldItemContent

The label + description column for a single choice option (checkbox/radio/switch row).

PropTypeDefaultDescription
size(required)"md" | "lg" | "xl" | "2xl"—
descriptionReactNode—

FieldDescription

Supporting / helper text for a field: Base UI's Field.Description (auto-associated as the control's accessible description) grafted onto the styled FieldDescription element (rule 1a).

PropTypeDefaultDescription
size(required)"md" | "lg" | "xl" | "2xl"—
renderReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, FieldDescriptionState>—Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.

FieldError

Error text for a field: Base UI's Field.Error (shown per the control's validity / match) grafted onto the styled FieldError element (rule 1a).

PropTypeDefaultDescription
size(required)"md" | "lg" | "xl" | "2xl"—
renderReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, FieldErrorState>—Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.

FieldHelperText

The error-or-hint line beneath a field: shows the FieldError when there is an error, otherwise the FieldDescription hint. With no explicit error, the FieldError renders unmatched so Base UI's own error channel stays open — validity messages and external Form errors for this field display (and clear) automatically. A components-tier composition of the two elements parts; shared by the ready-made field types so the error-XOR-hint rule lives in one place.

PropTypeDefaultDescription
size(required)"md" | "lg" | "xl" | "2xl"—
hintReactNode—
errorReactNode—