Skip to content

Built-in widgets

All widgets that ship with Rangka. Each widget follows the same contract as custom widgets defined via defineWidget().

Data source pattern

Data container widgets (data, form, table) use the source field to declare what model they operate on. This is separate from bind which handles field/expression value binding.

typescript
source: { model: string; id?: string; filters?: Record<string, unknown>; limit?: number }
FieldTypeDescription
modelstringQualified model name (e.g. sales.order)
idstringRecord ID or expression ($route.id, $state.selectedId)
filtersobjectStatic filters applied to the query
limitnumberMaximum number of records

When id is set, the widget operates in record mode (single record). Otherwise it operates in collection mode (list).

The id field supports bare $-prefixed expressions without template syntax:

typescript
// All equivalent for resolving the route parameter
source: { model: 'sales.order', id: '$route.id' }
source: { model: 'sales.order', id: '{{$route.id}}' }

// State variable
source: { model: 'sales.customer', id: '$state.selectedId' }

Input widgets

input

Text and number input field.

PropertyTypeDefaultDescription
labelstringField label
placeholderstringPlaceholder text
readOnlybooleanfalsePrevent editing
disabledbooleanfalseDisable the input
errorstringError message to display
prefixstringText before the input
suffixstringText after the input
minnumberMinimum numeric value
maxnumberMaximum numeric value
stepnumberNumeric step increment
patternstringRegex validation pattern
  • Binding: field
  • Triggers: change, focus, blur
  • Container: no

select

Dropdown selection from field options.

PropertyTypeDefaultDescription
labelstringField label
placeholderstringPlaceholder text
searchablebooleanfalseEnable type-to-search
disabledbooleanfalseDisable the select
  • Binding: field
  • Triggers: change
  • Container: no

checkbox

Boolean toggle input.

PropertyTypeDefaultDescription
labelstringCheckbox label
disabledbooleanfalseDisable the checkbox
  • Binding: field
  • Triggers: change
  • Container: no

textarea

Multiline text input.

PropertyTypeDefaultDescription
labelstringField label
placeholderstringPlaceholder text
rowsnumber4Visible rows
disabledbooleanfalseDisable the input
readOnlybooleanfalsePrevent editing
  • Binding: field
  • Triggers: change, focus, blur
  • Container: no

datepicker

Date selection input.

PropertyTypeDefaultDescription
labelstringField label
disabledbooleanfalseDisable the picker
  • Binding: field
  • Triggers: change
  • Container: no

datetime

Date and time selection input.

PropertyTypeDefaultDescription
labelstringField label
disabledbooleanfalseDisable the picker
  • Binding: field
  • Triggers: change
  • Container: no

money

Currency input with formatting.

PropertyTypeDefaultDescription
labelstringField label
currencystring'$'Currency symbol
disabledbooleanfalseDisable the input
readOnlybooleanfalsePrevent editing
  • Binding: field
  • Triggers: change, focus, blur
  • Container: no

Foreign key reference picker. Searches and selects a record from the linked model.

PropertyTypeDefaultDescription
labelstringField label
placeholderstringPlaceholder text
disabledbooleanfalseDisable the picker
  • Binding: field
  • Triggers: change, search
  • Container: no

many-to-many

Multi-select for many-to-many relationships.

PropertyTypeDefaultDescription
labelstringField label
placeholderstringPlaceholder text
disabledbooleanfalseDisable the picker
  • Binding: field
  • Triggers: change, search
  • Container: no

Polymorphic reference picker. The target model is determined by another field's value.

PropertyTypeDefaultDescription
labelstringField label
modelFieldstringField that stores the target model name
modelsarrayAllowed target models
disabledbooleanfalseDisable the picker
  • Binding: field
  • Triggers: change, search
  • Container: no

attachment

Single file upload.

PropertyTypeDefaultDescription
labelstringField label
acceptstringAllowed MIME types
maxSizestringMaximum file size (e.g., '10mb')
disabledbooleanfalseDisable uploads
  • Binding: field
  • Triggers: change, remove
  • Container: no

