Eney
Widgets

Form

The Form is the primary container for user input. It consists of three sections:

  1. Header — an optional header element (e.g. a CardHeader)
  2. Form fields — input elements laid out in a column
  3. ActionPanel — a panel with actions for the form

All form fields are controlled. This means:

  • The component holds the “source of truth” in its state (e.g. useState)
  • The field's value comes from that state
  • The field's onChange updates that state
PropertyDescriptionTypeDefaultRequired
childrenThe form input fieldsReact.ReactNodeYes
actionsA reference to an ActionPanelReact.ReactNodeNo
headerHeader elementReact.ReactNodeNo

Usage

Wrap your input fields and actions within the Form component to create a structured interface:

import { useState } from "react";
import { Form, Action, ActionPanel } from "@eney/api";

function MyForm() {
  const [name, setName] = useState("");

  function onSubmit() {
    // handle form submit
  }

  const actions = (
    <ActionPanel>
      <Action.SubmitForm title="Submit" onSubmit={onSubmit} />
    </ActionPanel>
  );

  return (
    <Form actions={actions}>
      <Form.TextField
        name="name"
        label="Name"
        value={name}
        onChange={setName}
      />
    </Form>
  );
}

Form.TextField

Use for single-line text input.

TextField

Properties

PropertyDescriptionTypeDefaultRequired
nameUnique name of the form fieldstringYes
valueThe current value of the fieldstring""No
onChangeCallback triggered when the value changes(value: string) => voidYes
labelThe label displayed for the fieldstringNo
isCopyableAdds a copy button to the fieldbooleanNo

Usage

Create a standard text input by linking the value and onChange props to your component's state:

import { useState } from "react";
import { Form } from "@eney/api";

function MyWidget() {
  const [city, setCity] = useState("");

  return (
    <Form>
      <Form.TextField
        name="city"
        label="City"
        value={city}
        onChange={setCity}
      />
    </Form>
  );
}

Form.NumberField

Numeric input with optional min/max bounds.

NumberField

Properties

PropertyDescriptionTypeDefaultRequired
nameUnique name of the form fieldstringYes
valueThe current value of the fieldnumber | null0No
onChangeCallback triggered when the value changes(value: number | null) => voidYes
labelThe label displayed for the fieldstringNo
minMinimum allowed valuenumberNo
maxMaximum allowed valuenumberNo

Usage

Set up a numeric input field with a defined range:

import { useState } from "react";
import { Form } from "@eney/api";

function MyWidget() {
  const [quantity, setQuantity] = useState<number | null>(1);

  return (
    <Form>
      <Form.NumberField
        name="quantity"
        label="Quantity"
        value={quantity}
        onChange={setQuantity}
        min={1}
        max={100}
      />
    </Form>
  );
}

Form.PasswordField

Masked text input for sensitive values.

PasswordField

Properties

PropertyDescriptionTypeDefaultRequired
nameUnique name of the form fieldstringYes
valueThe current value of the fieldstring""No
onChangeCallback triggered when the value changes(value: string) => voidYes
labelThe label displayed for the fieldstringNo

Usage

import { useState } from "react";
import { Form } from "@eney/api";

function MyWidget() {
  const [apiKey, setApiKey] = useState("");

  return (
    <Form>
      <Form.PasswordField
        name="apiKey"
        label="API Key"
        value={apiKey}
        onChange={setApiKey}
      />
    </Form>
  );
}

Form.Dropdown

Provides a selection menu for users. Functions as a standard drop-down list by default. When searchable is true, as a searchable autocomplete field.

Dropdown

Properties

PropertyDescriptionTypeDefaultRequired
nameUnique name of the form fieldstringYes
valueThe current selected valuestringNo
onChangeCallback triggered when the value changes(value: string) => voidYes
labelThe label displayed for the fieldstringNo
searchableEnables a search field with autocomplete suggestionsbooleanfalseNo
childrenForm.Dropdown.Item elementsReact.ReactNodeYes

Form.Dropdown.Item

Use Form.Dropdown.Item to define individual selectable options within a Form.Dropdown list.

Dropdown

Properties

PropertyDescriptionTypeDefaultRequired
valueUnique value of the dropdown itemstringYes
titleThe title displayed for the itemstringYes

Usage

Populate your dropdown by adding multiple items with unique values:

import { useState } from "react";
import { Form } from "@eney/api";

