FormLayout
A page that is one form: header, fields, then the actions.
Overview
Creating or editing a record on a page of its own.
Form
Do
New client
Who is the quote for?
import { Button, Card, Field, FormLayout, Input, Stack } from "@hackcove/ui";
<FormLayout
title="New client"
subtitle="Who is the quote for?"
onSubmit={(event) => event.preventDefault()}
actions={
<>
<Button type="submit">Save client</Button>
<Button variant="ghost">Cancel</Button>
</>
}
>
<Card title="Client">
<Stack>
<Field label="Full name" htmlFor="do-form-name">
<Input id="do-form-name" placeholder="Naledi Mokoena" />
</Field>
<Field label="Email" htmlFor="do-form-email">
<Input id="do-form-email" type="email" placeholder="[email protected]" />
</Field>
</Stack>
</Card>
</FormLayout>children; Save and Cancel go in actions, at the end of the form.Don't
New client
Who is the quote for?
Client
import { Button, Card, Field, Input, ListLayout, Stack } from "@hackcove/ui";
<ListLayout
title="New client"
subtitle="Who is the quote for?"
actions={<Button>Save client</Button>}
>
<Card title="Client">
<Stack>
<Field label="Full name" htmlFor="dont-form-name">
<Input id="dont-form-name" placeholder="Naledi Mokoena" />
</Field>
<Field label="Email" htmlFor="dont-form-email">
<Input id="dont-form-email" type="email" placeholder="[email protected]" />
</Field>
</Stack>
</Card>
</ListLayout>ListLayout is not a form: Save sits in the header, away from the fields, and nothing submits on Enter. Use FormLayout.Full page
New client
Who is the quote for?
import {
AppShell,
Button,
Card,
Field,
FormLayout,
Input,
NavTabs,
Stack,
} from "@hackcove/ui";
<AppShell
brand={<a href="#">Hack Cove</a>}
nav={
<NavTabs
label="Main"
items={[
{ label: "Quotes", href: "#quotes", active: true },
{ label: "Clients", href: "#clients" },
]}
/>
}
>
<FormLayout
title="New client"
subtitle="Who is the quote for?"
onSubmit={(event) => event.preventDefault()}
actions={
<>
<Button type="submit">Save client</Button>
<Button variant="ghost">Cancel</Button>
</>
}
>
<Card title="Client">
<Stack>
<Field label="Full name" htmlFor="full-page-name">
<Input id="full-page-name" placeholder="Naledi Mokoena" />
</Field>
<Field label="Email" htmlFor="full-page-email">
<Input id="full-page-email" type="email" />
</Field>
</Stack>
</Card>
</FormLayout>
</AppShell>children and Save and Cancel in actions.Usage
- The fields are the
children, grouped inCards; the layout spaces them in a reading-width column. - Save and Cancel go in
actions, at the end of the form: atype="submit"Button first, then a ghost Cancel. The header has noactionshere. - Handle the submit with
onSubmit: other props go on the<form>itself. - A form in a small panel is a
DialogorFieldDialog; a sign-in isCenteredLayout. - Do not put Save in the header of a
ListLayout: that is not a form.
Accessibility
- The root is a real
<form>: Enter in a field submits it, and atype="submit"Button submits it. - The title is the page's
h1. - Give each control a
FieldwithhtmlFor, so every input has a label.
API
FormLayout
A form page: header (no header actions), then a max-w-3xl column that starts at the Container's left edge (it is not re-centred), with an actions row at the end. Other props go on the <form>.
actions- Type
ReactNode
breadcrumbsA Breadcrumbs above the title.
- Type
ReactNode
subtitle- Type
ReactNode
tabsA NavTabs (or similar) under the title.
- Type
ReactNode
title required- Type
ReactNode