FieldDialog

A Dialog that asks for one text value.

Overview

Asking for a single name or value: new project, rename, a label.

One field

Do
import { useState } from "react";
import { Button, FieldDialog } from "@hackcove/ui";

function Example() {
  const [open, setOpen] = useState(false);
  return (
    <>
      <Button variant="outline" onClick={() => setOpen(true)}>
        New project
      </Button>
      {open && (
        <FieldDialog
          title="New project"
          description="Projects hold your builds and their reviews."
          label="Name"
          inputLabel="Project name"
          placeholder="my-project"
          hint="Letters, numbers and dashes."
          emptyReason="Type a name first."
          submit="Create"
          busyLabel="Creating…"
          onSubmit={() => new Promise((resolve) => setTimeout(resolve, 600))}
          onClose={() => setOpen(false)}
        />
      )}
    </>
  );
}
One value to ask for is a FieldDialog: it blocks an empty submit, shows the busy state and puts a rejection under the field.
Don't
import { useState } from "react";
import { Button, Dialog, Field, Input } from "@hackcove/ui";

function Example() {
  const [open, setOpen] = useState(false);
  return (
    <>
      <Button variant="outline" onClick={() => setOpen(true)}>
        New project
      </Button>
      {open && (
        <Dialog
          title="New project"
          onClose={() => setOpen(false)}
          footer={<Button onClick={() => setOpen(false)}>Create</Button>}
        >
          <Field label="Name" htmlFor="project-name">
            <Input id="project-name" placeholder="my-project" />
          </Field>
        </Dialog>
      )}
    </>
  );
}
A Dialog with a hand-built field has no empty check, no busy state and no error line, and each copy drifts from the next.

Usage

  • Render it only while it is open, and give every string it shows: title, label, inputLabel, placeholder, hint, emptyReason, submit and busyLabel.
  • onSubmit gets the trimmed value and returns a promise. Resolving closes the dialog; rejecting shows the error message under the field and keeps the dialog open.
  • More than one field is a Dialog with a FormRow or Fields, or a Drawer.

Accessibility

  • It is a Dialog: native <dialog>, page behind inert, focus kept inside, Esc closes, named by its title.
  • The input has focus when it opens and is named by inputLabel.
  • While the field is empty the submit button is disabled and its emptyReason is the button's title and the field's hint.
  • While onSubmit is pending the button is busy (aria-busy); a rejection shows in the field's error line, which is role="alert".

API

FieldDialog

A Dialog with one text field and Cancel / submit buttons. Render it only while open.


busyLabel required
Type
string

description
Type
string

emptyReason required

Said when the field is empty and the submit button is blocked.

Type
string

hint required
Type
string

inputLabel required

The field's accessible name, when it says more than the visible label.

Type
string

label required

The visible label above the field.

Type
string

onClose required
Type
() => void

onSubmit required

Gets the trimmed value. Resolving closes the dialog; a rejection shows its message in it.

Type
(value: string) => Promise<unknown>

placeholder required
Type
string

submit required
Type
string

title required
Type
string