Browse docs
Browse docs
Form-aware text input built on Material-UI. Integrates automatically with DashForm — registration, validation, and error display are handled for you.
Presets
Layout
Variant
States
Helper text
tsx
<TextField label="Name" placeholder="Enter your name" helperText="Helper text" name="fieldName" />
The basic TextField component requires the name prop to connect the field to the form schema previously defined in <DashForm>.
The label are optional prop is used to display the field label to the user.
<TextField label="Name" name="name" />visibleWhen allows a field to react to form state changes declaratively.
Instead of using watch() in the parent component and conditionally rendering fields with JSX, the
Visiblity rule lives directly on the field itself.
The form engine evaluates the predicate automatically whenever dependent field value change.
<TextField
name="details"
label="Bug details"
visibleWhen={(engine) => engine.getNode('category')?.value === 'bug'}
/>Without visibleWhen, conditional fields are usually implemented with:
watch() callsExample with React Hook Form:
const category = watch('category');
return(
<>
{category === 'bug' && (
<TextField />
)}
</>
);As forms grow, this logic becomes fragmented across components.
With visibleWhen, the dependency stays attached to the field that owns the behavior.
This keeps:
visibleWhen also works in controlled mode.
Even when using value and onChange, the field still partecipates in the Dashforge form engine as long as
the name porp is provided.
<Box sx={{ width: "100%" }}>
<MuiTextField onChange={(v) => setInput(v.target.value)} size="small" label="Enter OK" />
<TextField
label="Email"
name="email"
visibleWhen={() => input === 'OK'}
helperText="Visible because the Input equal to OK"
fullWidth
/>
</Box>The component remains connected to the engine for orchestration if need it, or can evaluate by other state changes
The simplest form with a required text field:
import { DashForm } from '@dashforge/forms';
import { TextField } from '@dashforge/ui';
function MyForm() {
return (
<DashForm onSubmit={(data) => console.log(data)}>
<TextField
name="email"
label="Email"
type="email"
rules={{ required: 'Email is required' }}
/>
</DashForm>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
name | string | — | Field name for React Hook Form registration. Required. |
label | string | — | Label displayed above or beside the field. |
layout | 'floating' | 'stacked' | 'inline' | 'floating' | Controls label position relative to the input. |
helperText | string | — | Hint text shown below the field. Overridden by validation errors. |
rules | RegisterOptions | — | Validation rules passed to React Hook Form. |
disabled | boolean | false | Disables the field. Composed with RBAC via OR logic. |
error | boolean | false | Puts the field into error visual state manually. |
fullWidth | boolean | false | Stretches the field to fill its container. |
multiline | boolean | false | Renders as a textarea. |
rows | number | — | Number of visible rows (multiline only). |
variant | 'outlined' | 'filled' | 'standard' | 'outlined' | MUI TextField variant. |
placeholder | string | — | Placeholder text shown when the field is empty. |
type | string | 'text' | HTML input type (email, password, number, etc.). |
access | AccessRequirement | — | RBAC access requirement. Controls visibility, disabled, and readonly state based on role permissions. See Access Control. |
visibleWhen | (engine: Engine) => boolean | — | Reactive visibility predicate. Field renders only when this returns true AND RBAC grants access. |
<DashForm> — no need for useFormContext or Controller.helperText area automatically when the field is touched.layout prop controls label/field arrangement. floating is the standard MUI floating label style; stacked puts the label above; inline puts it to the left.visibleWhen to conditionally show/hide the field based on other form values — no watch() needed.access to restrict the field based on RBAC permissions — the component calls useAccessState(access) internally and adjusts its state without any manual logic in the parent.Use TextField as a controlled component, integrate with React Hook Form, or leverage reactive capabilities. Choose the adoption level that fits your workflow.
Integration-Friendly
Integrates with React Hook Form via DashForm. Automatic validation, error handling, and familiar RHF patterns.
<DashForm>
<TextField
name="email"
label="Email"
/>
</DashForm>Declarative role-based access control via the access prop. The component calls useAccessState(access) internally and maps the resolved permission to one of three field states — no if statements or manual checks needed in the parent.
The access prop accepts an AccessRequirement object:
| Field | Type | Description |
|---|---|---|
resource | string | The resource being protected (e.g. 'employee', 'invoice'). |
action | string | The action being checked (e.g. 'read', 'update', 'delete'). |
onUnauthorized | 'hide' | 'disable' | 'readonly' | What to render when the user lacks permission. Defaults to 'hide'. |
Hide (default) — field is removed from the DOM entirely:
<TextField
name="salary"
label="Salary"
access={{
resource: 'employee',
action: 'update',
}}
/>Disable — field renders but is non-interactive:
<TextField
name="salary"
label="Salary"
access={{
resource: 'employee',
action: 'update',
onUnauthorized: 'disable',
}}
/>Readonly — field renders and is visible but cannot be edited:
<TextField
name="salary"
label="Salary"
access={{
resource: 'employee',
action: 'update',
onUnauthorized: 'readonly',
}}
/>OR-logic composition — explicit props and RBAC are combined with OR logic, so either source alone is sufficient to disable or make readonly:
{/* Disabled if RBAC denies OR if the form step is not yet reached */}
<TextField
name="signature"
label="Signature"
disabled={step < 3}
access={{
resource: 'contract',
action: 'sign',
onUnauthorized: 'disable',
}}
/>Safe fallback without RbacProvider — if access is provided but no <RbacProvider> wraps the component tree, useAccessState returns full access and logs a development warning. The field is never broken in production by a missing provider:
// Dev warning is logged, but the field renders normally
<TextField
name="field"
label="Field"
access={{ resource: 'data', action: 'read' }}
/>