Propel

Select Field

A labeled select with description, popup options, and helper or error text.

Choose the default role for new members.

You can change this later.

Show code
import { SelectField } from "@makeplane/propel/components/select-field";

const ROLES = [
  { label: "Admin", value: "admin" },
  { label: "Member", value: "member" },
  { label: "Guest", value: "guest" },
];

export default function BasicDemo() {
  return (
    <SelectField
      name="role"
      label="Member role"
      description="Choose the default role for new members."
      size="lg"
      options={ROLES}
      defaultValue="member"
      hint="You can change this later."
    />
  );
}

Installation

import { SelectField } from "@makeplane/propel/components/select-field";

Usage

import { SelectField } from "@makeplane/propel/components/select-field";

const ROLES = [
  { label: "Admin", value: "admin" },
  { label: "Member", value: "member" },
  { label: "Guest", value: "guest" },
];

export default function BasicDemo() {
  return (
    <SelectField
      name="role"
      label="Member role"
      description="Choose the default role for new members."
      size="lg"
      options={ROLES}
      defaultValue="member"
      hint="You can change this later."
    />
  );
}

Examples

Sizes

Size steps the label, helper text, and trigger together. The popup’s option rows stay a fixed size regardless, matching the Figma spec.

Show code
import { SelectField } from "@makeplane/propel/components/select-field";

const VISIBILITY = [
  { label: "Private", value: "private" },
  { label: "Workspace", value: "workspace" },
  { label: "Public", value: "public" },
];

const SIZES = ["lg", "xl", "2xl"] as const;

export default function SizesDemo() {
  return (
    <div className="flex flex-col gap-4">
      {SIZES.map((size) => (
        <SelectField
          key={size}
          name={`visibility-${size}`}
          label={size}
          size={size}
          options={VISIBILITY}
          defaultValue="workspace"
        />
      ))}
    </div>
  );
}

Ghost

Passing variant="ghost" drops the trigger’s border and fill for a select that sits directly on its parent surface.

Show code
import { SelectField } from "@makeplane/propel/components/select-field";

const VISIBILITY = [
  { label: "Private", value: "private" },
  { label: "Workspace", value: "workspace" },
  { label: "Public", value: "public" },
];

export default function GhostDemo() {
  return (
    <SelectField
      name="visibility-ghost"
      label="Visibility"
      size="lg"
      variant="ghost"
      options={VISIBILITY}
      defaultValue="workspace"
    />
  );
}

With icon

icon shows a leading glyph before the value, forwarded to the trigger’s Icon slot.

Show code
import { Icon } from "@makeplane/propel/components/icon";
import { SelectField } from "@makeplane/propel/components/select-field";
import { Server } from "lucide-react";

const SERVER_TYPES = [
  { label: "General purpose", value: "general" },
  { label: "Compute optimized", value: "compute" },
  { label: "Memory optimized", value: "memory" },
];

export default function WithIconDemo() {
  return (
    <SelectField
      name="serverType"
      label="Server type"
      size="lg"
      options={SERVER_TYPES}
      defaultValue="general"
      icon={<Icon icon={Server} tint="placeholder" />}
    />
  );
}

Disabled

Contact an admin to change your plan.

Show code
import { SelectField } from "@makeplane/propel/components/select-field";

const PLANS = [
  { label: "Free", value: "free" },
  { label: "Pro", value: "pro" },
  { label: "Enterprise", value: "enterprise" },
];

export default function DisabledDemo() {
  return (
    <SelectField
      name="plan"
      label="Workspace plan"
      description="Contact an admin to change your plan."
      size="lg"
      options={PLANS}
      defaultValue="pro"
      disabled
    />
  );
}

Invalid

Passing error marks the field invalid and replaces the helper text with the error message.

A project lead is required before publishing.
Show code
import { SelectField } from "@makeplane/propel/components/select-field";

const MEMBERS = [
  { label: "Unassigned", value: "unassigned" },
  { label: "Ana Silva", value: "ana" },
  { label: "Ravi Kumar", value: "ravi" },
];

export default function InvalidDemo() {
  return (
    <SelectField
      name="lead"
      label="Project lead"
      size="lg"
      options={MEMBERS}
      defaultValue="unassigned"
      error="A project lead is required before publishing."
    />
  );
}

Controlled

Selected: medium

Show code
import { SelectField } from "@makeplane/propel/components/select-field";
import * as React from "react";

const PRIORITIES = [
  { label: "Urgent", value: "urgent" },
  { label: "High", value: "high" },
  { label: "Medium", value: "medium" },
  { label: "Low", value: "low" },
];

export default function ControlledDemo() {
  const [value, setValue] = React.useState<string | null>("medium");
  return (
    <SelectField
      name="priority"
      label="Priority"
      description={`Selected: ${value ?? "none"}`}
      size="lg"
      options={PRIORITIES}
      value={value}
      onValueChange={setValue}
    />
  );
}

API Reference

SelectField

Ready-to-use select field with label, trigger, popup options, and helper/error text.

PropTypeDefaultDescription
label(required)stringVisible field label.
size(required)"lg" | "xl" | "2xl"Label and helper text size.
options(required)readonly SelectFieldOption[]Options rendered in the popup.
requiredbooleanfalseWhether the user must choose a value before submitting a form. Marks the field required: adds a `*` asterisk and sets `required`.
descriptionReactNodeSupporting text shown below the label, above the trigger. Always shown, alongside `hint`/`error`.
errorReactNodeError text shown below the control.
hintReactNodeHelper text shown below the control. Replaced by `error` when an error is set.
iconReactNodeElement shown before the value, e.g. `<Icon icon={Server} tint="placeholder" />`.
variant"secondary" | "ghost""secondary"Figma "Prominence": `secondary` is the bordered trigger, `ghost` drops its border and fill.