attachments

Multiple file upload.

PropertyTypeDefaultDescription
labelstringField label
acceptstringAllowed MIME types
maxSizestringMaximum file size per file
maxCountnumber10Maximum number of files
disabledbooleanfalseDisable uploads
  • Binding: field
  • Triggers: change, remove
  • Container: no

code

Code editor with syntax highlighting.

PropertyTypeDefaultDescription
labelstringField label
languagestringSyntax highlighting language
rowsnumber6Visible rows
disabledbooleanfalseDisable editing
  • Binding: field
  • Triggers: change, focus, blur
  • Container: no

json

JSON editor with validation.

PropertyTypeDefaultDescription
labelstringField label
rowsnumber6Visible rows
disabledbooleanfalseDisable editing
  • Binding: field
  • Triggers: change, focus, blur
  • Container: no

tree

Hierarchical record picker for tree-structured models.

PropertyTypeDefaultDescription
labelstringField label
placeholderstringPlaceholder text
disabledbooleanfalseDisable the picker
  • Binding: field
  • Triggers: change, search
  • Container: no

Display widgets

text

Displays text content bound to a field value.

PropertyTypeDefaultDescription
styleenum'body'heading, body, caption, bold
  • Binding: field
  • Triggers: none
  • Container: no

badge

Colored status label.

PropertyTypeDefaultDescription
variantenum'subtle'solid, outline, subtle
colorenum'default'default, success, warning, error, info
colorMapobjectMaps field values to colors
  • Binding: field
  • Triggers: none
  • Container: no

icon

Displays an icon from the icon set.

PropertyTypeDefaultDescription
namestringrequiredIcon name
sizenumber14Icon size in pixels
colorstringIcon color
  • Binding: none
  • Triggers: click
  • Container: no

image

Displays an image.

PropertyTypeDefaultDescription
srcstringStatic image URL (overrides field binding)
altstringAlt text
widthstringCSS width
heightstringCSS height
  • Binding: field
  • Triggers: none
  • Container: no

computed

Displays a computed field value with formatting.

PropertyTypeDefaultDescription
labelstringDisplay label
formatenum'text'text, number, currency, date
  • Binding: field
  • Triggers: none
  • Container: no

sequence

Displays a sequence field value (auto-generated numbers like INV-00001).

PropertyTypeDefaultDescription
labelstringDisplay label
  • Binding: field
  • Triggers: none
  • Container: no

Layout widgets

group

Arranges children in a row or column with no visual chrome.

PropertyTypeDefaultDescription
directionenum'column'row, column
alignenumstart, center, end, stretch
justifyenumstart, center, end, between, around
gapenum'md'none, xs, sm, md, lg, xl, 2xl
wrapbooleanfalseWrap overflowing children
paddingenumnone, xs, sm, md, lg, xl, 2xl
paddingXenumHorizontal padding
paddingYenumVertical padding
  • Binding: none
  • Triggers: none
  • Container: yes

section

Visual grouping with a label and optional collapsibility.

PropertyTypeDefaultDescription
labelstringrequiredSection heading
collapsiblebooleanfalseAllow collapsing
defaultCollapsedbooleanfalseStart collapsed
paddingenum'md'none, xs, sm, md, lg, xl, 2xl
iconstringIcon name beside the label
  • Binding: none
  • Triggers: none
  • Container: yes

split

Splits children into resizable columns or rows.

PropertyTypeDefaultDescription
sizesarrayPercentage sizes for each pane (e.g., [60, 40])
directionenum'horizontal'horizontal, vertical
minSizenumber10Minimum pane size percentage
paddingenumnone, xs, sm, md, lg, xl, 2xl
  • Binding: none
  • Triggers: none
  • Container: yes

grid

Responsive grid layout.

