Field
The standard web form input: a label above an inset well.
It is web-only — field.web.tsx has no native counterpart, so the bare specifier resolves here and nowhere else.
The well has a transparent 1.5px border at rest rather than no border, so focusing the field paints the ring without shifting the row it sits in.
function Controlled({ initial = '', ...props }: { initial?: string } & Omit<React.ComponentProps<typeof Field>, 'value' | 'onChangeText'>) {
const [value, setValue] = React.useState(initial);
return <Field {...props} value={value} onChangeText={setValue} />;
}
<Controlled {...args} />Import
import { Field } from '@simal/ui/nativewindui';Props
| Prop | Values | Default | Description |
|---|---|---|---|
label | — | "Legal name" | Sits above the input and stays visible. This is not a placeholder. |
placeholder | — | "Simal Ventures Pvt. Ltd." | Hint shown only while the field is empty. |
error | — | — | Any non-empty string turns the label and border red and renders the message below. Presence is the trigger; there is no separate hasError. |
disabled | boolean | false | Dims the well and blocks input. The field keeps its height, so a disabled row does not reflow. |
numeric | boolean | false | Strips every non-digit on change and switches the keyboard to a number pad. Use for IDs and counts, not for currency. |
prefix | — | — | Static text rendered inside the well before the input, such as a currency symbol or dial code. |
value | — | "" | Makes the field controlled. Pair with onChangeText or it will not accept typing. |
onChangeText | — | — | Required. Receives the new value on every keystroke. |
onBlur | — | — | Fires after focus leaves. Use it to run validation once rather than per keystroke. |
Examples
States
The three states a field can be in, stacked so the well colours are comparable.
function Controlled({ initial = '', ...props }: { initial?: string } & Omit<React.ComponentProps<typeof Field>, 'value' | 'onChangeText'>) {
const [value, setValue] = React.useState(initial);
return <Field {...props} value={value} onChangeText={setValue} />;
}
<View className="gap-5" style={{ maxWidth: 420 }}>
<Controlled label="Default" placeholder="Type here" />
<Controlled label="Filled" initial="Simal Ventures Pvt. Ltd." />
<Controlled label="Disabled" initial="Cannot edit" disabled />
</View>With Error
The error message replaces nothing — it is added below, so the row grows.
function Controlled({ initial = '', ...props }: { initial?: string } & Omit<React.ComponentProps<typeof Field>, 'value' | 'onChangeText'>) {
const [value, setValue] = React.useState(initial);
return <Field {...props} value={value} onChangeText={setValue} />;
}
<View style={{ maxWidth: 420 }}>
<Controlled label="Tax ID" initial="60123" error="Must be 9 digits." numeric />
</View>With Prefix
A prefix sits inside the well, so it reads as part of the value rather than a separate control.
function Controlled({ initial = '', ...props }: { initial?: string } & Omit<React.ComponentProps<typeof Field>, 'value' | 'onChangeText'>) {
const [value, setValue] = React.useState(initial);
return <Field {...props} value={value} onChangeText={setValue} />;
}
<View className="gap-5" style={{ maxWidth: 420 }}>
<Controlled label="Amount" prefix="Rs" initial="12500" numeric />
<Controlled label="Phone" prefix="+977" initial="9800000000" numeric />
</View>In A Grid
Two fields on one row is the dense-grid case the 48px height was chosen for.
function Controlled({ initial = '', ...props }: { initial?: string } & Omit<React.ComponentProps<typeof Field>, 'value' | 'onChangeText'>) {
const [value, setValue] = React.useState(initial);
return <Field {...props} value={value} onChangeText={setValue} />;
}
<View className="flex-row gap-5" style={{ maxWidth: 640 }}>
<Controlled label="Legal name" initial="Simal Ventures Pvt. Ltd." />
<Controlled label="Trading name" initial="Simal" />
</View>DataTable
A table shell over TanStack Table: header row, body, and the three states a remote list actually has — loading, error and empty.
InlineField
The dense-grid sibling of Field: same 48px height and label treatment, but it supports a read-only mode and a monospace value, so it doubles as a display row.