Field
The form-field wrapper: label wiring, help text, error messages, and state that flows into any input.
We’ll never share your email.
"use client";
import { Field, Input, Box } from "astralis-ui";
export function FieldDemo() {
return (
<Box w="full" maxW="xs">
<Field required>
<Field.Label>Email address</Field.Label>
<Input type="email" placeholder="you@example.com" />
<Field.HelpText>We’ll never share your email.</Field.HelpText>
</Field>
</Box>
);
}We’ll never share your email.
id
import { Field, Input } from "astralis-ui";
<Field>
<Field.Label>Email address</Field.Label>
<Input type="email" placeholder="you@example.com" />
<Field.HelpText>We’ll never share your email.</Field.HelpText>
</Field>
Import#
import { Field } from "astralis-ui";
// Field.Label, Field.HelpText, Field.ErrorText
// useFieldContext, for your own controlsUsage#
Field is context, not chrome: it generates an id, wires
Field.Label to the input, appends the required *, and pushes invalid,
disabled, required and readOnly down to any Astralis input inside:
Input, Checkbox, Radio, Switch, Select, Slider… no prop repetition.
Validation state#
Flip one invalid flag on the Field and everything reacts: the input
border, and your swap from HelpText to ErrorText.
That username is already taken.
"use client";
import { useState } from "react";
import { Field, Input, Switch, VStack } from "astralis-ui";
export function FieldError() {
const [invalid, setInvalid] = useState(true);
return (
<VStack gap="5" alignItems="stretch" w="full" maxW="xs">
<Switch checked={invalid} onChange={(e) => setInvalid(e.target.checked)} size="sm">
Simulate a validation error
</Switch>
{/* One `invalid` flag restyles the input and swaps the message. */}
<Field invalid={invalid} required>
<Field.Label>Username</Field.Label>
<Input placeholder="astro_naut" />
{invalid ? (
<Field.ErrorText>That username is already taken.</Field.ErrorText>
) : (
<Field.HelpText>Letters, numbers and underscores only.</Field.HelpText>
)}
</Field>
</VStack>
);
}Props#
| Prop | Type | Default | Description |
|---|---|---|---|
invalid | boolean | false | Error styling + `aria-invalid` on the child input. |
disabled | boolean | false | Disables the child input. |
required | boolean | false | Appends `*` to the label, sets `aria-required`. |
readOnly | boolean | false | Read-only state. |
id | string | auto | Explicit id for the label/input pair. |
Field.Label, Field.HelpText and Field.ErrorText accept their native
element attributes.
Custom controls#
useFieldContext() gives a control of your own the same wiring the built-in
inputs get. It returns null outside a Field, so the control still works on
its own.
import { Field, useFieldContext } from "astralis-ui";
function ColorInput(props: React.ComponentProps<"input">) {
const field = useFieldContext();
return (
<input
type="color"
id={field?.id}
aria-describedby={field?.describedBy}
aria-invalid={field?.invalid || undefined}
disabled={field?.disabled}
required={field?.required}
{...props}
/>
);
}
<Field required>
<Field.Label>Brand color</Field.Label>
<ColorInput />
<Field.HelpText>Used for buttons and links.</Field.HelpText>
</Field>| Value | Type | Description |
|---|---|---|
id | string | The id Field.Label points at. Put it on the focusable element. |
describedBy | string | undefined | Ids of the help and error text currently shown, for aria-describedby. |
labelledBy | string | undefined | Id of the rendered label, for controls a <label for> can't name, such as a radio group. |
invalid · disabled · required · readOnly | boolean | undefined | The Field's state flags. |
Accessibility#
- The label's
htmlForand the input'sidare wired automatically. Field.ErrorTextrenders withrole="alert"andaria-live="polite", so screen readers announce validation failures as they happen.