com um clique
rezi-forms
// Set up form input handling with validation and submission. Use when building forms with inputs, selects, checkboxes, etc.
// Set up form input handling with validation and submission. Use when building forms with inputs, selects, checkboxes, etc.
Create a new screen/page for a Rezi TUI application. Use when adding views, pages, or screens to an app.
Profile and optimize Rezi app performance. Use when app feels slow, frames drop, or render phases take too long.
Add routing with guards and nested outlets to a Rezi app. Use when building multi-page/screen TUI applications.
Add modal dialogs and overlay UI with focus trapping. Use when implementing confirmations, alerts, or layered interfaces.
Debug rendering and layout issues in Rezi apps. Use when UI looks wrong, has layout problems, or renders unexpectedly.
Add a new widget type to the Rezi framework. Use when creating new ui.* factory functions with layout, rendering, and tests.
| name | rezi-forms |
| description | Set up form input handling with validation and submission. Use when building forms with inputs, selects, checkboxes, etc. |
| user-invocable | true |
| allowed-tools | Read, Glob, Grep, Edit, Write |
| argument-hint | [form-name] |
| metadata | {"short-description":"Set up forms"} |
Use this skill when:
packages/core/src/forms/useForm.ts — useForm() hookpackages/core/src/widgets/types.ts — InputProps, FieldProps, CheckboxProps, SelectPropspackages/core/src/widgets/ui.ts — ui.input(), ui.field(), ui.checkbox(), ui.select()packages/core/src/ui/recipes.ts — recipe.input(), recipe.button(), recipe.select() for design-system stylingUse the useForm() hook inside a defineWidget:
import { defineWidget, ui, useForm } from "@rezi-ui/core";
const MyForm = defineWidget<{ onSubmit: (v: Values) => void }>((props, ctx) => {
const form = useForm(ctx, {
initialValues: { name: "", email: "" },
validate: (values) => {
const errors: Record<string, string> = {};
if (!values.name) errors.name = "Required";
if (!values.email.includes("@")) errors.email = "Invalid email";
return errors;
},
onSubmit: async (values) => props.onSubmit(values),
});
return ui.column({ gap: 1 }, [
ui.field({
label: "Name",
error: form.errors.name,
children: ui.input({ id: "field-name", ...form.bind("name") }),
}),
ui.field({
label: "Email",
error: form.errors.email,
children: ui.input({ id: "field-email", ...form.bind("email") }),
}),
ui.actions([
ui.button({ id: "cancel", label: "Cancel", intent: "secondary", onPress: () => {} }),
ui.button({ id: "save", label: "Save", intent: "primary", onPress: form.handleSubmit }),
]),
]);
}, { name: "MyForm" });
Bind fields using form.bind("fieldName") — returns object-form input props (value, onInput, onBlur, disabled)
Use ui.field() to wrap inputs with labels and error display
Access form state via form.errors, form.touched, form.dirty, form.submitting
Use success/warning for non-submit side actions:
ui.button({ id: "approve", label: "Approve", intent: "success", onPress: handleApprove });
ui.button({ id: "review", label: "Needs Review", intent: "warning", onPress: handleReview });
Inputs are recipe-styled by default when semantic color tokens are available (for example via a ThemeDefinition preset).
Manual overrides merge on top via the same mergeTextStyle(baseStyle, ownStyle) pattern used by the renderer.
Use manual style only for targeted overrides (merged on top of recipe output).
For button visuals, use intent (primary, secondary, danger, success, warning, link) in app code.
Do not use dsVariant/dsTone in app-level form code.
onSubmit