Layout Fields
Row
The f.row() layout field arranges fields horizontally. Like other layout fields, rows are UI-only and do not affect data storage. All fields inside a row are flattened to the parent level.
Basic usage
import { f, defineVextroCollection } from "vextro";
export const contacts = defineVextroCollection({
slug: "contacts",
label: "Contacts",
collectionType: "config",
tableName: "contacts",
fields: {
nameRow: f.row({
fields: {
firstName: f.text({ required: true }),
lastName: f.text({ required: true }),
},
}),
email: f.email({ required: true }),
},
}); Options
| Option | Type | Default | Description |
|---|---|---|---|
fields | Record<string, VextroFieldInput> | required | Fields to display in the row. |
gap | number | 16 | Gap between fields in pixels. |
condition | FieldCondition | -- | Condition for showing the entire row. |
Per-field widths
By default, every field in a row gets equal width (2 fields = 50% each, 3 fields = 33.3% each).
Individual fields can declare a width as a percentage. Fields without an explicit width share the remaining space equally:
contactRow: f.row({
fields: {
firstName: f.text(), // auto → 20%
lastName: f.text(), // auto → 20%
email: f.email({ required: true, width: 60 }), // fixed 60%
},
}), Another example -- giving the main field more space:
addressRow: f.row({
fields: {
street: f.text({ width: 50 }), // 50%
city: f.text(), // auto → 16.7%
state: f.text(), // auto → 16.7%
zip: f.text(), // auto → 16.7%
},
}), Conditional rows
Show or hide the row based on another field's value:
dimensionsRow: f.row({
condition: { field: "hasCustomDimensions", equals: true },
fields: {
width: f.number({ required: true }),
height: f.number({ required: true }),
},
}), Data storage
Fields inside a row are stored at the document root level. The row key itself (e.g., nameRow) is not stored -- it only identifies the layout container in admin metadata.