Labeled field wrapper with validation messaging.
components/ui/form/form.tsx@lumioui/core@latestreact-native-reanimated@*| Form | ||
| disabled? | boolean | Disable all fields in the form (exposed via useFormContext). |
| className? | string | |
| FormField | ||
| name? | string | Field name (for identification/analytics). |
| label? | string | Shorthand label — equivalent to rendering <Form.Label>. |
| required? | boolean | Show a required asterisk on the label. |
| error? | string | Error message — renders <Form.Message> and marks the field invalid. |
| description? | string | Hint text shown when there is no error. |
| className? | string | |
| labelClassName? | string | |
| FormLabel | ||
| className? | string | |
| FormMessage | ||
| className? | string | |
| FormSection | ||
| title? | string | Optional header text rendered above the group, iOS-settings style. |
| footer? | string | Optional footer text rendered below the group. |
| titleClassName? | string | Extra classes for the header text. |
| footerClassName? | string | Extra classes for the footer text. |
| className? | string | |
| FormRow | ||
| label | string | Primary label. |
| description? | string | Secondary description below the label. |
| leading? | React.ReactNode | Slot rendered before the label (icon, avatar). |
| trailing? | React.ReactNode | Control rendered on the trailing side (Switch, value text, etc.). |
| showChevron? | boolean | Show a disclosure chevron on the trailing edge. |
| haptic? | "light" | "selection" | false | Haptic on press. Default "selection"; false to disable. |
| className? | string | |
| labelClassName? | string | |
| descriptionClassName? | string | |
| children? | React.ReactNode | |
| FormSeparator | ||
| className? | string | |
Labeled field wrapper with validation messaging.
import { FormCheckout } from "@/components/ui/form/variants/checkout";
export function Example() {
return (
<FormCheckout />
);
} import * as React from "react";
import { View } from "react-native";
import { Form } from "../form";
import { Icon } from "../../icon/icon";
import { Input } from "../../input/input";
import { Text } from "../../text/text";
import { Glass } from "../../glass/glass";
/** FormCheckout — labeled fields with live validation and helper copy. */
export function FormCheckout() {
const [address, setAddress] = React.useState("");
const [phone, setPhone] = React.useState("");
const addressError = address.length > 0 && address.length < 8 ? "Enter the full street address" : undefined;
return (
<View className="w-full gap-3">
<Glass interactive curvature="edge" className="w-full gap-3 rounded-2xl p-4">
<Text variant="small" className="font-semibold">Checkout · Order #8421</Text>
<Form className="w-full gap-3">
<Form.Field name="address" label="Delivery address" required error={addressError} description="Courier arrives in 25–35 min.">
<Input glass placeholder="742 Evergreen Terrace, Apt 4B" value={address} onChangeText={setAddress} />
</Form.Field>
<Form.Field name="phone" label="Phone" required error={phone.length > 0 && phone.length < 7 ? "Enter a reachable phone number" : undefined}>
<Input glass placeholder="(415) 555-0132" value={phone} onChangeText={setPhone} keyboardType="phone-pad" leftIcon={<Icon name="phone" size="sm" color="mutedForeground" />} />
</Form.Field>
<Form.Field name="notes" label="Kitchen notes" description="Allergies, spice level, extra noodles…">
<Input glass placeholder="Extra chili oil, no sesame please" />
</Form.Field>
</Form>
</Glass>
</View>
);
}
Labeled field wrapper with validation messaging.
import { FormPreferences } from "@/components/ui/form/variants/preferences";
export function Example() {
return (
<FormPreferences />
);
} import * as React from "react";
import { View } from "react-native";
import { Form } from "../form";
import { Icon } from "../../icon/icon";
import { Switch } from "../../switch/switch";
import { Text } from "../../text/text";
import { Glass } from "../../glass/glass";
/** FormPreferences — iOS grouped section with switch rows. */
export function FormPreferences() {
const [chopsticks, setChopsticks] = React.useState(true);
const [contactless, setContactless] = React.useState(true);
const [saveAddress, setSaveAddress] = React.useState(false);
return (
<View className="w-full gap-3">
<View className="w-full">
<Text className="mx-4 mb-2 text-xs font-medium uppercase tracking-wide text-white drop-shadow">
Preferences
</Text>
<Glass interactive curvature="edge" className="overflow-hidden rounded-2xl">
<Form.Row
label="Extra chopsticks"
description="Two pairs, free of charge"
leading={<Icon name="utensils" size="sm" color="primary" />}
trailing={<Switch checked={chopsticks} onCheckedChange={setChopsticks} />}
/>
<Form.Separator />
<Form.Row
label="Contactless delivery"
description="Left at your door, photo on drop-off"
leading={<Icon name="package" size="sm" color="primary" />}
trailing={<Switch checked={contactless} onCheckedChange={setContactless} />}
/>
<Form.Separator />
<Form.Row
label="Save this address"
description="Faster checkout next time"
leading={<Icon name="map-pin" size="sm" color="primary" />}
trailing={<Switch checked={saveAddress} onCheckedChange={setSaveAddress} />}
/>
</Glass>
<Text className="mx-4 mt-2 text-xs text-white drop-shadow">
Saved with your Sakura Ramen profile.
</Text>
</View>
</View>
);
}