PropertyTypeDefaultDescription
columnsnumber3Number of columns
gapenum'md'none, xs, sm, md, lg, xl, 2xl
rowGapenumOverride gap for rows
colGapenumOverride gap for columns
autoFlowenum'row'row, column, dense
responsiveobjectBreakpoint overrides
paddingenumnone, xs, sm, md, lg, xl, 2xl
paddingXenumHorizontal padding
paddingYenumVertical padding
  • Binding: none
  • Triggers: none
  • Container: yes

divider

Horizontal separator line.

PropertyTypeDefaultDescription
marginenumnone, sm, md, lg, xl
marginYenumVertical margin override
  • Binding: none
  • Triggers: none
  • Container: no

spacer

Empty space between elements.

PropertyTypeDefaultDescription
sizeenum'md'xs, sm, md, lg, xl
  • Binding: none
  • Triggers: none
  • Container: no

card

Visual card container with optional title and actions.

PropertyTypeDefaultDescription
titlestringCard title
descriptionstringCard description
sizeenum'default'default, sm
actionsarrayHeader action buttons
footerarrayFooter content
  • Binding: none
  • Triggers: none
  • Container: yes

scroll-area

Scrollable container with a fixed height.

PropertyTypeDefaultDescription
directionenum'vertical'vertical, horizontal, both
heightstringCSS height
maxHeightstringCSS max-height
  • Binding: none
  • Triggers: none
  • Container: yes

stack

Vertical stack with height control.

PropertyTypeDefaultDescription
heightstring'auto'CSS height
paddingenumnone, xs, sm, md, lg, xl, 2xl
  • Binding: none
  • Triggers: none
  • Container: yes

column

Declares a table column. Only valid as a direct child of table.

PropertyTypeDefaultDescription
labelstringrequiredColumn header text
widthstringCSS width
alignenum'left'left, center, right
sortablebooleanEnable column sorting
filterablebooleanEnable column filtering
  • Binding: none
  • Triggers: none
  • Container: yes

drawer

Slide-in panel from the right side.

PropertyTypeDefaultDescription
widthenum'md'sm, md, lg
titlestringDrawer title
closablebooleantrueShow close button
  • Binding: none
  • Triggers: none
  • Container: yes

Centered overlay dialog.

PropertyTypeDefaultDescription
sizeenum'md'sm, md, lg
titlestringModal title
closablebooleantrueShow close button
  • Binding: none
  • Triggers: none
  • Container: yes

Action widgets

button

Clickable action trigger.

PropertyTypeDefaultDescription
labelstringrequiredButton text
variantenum'secondary'primary, secondary, ghost, destructive
sizeenum'md'sm, md, lg
disabledbooleanfalseDisable the button
loadingbooleanfalseShow loading state
  • Binding: none
  • Triggers: click
  • Container: no

Data widgets

data

Data container that fetches a record or collection. Children render within the data context.

PropertyTypeDefaultDescription
placeholderstringText shown while loading
pageSizenumberPage size for collection
  • Source: { model, id?, filters?, limit? }
  • Binding: none
  • Triggers: load, error
  • Container: yes
typescript
// Single record
{ type: 'data', source: { model: 'sales.order', id: '$route.id' }, children: [...] }

// Collection
{ type: 'data', source: { model: 'sales.product' }, children: [...] }

form

Data container with form state management. Fetches a record for editing or provides a blank form for creation.

PropertyTypeDefaultDescription
  • Source: { model, id? }
  • Binding: none
  • Triggers: success, error
  • Container: yes

When source.id is set, the form loads the record and enters edit mode. Without id, the form starts in create mode.

typescript
// Edit existing record
{ type: 'form', source: { model: 'sales.order', id: '$route.id' }, children: [...] }

// Create new record
{ type: 'form', source: { model: 'sales.order' }, children: [...] }

repeat

Iterates over a collection, rendering children for each item.

PropertyTypeDefaultDescription
layoutenum'list'list, grid
columnsnumber3Grid columns (when layout is grid)
gapenum'md'sm, md, lg
  • Binding: field
  • Triggers: none
  • Container: yes

table

Data table with pagination, sorting, and selection.

