Snygg Theming Engine
Relevant source files
The following files were used as context for generating this wiki page:
- lib/snygg/src/main/kotlin/org/florisboard/lib/snygg/Snygg.kt
- lib/snygg/src/main/kotlin/org/florisboard/lib/snygg/SnyggTheme.kt
- lib/snygg/src/main/kotlin/org/florisboard/lib/snygg/SnyggStylesheet.kt
- lib/snygg/src/main/kotlin/org/florisboard/lib/snygg/SnyggStylesheetEditor.kt
- lib/snygg/schemas/stylesheet.schema.json
- lib/snygg/src/main/kotlin/org/florisboard/lib/snygg/value/SnyggValueSpec.kt
- app/src/main/kotlin/dev/patrickgold/florisboard/app/settings/theme/EditPropertyDialog.kt
The Snygg Theming Engine (named after the Swedish word for "stylish") is the core system responsible for styling the user interface of the Ownkey Keyboard. It provides a flexible, CSS-like approach to defining appearance rules for keyboard elements, supporting features like inheritance, variable definitions, and dynamic Material You color schemes.
Sources: lib/snygg/src/main/kotlin/org/florisboard/lib/snygg/Snygg.kt:45-49
System Architecture
The engine is structured around three primary stages: specification, serialization (Stylesheet), and runtime application (Theme).
Data Flow Overview
The theming process follows a linear progression from raw JSON data to pre-compiled runtime data, which is then queried by UI components.
Core Components
| Component | Description |
|---|---|
SnyggSpec | The central specification defining all valid property names, allowed value types, and annotation rules. |
SnyggStylesheet | A serializable container for theme rules, typically loaded from a JSON file. |
SnyggTheme | The "compiled" version of a stylesheet, optimized for fast runtime queries. It resolves variables and font references. |
SnyggRule | Defines when a style applies (e.g., to a specific element, key code, or state like :pressed). |
SnyggPropertySet | A collection of property-value pairs (e.g., background: #FF0000). |
Sources: lib/snygg/src/main/kotlin/org/florisboard/lib/snygg/Snygg.kt:51-182, lib/snygg/src/main/kotlin/org/florisboard/lib/snygg/SnyggTheme.kt:55-58, lib/snygg/src/main/kotlin/org/florisboard/lib/snygg/SnyggStylesheet.kt:31-34
Stylesheet Specification
The SnyggSpec defines the vocabulary of the theming engine. It categorizes properties into elements and provides constraints for their values.
Property Categories
Snygg supports a wide range of UI properties, including:
- Colors:
background,foreground,border-color,shadow-color. - Typography:
font-family,font-size,font-style,font-weight,line-height. - Layout:
margin,padding,text-align. - Shapes:
shape(supports rectangle, circle, rounded corners, and cut corners). - Special:
background-image,clip,shadow-elevation.
Sources: lib/snygg/src/main/kotlin/org/florisboard/lib/snygg/Snygg.kt:52-87
Value Specifications (SnyggValueSpec)
Values are parsed using regex-based patterns. The system uses a domain-specific language to define these patterns for different data types.
Rule Matching and Selectors
Rules determine which property sets are applied to which UI elements. Elements can be further refined by attributes and state-based selectors.
Selectors
Snygg supports standard UI states as selectors:
:pressed: Applies when the element is being touched.:focus: Applies when the element has input focus.:hover: Applies when a pointer hovers over the element.:disabled: Applies when the element is inactive.
Sources: lib/snygg/schemas/stylesheet.schema.json:28-28, lib/snygg/src/main/kotlin/org/florisboard/lib/snygg/SnyggTheme.kt:148-150
Attribute Matching
Rules can also target specific element attributes. For example, a rule can apply only to keys with a specific code or group.
Sources: lib/snygg/src/main/kotlin/org/florisboard/lib/snygg/SnyggTheme.kt:139-146
Theme Compilation and Querying
The SnyggTheme object is the runtime engine that resolves styles based on the current UI context.
Compilation Phase
During compilation (SnyggTheme.compileFrom), the engine:
- Resolves Variables: Replaces all
var(--name)references with their defined static values. - Processes Fonts: Loads font assets via an
SnyggAssetResolver. - Sorts Rules: Rules are ordered to ensure that more specific rules (with more attributes or selectors) override more general ones.
Sources: lib/snygg/src/main/kotlin/org/florisboard/lib/snygg/SnyggTheme.kt:81-137
Query Resolution
When a UI element requests its style, the engine executes the following logic:
Dynamic Colors and Material You
Snygg integrates with Android's Material You dynamic color system. Stylesheets can reference colors like dynamic-light-color(primary) or dynamic-dark-color(surface). At runtime, SnyggTheme resolves these into actual Color objects based on the system's current ColorScheme.
Sources: lib/snygg/schemas/stylesheet.schema.json:88-100, lib/snygg/src/main/kotlin/org/florisboard/lib/snygg/SnyggTheme.kt:70-76
JSON Schema
The engine uses a strict JSON schema for validation. The schema defines three root property types:
@defines: A map for variable declarations.@font "Name": An array for defining custom font sources.elementName[attr=val]:selector: Style rules for UI components.
Sources: lib/snygg/schemas/stylesheet.schema.json:11-30
Example Rule Structure
{
"@defines": {
"--my-bg": "#FFFFFF"
},
"key[code=32]:pressed": {
"background": "var(--my-bg)",
"shape": "rounded-corner(4dp, 4dp, 4dp, 4dp)"
}
}
Sources: lib/snygg/schemas/stylesheet.schema.json:11-32, lib/snygg/src/main/kotlin/org/florisboard/lib/snygg/Snygg.kt:101-105
Conclusion
The Snygg Theming Engine provides a powerful and extensible framework for UI customization. By separating the static definition (Stylesheet) from the runtime logic (Theme), it achieves both high performance and deep integration with system features like dynamic color schemes and custom font loading.