function MyWidget() {
  const [currency, setCurrency] = useState("usd");

  return (
    <Form>
      <Form.Dropdown
        name="currency"
        label="Currency"
        value={currency}
        onChange={setCurrency}
      >
        <Form.Dropdown.Item value="usd" title="USD" />
        <Form.Dropdown.Item value="eur" title="EUR" />
        <Form.Dropdown.Item value="uah" title="UAH" />
        <Form.Dropdown.Item value="pln" title="PLN" />
      </Form.Dropdown>
    </Form>
  );
}

Form.Checkbox

Toggle input that can be displayed as a checkbox or a switch.

Checkbox

Properties

PropertyDescriptionTypeDefaultRequired
nameUnique name of the form fieldstringYes
labelThe label displayed for the fieldstringYes
checkedThe current state of the checkboxbooleanYes
onChangeCallback triggered when the value changes(value: boolean) => voidYes
variantDisplay variant"checkbox" | "switch""checkbox"No

Usage

Add a simple switch to your form to handle boolean settings:

import { useState } from "react";
import { Form } from "@eney/api";

function MyWidget() {
  const [enabled, setEnabled] = useState(false);

  return (
    <Form>
      <Form.Checkbox
        name="notifications"
        label="Enable notifications"
        checked={enabled}
        onChange={setEnabled}
        variant="switch"
      />
    </Form>
  );
}

Form.DatePicker

Allows users to select a specific date, time, or both.

DatePicker

Properties

PropertyDescriptionTypeDefaultRequired
nameUnique name of the form fieldstringYes
labelThe label displayed for the fieldstringYes
valueThe current date valueDateYes
onChangeCallback triggered when the value changes(value: Date) => voidYes
typeThe types of date components the user can pick"date" | "time" | "datetime""datetime"No

Usage

import { useState } from "react";
import { Form, Paper, Action, ActionPanel } from "@eney/api";

function CountdownWidget() {
  const [date, setDate] = useState<Date>(new Date());
  const [result, setResult] = useState<string | undefined>();

  function onSubmit() {
    const now = new Date();
    const delta = date.getTime() - now.getTime();
    const days = Math.floor(delta / (1000 * 60 * 60 * 24));
    setResult(`${days} days remaining`);
  }

  return (
    <Form
      actions={
        <ActionPanel>
          <Action.SubmitForm title="Calculate" onSubmit={onSubmit} />
        </ActionPanel>
      }
    >
      <Form.DatePicker
        name="date"
        label="Target date"
        value={date}
        onChange={setDate}
        type="date"
      />
      {result && <Paper markdown={result} />}
    </Form>
  );
}

Form.FilePicker

Allows users to select files from their Mac. Supports both single and multiple file selections.

Users may delete or move files after selecting them, but before the form is submitted. Always verify that files still exist before your extension acts on them.

FilePicker

Properties

PropertyDescriptionTypeDefaultRequired
nameUnique name of the form fieldstringYes
labelThe label displayed for the fieldstringNo
valueCurrent file path(s). Expects an array if multiple is truestring | string[]No
onChangeCallback triggered when selection changes(value: string | string[]) => voidYes
multipleAllow selecting multiple filesbooleanfalseNo
acceptUniform Type Identifiers to filter by typestring[]No

Usage

import { useState } from "react";
import { Form } from "@eney/api";

function MyWidget() {
  const [files, setFiles] = useState<string[]>([]);

  return (
    <Form>
      <Form.FilePicker
        name="attachments"
        label="Select files"
        value={files}
        onChange={setFiles}
        multiple
      />
    </Form>
  );
}

Form.RichTextEditor

Provides a multi-line input field that supports rich text formatting, such as bolding, lists, and headers.

RichTextEditor

Properties

PropertyDescriptionTypeDefaultRequired
valueThe current text contentstring""No
onChangeCallback triggered when the content changes(value: string) => voidYes
isInitiallyFocusedWhether the editor receives focus on mountbooleanNo

Usage

import { useState } from "react";
import { Form, Action, ActionPanel } from "@eney/api";

function NoteEditor() {
  const [content, setContent] = useState("");

  function onSubmit() {
    // process content
  }

  return (
    <Form
      actions={
        <ActionPanel>
          <Action.SubmitForm title="Save" onSubmit={onSubmit} />
        </ActionPanel>
      }
    >
      <Form.RichTextEditor
        value={content}
        onChange={setContent}
        isInitiallyFocused
      />
    </Form>
  );
}