Style Syntax
AppConfig styles are plain JSON objects with a small amount of Hosanna-specific resolution syntax. The same rules are used by control styles, fragment styles, row settings, cell settings, and theme tokens.
Style resolution combines variant files, $extends, ~ references, and state buckets before a view consumes the final fields.
Style Keys
Views and controls usually reference styles by key:
Button({
text: 'Continue',
styleKey: 'controls.Button.primary',
});
The key points into assets/meta/app.config.json:
{
"controls": {
"Button": {
"primary": {
"normal": {
"color": "~theme.colors.white",
"titleFontKey": "~theme.fonts.text-bold-20"
},
"focused": {
"color": "~theme.colors.blue400"
}
}
}
}
}
References
Use ~ to resolve another AppConfig path. References keep common tokens in one place and avoid copying raw colors, fonts, image paths, or nested style values.
{
"theme": {
"colors": {
"textPrimary": "#ffffff"
},
"fonts": {
"body": "pkg:/assets/fonts/Poppins-Regular.ttf, 24"
}
},
"controls": {
"Label": {
"default": {
"normal": {
"font": "~theme.fonts.body",
"color": "~theme.colors.textPrimary"
}
}
}
}
}
Inheritance
Use $extends when a style should derive from another style and override only the fields that differ.
{
"controls": {
"Button": {
"primary": {
"normal": { "color": "~theme.colors.white" }
},
"danger": {
"$extends": "controls.Button.primary",
"normal": { "color": "~theme.colors.red500" }
}
}
}
}
The extending object is deep-merged over the base object. Use this for named variants, not for per-row runtime data; CollectionView rows should use settingsOverrides for one-off row changes.
State Buckets
Stateful styles usually group properties by UI state:
{
"normal": {
"opacity": 0.8
},
"focused": {
"opacity": 1,
"scale": [1.05, 1.05]
},
"selected": {
"borderColor": "~theme.colors.accent"
},
"disabled": {
"opacity": 0.35
}
}
Common buckets include normal, focused, selected, disabled, error, and combined states such as focusSelected where a control supports them. Fragment cell styles also use views.base for the initial tree and state buckets for updates to existing fragment children.
Config Variants
Expression-specific files can extend a base config:
{
"$extendFile": "app.config.json",
"theme": {
"fonts": {
"body": "pkg:/assets/fonts/Poppins-Regular.ttf, 18"
}
}
}
Use variants for expression or device differences that should be selected at launch, such as phone, TV, web, or native differences. See Cross-Platform Runtime Model for the runtime selection model.
Where To Go Next
- Use Fragments for fragment trees, constraints, data maps, and callbacks.
- Use Fragment Constraints for inline fragment layout constraints and explicit constraint rules.
- Use Fragment Computed Values for computed fragment fields and numeric constraint arguments.
- Use Cells for
DynamicCellcontent. - Use Rows for CollectionView row layout and overrides.