Skip to main content
View as Markdown

Text & Choice Controls

Form controls are the individual inputs a form is built from. They sit inside a form or data-form, or stand alone inside any container.

app.yaml
- type: form
  action: { type: crud, operation: create, table: signups }
  children:
    - { type: input, inputType: email, props: { name: email } }
    - { type: select, options: [{ label: Free, value: free }], props: { name: plan } }
    - { type: switch, checked: true, props: { name: subscribe } }

input

A single-line text input. The HTML input type is the schema-level inputType property — not props.type.

Property Description
inputType text (default), email, password, number, tel, url, or search.

Placeholder, default value, disabled and required all travel through props.

textarea

A multi-line text input.

Property Description
rows Visible number of text lines.
maxLength Maximum character count, enforced as you type.
autoResize Grow the height as the content grows.

select

A dropdown showing the selected value and opening an option list on click.

Property Description
options The choices, at least one. Required unless dataSource is set below.
dataSource Read the choices from a table's rows instead. See below.
defaultValue Pre-selected value.
multiple Allow more than one selection.
searchable Enable type-ahead filtering of the options.
searchPlaceholder Placeholder for the type-ahead field.
allowCustomValue Accept a value that is not in options.

An option is { label, value, disabled, icon }; label and value are required.

Options from a table

Instead of listing the choices by hand, bind the select to a table and let each row become an option:

app.yaml
- type: select
  dataSource:
    table: categories
    displayField: name # required — the row field shown to the user
    valueField: slug # optional — defaults to id
    sort: [{ field: name, direction: asc }]
    filter: [{ field: archived, operator: eq, value: false }]
    limit: 50
  props: { id: category-filter, label: Filter by Category }
Property Description
table Required. The table the option rows come from.
displayField Required. The row field supplying each option's label.
valueField The row field supplying each option's submitted value. Defaults to id.
filter Conditions narrowing the rows, same shape as any other filter (AND logic).
sort Sort rules applied in order.
limit Maximum number of options. Defaults to 100, hard maximum 1000.

options and dataSource are mutually exclusive — both answer "what are the choices", so declaring the two together is refused at startup. displayField has no default on purpose: guessing would silently produce a dropdown of blank rows on any table that did not happen to match.

The rows are read on the server, before the page is sent, so the choices are in the first response — no empty flash on arrival, and crawlers see them. That also means the table's read permission gates the binding: a visitor who may not read the table gets an empty dropdown, and not one of its row values reaches the page. Filters accept $currentUser.* references, resolved per request, so a per-user option list is a supported binding.

Because the whole list is rendered into the page, limit caps it at 1000. A picker over a table larger than that is a different control — one that searches the table as you type instead of inlining it — and is not expressed here.

combobox

Now expressed as select with searchable: true, which accepts the same searchPlaceholder and allowCustomValue.

checkbox

Property Description
checked Render checked.
indeterminate Render the mixed-state dash — for a parent whose children are partly selected.

radio-group

A set of mutually exclusive options.

Property Description
options Required. The options to choose between.
defaultValue Pre-selected option.
orientation horizontal or vertical.

switch

An on/off toggle with an accessible switch role. Accepts checked.

Use switch when the change takes effect immediately, and checkbox when it takes effect on submit — the two look similar and read very differently to someone deciding whether to press Save.

toggle / toggle-group

toggle is a single pressable button that stays pressed. toggle-group groups several.

Property Description
pressed Initial pressed state (toggle only).
options The grouped toggles (toggle-group only).
toggleType single or multiple — how many may be active at once.
orientation horizontal or vertical (toggle-group only).
size Control size.

field

A wrapper that renders a label, a control, a description and an error message as one accessible unit. It is the only form control that takes children.

Property Description
fieldLabel Label associated with the child control.
fieldDescription Help text below the control.
fieldError Error message, rendered in the destructive tone.
required Show a required indicator on the label.
children The wrapped control.
app.yaml
- type: field
  fieldLabel: 'Email'
  fieldDescription: "We'll never share it."
  required: true
  children:
    - { type: input, inputType: email, props: { name: email } }

slider

Moved to Date, Number & File Controls.

date-picker

Moved to Date, Number & File Controls.

time-picker

Moved to Date, Number & File Controls.

number-input

Moved to Date, Number & File Controls.

file-upload

Moved to Date, Number & File Controls.

Last updated August 11, 2026

This documentation was written with AI, so errors or outdated content are possible. Sovrium is in beta. Contributions and corrections are welcome.

Built with Sovrium