PropertyTypeDefaultDescription
variantenum'card'card, flat
selectablebooleanEnable row selection
borderedbooleanShow cell borders
stripedbooleanAlternate row colors
pageSizenumberRows per page
emptyTextstringText when no records
  • Source: { model, filters?, limit? }
  • Binding: none
  • Triggers: rowClick, select, pageChange
  • Container: yes (accepts column only)

When pageSize is set, the table fetches its own data (smart mode). Without pageSize, it reads records from a parent data container (passive mode).

typescript
{
  type: 'table',
  source: { model: 'sales.order' },
  props: { pageSize: 10, selectable: true },
  children: [
    { type: 'column', props: { label: 'Customer', sortable: true }, bind: { field: 'customer' } },
    { type: 'column', props: { label: 'Status', filterable: true }, bind: { field: 'status' } },
  ],
}

datagrid

Spreadsheet-like grid with inline editing, virtual scrolling, and infinite loading. Use the datagrid when users need to edit data inline, manage rows, or work with large datasets. Use the table widget for simple read-only lists.

PropertyTypeDefaultDescription
pageSizenumber50Records per fetch batch (infinite scroll)
maxHeightnumberautoMax height in px. Defaults to pageSize * rowHeight + 40.
rowHeightenum'default'compact (32px), default (40px), comfortable (52px)
editablebooleantrueEnable inline cell editing
resizablebooleantrueAllow column width resizing
reorderablebooleantrueAllow column drag reordering
selectablebooleantrueShow row numbers with checkbox on hover
addRowbooleanfalseShow add-row button in footer
emptyTextstring'No records'Message when no data
  • Source: { model, filters? }
  • Binding: none
  • Triggers: cellChange, rowSelect, rowCreate, rowDelete
  • Container: yes (accepts column only)

The datagrid uses infinite scroll. It fetches pageSize records per batch and loads more as the user scrolls near the bottom. There is no pagination UI.

Sorting is server-side. Click a column header to sort. Shift+click for multi-column sort. Sort stays stable during inline editing. Rows do not reorder after a cell edit.

New rows appear at the top of the grid. Required fields must be filled before the row persists to the server. The row shows placeholder labels for required fields until they are populated.

When children is empty the datagrid derives columns automatically from model metadata.

typescript
{
  type: 'datagrid',
  source: { model: 'sales.order' },
  props: { pageSize: 50, editable: true, selectable: true, addRow: true },
  children: [
    { type: 'column', bind: { field: 'customer' }, props: { label: 'Customer', sortable: true, filterable: true } },
    { type: 'column', bind: { field: 'status' }, props: { label: 'Status', editable: true, filterable: true } },
    { type: 'column', bind: { field: 'total' }, props: { label: 'Total', sortable: true, editable: true } },
  ],
  on: {
    rowCreate: { type: 'refreshSource' },
    rowDelete: { type: 'refreshSource' },
  },
}

Column props (datagrid)

The datagrid reads these additional props on column children.

PropertyTypeDefaultDescription
labelstringfield nameColumn header text
widthstring'150'Initial width in pixels
minWidthstring'80'Minimum width during resize
maxWidthstringMaximum width during resize
sortablebooleanfalseAllow sorting by this column
filterablebooleanfalseInclude in filter options
editablebooleaninherits from gridOverride grid-level editable for this column
resizablebooleaninherits from gridOverride grid-level resizable for this column
frozenbooleanfalsePin column to left edge during horizontal scroll

Keyboard navigation

KeyAction
Arrow keysMove active cell
Tab / Shift+TabMove right/left, wrap to next/previous row
Enter / F2Enter edit mode
EscapeCancel edit or clear selection
Delete/BackspaceClear active cell value
Ctrl+C / Cmd+CCopy cell value to clipboard
Ctrl+A / Cmd+ASelect all rows
Home / EndMove to first/last cell in row
Ctrl+Home/EndMove to first/last cell in grid

Inline editing

Double-click or press Enter/F2 to edit a cell. The editor type is selected based on the field's data type from model metadata. Edits save immediately on commit (blur or Enter). The cell value is optimistically updated without a full refetch.