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​

A Button declaration becomes generated state and event metadata, a composed BaseView control, and a target renderer tree driven by AppConfig, focus, and ViewManagerA Button declaration becomes generated state and event metadata, a composed BaseView control, and a target renderer tree driven by AppConfig, focus, and ViewManager

  • 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 AppConfig style system as all views. A styleKey points to a style entry in assets/meta/app.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 reference notes:

ControlUse it for
ButtonFocusable click actions with text, icon, and background styling.
ButtonGroupA fixed four-slot data-driven button group.
CheckBoxBoolean toggle choices.
ComboBoxSingle-choice dropdown selection.
ComboBoxButtonComboBox button surface for custom dropdown work.
ComboBoxCardComboBox dropdown item surface for custom dropdown work.
FragmentViewControl wrapper for mounting a shared AppConfig fragment outside CollectionView.
LabelListA fixed four-slot label group without selection events.
MiniKeyboardThin native keyboard wrapper with a current callback-wiring caveat.
NativeVoiceTextEditBoxNative text editing with voice input.
PinPadThin native PIN-pad wrapper with fixed embedded settings.
PopupOverlay content and modal interaction surfaces.
ScrollContainerLower-level scroll surfaces with custom scrollbar control.
ScrollViewCommon scrollable layouts that follow focus.
TabSelectorSelectable tab rows.
TagBadge/status text with styled background.
TextEditBoxDirect native text edit box usage.
TextInputApp-level input that selects TV, web, or mobile editing.
VoiceTextButtonFixed voice-text prototype; it is not an actionable Button.
Talk to us