# Field Properties



Field properties set how a single field looks and behaves: its label, input control, format, help text, computed value, validation, visibility, and width. They are structured properties grouped by concern.

Set a field's baseline on the entity's `data` node, keyed by field name. Every page that renders the field uses it. For fields on the quote root, such as `startTime`, see [Quote-Root Fields](#quote-root-fields). This example is from `uiConfigs/operationsWorkbench/products/HO3/config.json`:

```json
{
	"data": {
		"commission": {
			"display": { "label": "Commission", "format": "percentage" }
		},
		"expireIn": {
			"display": { "label": "Quote to expire in", "suffix": " days" },
			"tooltip": {
				"content": "Number of days after quote generation that the offer is valid for"
			}
		},
		"submissionDate": {
			"display": { "label": "Date Request Received" },
			"tooltip": {
				"content": "The date the request was received from the agent"
			}
		}
	}
}
```

| Property       | Type    | Description                                                                           |
| -------------- | ------- | ------------------------------------------------------------------------------------- |
| `display`      | object  | How the field renders and which input control it uses. See [Display](#display).       |
| `tooltip`      | object  | Help text shown on hover or focus. See [Tooltip](#tooltip).                           |
| `compute`      | object  | Derives the field's value from another value plus an offset. See [Compute](#compute). |
| `validation`   | object  | Constraints on the value. See [Validation](#validation).                              |
| `access`       | object  | Whether the field is visible and editable. See [Field Access](#field-access).         |
| `layout`       | object  | The field's width and framing. See [Field Layout](#field-layout).                     |
| `prepopulated` | boolean | Pre-fills the field with a default or derived value on render.                        |

The same properties apply to the fields of a custom data type, under the data type's own `data` node in `dataTypes/`. They apply wherever a field of that type is shown.

Quote-Root Fields [#quote-root-fields]

A quote or policy has a few fields on the entity root rather than inside `data`, such as `startTime`, `endTime`, and `expirationTime`. To relabel or reformat one everywhere it renders, add it as a top-level key on the product node, beside `data` and `staticData`. It takes the same properties as a `data` entry. This example is from `uiConfigs/operationsWorkbench/products/HO3/config.json`:

```json
{
	"display": { "label": "Homeowners" },
	"startTime": {
		"display": { "label": "Proposed Effective Time", "format": "date" }
	},
	"expirationTime": { "display": { "label": "Expiration" } },
	"data": {
		"expireIn": { "display": { "label": "Quote to expire in" } }
	},
	"staticData": {
		"quoteDueDate": { "display": { "label": "Quote Due Date" } }
	}
}
```

* A root field placed under `data` has no effect, because it isn't part of the product's data model.
* A section's [inline override](#baseline-and-inline-overrides) for the same field wins over this one.
* Only these root fields are recognized: `startTime`, `endTime`, `expirationTime`, `effectiveTime`, `currency`, `timezone`, `billingLevel`, `billingTrigger`, `durationBasis`, `delinquencyPlanName`, `autoRenewalPlanName`, and `preferences.installmentPreferences.installmentPlanName`. A misspelled field name is ignored.
* Static data fields go under `staticData`, keyed by field name, in the same shape as `data`.

Display [#display]

| Property      | Type             | Description                                                                                                                                                                            |
| ------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `label`       | string or object | The field's label. A string is the label text; `{ "text": …, "markdown": true }` renders it as markdown. Replaces the data model's `displayName`.                                      |
| `control`     | string or object | The input widget only: `radio-group`, `dropdown`, `multiselect` (with `variant: "checkbox"`), `textarea`, `rich-text`, `table`, or `media`. Omit to use the default for the data type. |
| `format`      | string or object | Value formatting: `currency` (optional `currencyCode`, defaulting to the quote currency), `percentage`, or `date`.                                                                     |
| `suggestions` | array            | Pre-written text options the user can insert: a string array, or groups gated by a condition, `{ "when": <condition>, "options": [...] }`.                                             |
| `suffix`      | string           | Static text after the input, such as `" days"`.                                                                                                                                        |
| `details`     | string           | Additional descriptive text for the field.                                                                                                                                             |
| `className`   | string           | A raw Tailwind CSS class. Use sparingly, and prefer a typed property when one exists.                                                                                                  |

<Callout>
  Currency, percentage, and date are formats, not controls: set them in `display.format`, never in `display.control`.
</Callout>

The `media` control (file upload) takes `multiple`, `minItems` (the minimum when `multiple` is set), and `scope: "quoteGroup"` (attach documents to the quote group rather than the quote; the quote must already belong to a quote group). The `rich-text` control stores sanitized HTML, so formatting carries into generated documents.

Tooltip [#tooltip]

Provide exactly one body source.

| Property  | Type   | Description                                   |
| --------- | ------ | --------------------------------------------- |
| `content` | string | Inline tooltip text.                          |
| `asset`   | string | Path to a markdown file in the config assets. |
| `format`  | string | `markdown` renders the body as markdown.      |

Compute [#compute]

| Property      | Type   | Description                                                                                                                                                              |
| ------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `from`        | string | The base value: a field path, bare for a quote-root field (`startTime`) and `data.`-prefixed for a data field (`data.expireIn`), or a token (`today`, `submissionDate`). |
| `op`          | string | `add` or `subtract`.                                                                                                                                                     |
| `amount`      | number | A literal offset. Mutually exclusive with `amountField`.                                                                                                                 |
| `amountField` | string | Reads the offset from another field, such as `data.expireIn`. Mutually exclusive with `amount`.                                                                          |
| `unit`        | string | `days` or `years`.                                                                                                                                                       |

This example sets a date one year after the start date:

```json
{
	"compute": { "from": "startTime", "op": "add", "amount": 1, "unit": "years" }
}
```

Validation [#validation]

| Property     | Type                                   | Description                                                                                           |
| ------------ | -------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `min`, `max` | number, compute object, or `{ field }` | A literal bound, a relative bound (such as today plus 180 days), or a bound taken from another field. |
| `step`       | number                                 | The value must be a multiple of this step, such as `1000`.                                            |

Field Access [#field-access]

A field takes the data-driven subset of [access](/configuration/configurable-ui/scope-and-access#access):

| Effect  | Form                        | Description                               |
| ------- | --------------------------- | ----------------------------------------- |
| `read`  | `false`                     | Always hide the field.                    |
| `read`  | `{ "unless": <condition> }` | Hide the field while the condition holds. |
| `write` | `false`                     | Show the value but block editing.         |

Omit an effect to leave it granted. Keep the following in mind:

* `read` is the only field effect that takes a condition. A field's `write` is unconditional; to make fields read-only under a condition, set `access.write` on the section or step instead.
* A field can't use `roles`, `scope`, `when`, or a list of alternative rules. Put those on the section or step instead; they cascade to the fields inside.
* A field's `unless` must be flat: a single condition, or one `all` or `any` group.
* For a field whose value is an array, such as a multi-select, `eq` and `in` mean "contains". Prefer scalar fields for field conditions.

In this example, from a product's `data`, the producer code is hidden unless `isThisCannedPlan` is "Yes", and can't be edited:

```json
{
	"producerCode": {
		"access": {
			"read": {
				"unless": {
					"field": "isThisCannedPlan",
					"operator": "neq",
					"value": "Yes"
				}
			},
			"write": false
		}
	}
}
```

Field Layout [#field-layout]

A field accepts a subset of the [layout](/configuration/configurable-ui/sections#layout) object.

| Axis          | Field values  | Description                                                                                                                                                                       |
| ------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `width`       | `full`, `1/2` | The field's width in its row. Omit for the default grid cell.                                                                                                                     |
| `variant`     | `flat`        | Complex fields only. Drops the field's frame.                                                                                                                                     |
| `collapse`    | `expanded`    | On a complex field, renders the field in a collapsible panel, open by default. On a primitive field, adds an add/remove toggle instead. See the warning below.                    |
| `orientation` | `horizontal`  | Complex fields only. Controls how the field's nested children flow. \[TODO: confirm wording with engineering; the guide describes `horizontal` as stacking children one per row.] |

<Callout type="warn">
  On a primitive field, `collapse` is destructive: collapsing the field clears its value. Set it on a primitive field only where that is intended.
</Callout>

Baseline and Inline Overrides [#baseline-and-inline-overrides]

When a section lists a field in `include`, the entry can be a bare path or an inline override: an object with the field's path in `fieldName`, plus any field properties. For example, in a section:

```json
{
	"include": [
		{
			"fieldName": "startTime",
			"display": { "label": "Effective Date", "format": "date" }
		},
		"data.submissionDate"
	]
}
```

An inline override applies only to the section that declares it, and wins over the baseline for the properties it sets. Use the baseline for presentation that should apply everywhere, and inline overrides for one-off wording or behavior.

<Callout>
  In the editor, an inline override can't set `access` yet. Set it on the field's baseline or on the section instead.
</Callout>

Next Steps [#next-steps]

* [Sections and Layout](/configuration/configurable-ui/sections)

See Also [#see-also]

* [Configurable UI Overview](/configuration/configurable-ui/overview)
* [Scope, Access, and Conditions](/configuration/configurable-ui/scope-and-access)
* [Configure Fields](/learning/configurable-ui/fields)
