Skip to main content

Controls

Hosanna UI controls are regular Hosanna views with a helpful opinionated API. They inherit the same lifecycle, state model, layout, and styling mechanisms as other views, then add control-specific behavior (events, keyboard handling, composition).

How Controls Work

  • They extend views: Controls subclass the same BaseView as primitives and groups. You use them declaratively in getViews().
  • Stateful styling: Controls read styles via styleKey, and apply the correct sub-style based on ViewStatus (e.g., normal, focused, selected).
  • Focus-aware: Each view has isFocused; the focus system updates it automatically. ViewStatus tracks high-level interaction state and drives styles.
  • Custom data: Use customData(...) to attach arbitrary data. Retrieve it strongly typed at runtime with view.getCustomData<T>().
Tip: Start Simple

Most controls accept text, style keys, and event callbacks. Add features incrementally to keep performance predictable.

Styling Controls with Stateful Styles

Controls use the same theme style system as all views. A styleKey points to a style entry in your style.config.json. Control styles typically live under controls.<ControlType>.<subStyle> and contain per-status dictionaries:

{
"controls": {
"Button": {
"default": {
"normal": { "color": "~theme.colors.white" },
"focused": { "color": "~theme.colors.red" },
"selected": { "opacity": 0.9 }
},
"primary": {
"normal": { "titleFontKey": "~theme.fonts.text-bold-20" }
}
}
}
}
  • styleKey: For example, controls.Button.default or controls.Button.primary.
  • Stateful: Sub-keys such as normal, focused, selected, disabled, error, focusSelected map to ViewStatus values.
  • Auto-application: When focus changes, the framework switches the active style sub-dictionary automatically.
Where Control Styles Live

Use controls.<ControlType>.<subStyle> for control styles (e.g., controls.Button.default). Keep tokens (~theme.colors.*, ~theme.fonts.*) for portability.

Focus, ViewStatus, and Styles

  • isFocused is updated by the focus system. You do not set it manually.
  • ViewStatus can be controlled when needed (e.g., programmatically select a control), and the style engine uses it to pick the right sub-style.
  • Typical statuses: normal, focused, selected, disabled, error, focusSelected.
Don’t Mutate During Animation

Avoid changing view state inside animation ticks. Let the animator finish, then persist the final logical state.

Custom Data on Controls

Attach context to any view/control and retrieve it later without type assertions scattered across your code:

Button({ text: 'Details', styleKey: 'controls.Button.primary' })
.customData({ productId: item.id })
.onClick((event) => {
const data = event.view.getCustomData<{ productId: string }>();
this.openDetails(data.productId);
});

Example: Button + Stateful Styles

Button({
text: 'Click me',
styleKey: 'controls.Button.default',
width: 300,
height: 50,
})
.onClick(() => this.count++)
.customData({ kind: 'primary-action' });
  • On focus, ViewStatus becomes focused, and the style engine applies the focused style automatically.
  • You can set viewStatus(ViewStatus.Selected) when you need a selected visual state.

Controls Index

Use the pages below for focused guides and live examples:

  • Button
  • CheckBox
  • ComboBox
  • ScrollView
  • Popup
  • MiniKeyboard