# Theming and Styling System **Referenced Files in This Document** - [App.axaml](file://ClassicAssist.Avalonia/App.axaml) - [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs) - [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml) - [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml) - [ResourceDictionary.xaml](file://ClassicAssist/Resources/ResourceDictionary.xaml) - [Colours.xaml](file://ClassicAssist/Resources/Colours.xaml) - [DarkTheme.xaml](file://ClassicAssist/Resources/DarkTheme.xaml) - [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml) - [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml) ## Table of Contents 1. [Introduction](#introduction) 2. [Project Structure](#project-structure) 3. [Core Components](#core-components) 4. [Architecture Overview](#architecture-overview) 5. [Detailed Component Analysis](#detailed-component-analysis) 6. [Dependency Analysis](#dependency-analysis) 7. [Performance Considerations](#performance-considerations) 8. [Troubleshooting Guide](#troubleshooting-guide) 9. [Conclusion](#conclusion) 10. [Appendices](#appendices) ## Introduction This document explains the theming and styling system used by ClassicAssist.Avalonia. It covers how resource dictionaries are organized, how color schemes and themes are defined and switched, how icons are implemented, how fonts are managed, and what cross-platform considerations apply. It also provides guidance for creating custom themes, overriding default styles, implementing responsive design patterns, and building dynamic theme switching with style inheritance hierarchies. ## Project Structure The Avalonia UI layer is organized into Views, Controls, Assets, and App-level configuration. Theming-related resources live both at the application level (Avalonia project) and within shared resources (ClassicAssist project). The main entry point configures global styles and resources. ```mermaid graph TB subgraph "Avalonia App" A["App.axaml"] B["App.axaml.cs"] C["Assets/Icons.xaml"] D["Controls/GroupBox.Theme.xaml"] E["Views/MainWindow.axaml"] F["Views/DialogWindow.axaml"] end subgraph "Shared Resources" G["Resources/ResourceDictionary.xaml"] H["Resources/Colours.xaml"] I["Resources/DarkTheme.xaml"] end A --> C A --> D A --> G A --> H A --> I E --> A F --> A ``` **Diagram sources** - [App.axaml](file://ClassicAssist.Avalonia/App.axaml) - [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs) - [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml) - [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml) - [ResourceDictionary.xaml](file://ClassicAssist/Resources/ResourceDictionary.xaml) - [Colours.xaml](file://ClassicAssist/Resources/Colours.xaml) - [DarkTheme.xaml](file://ClassicAssist/Resources/DarkTheme.xaml) - [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml) - [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml) **Section sources** - [App.axaml](file://ClassicAssist.Avalonia/App.axaml) - [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs) - [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml) - [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml) - [ResourceDictionary.xaml](file://ClassicAssist/Resources/ResourceDictionary.xaml) - [Colours.xaml](file://ClassicAssist/Resources/Colours.xaml) - [DarkTheme.xaml](file://ClassicAssist/Resources/DarkTheme.xaml) - [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml) - [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml) ## Core Components - Application-level resource dictionary: Centralizes merged dictionaries for colors, themes, icons, and control-specific themes. - Color scheme definitions: Shared color tokens that can be reused across controls and views. - Theme definitions: Named sets of resources (colors, brushes, etc.) that can be swapped at runtime. - Icon system: A centralized icon dictionary referenced by views and controls. - Control-level themes: Per-control theme dictionaries to override defaults consistently. - View integration: Views reference theme resources via static resources or themed bindings. Key responsibilities: - App.axaml merges all theme-related dictionaries and exposes them globally. - ResourceDictionary.xaml aggregates shared resources from multiple files. - Colours.xaml defines semantic color tokens. - DarkTheme.xaml provides a complete dark theme set. - Icons.xaml defines reusable vector/icon resources. - GroupBox.Theme.xaml demonstrates control-level theme overrides. **Section sources** - [App.axaml](file://ClassicAssist.Avalonia/App.axaml) - [ResourceDictionary.xaml](file://ClassicAssist/Resources/ResourceDictionary.xaml) - [Colours.xaml](file://ClassicAssist/Resources/Colours.xaml) - [DarkTheme.xaml](file://ClassicAssist/Resources/DarkTheme.xaml) - [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml) - [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml) ## Architecture Overview The theming architecture follows a layered approach: - Global app resources define base tokens and merged dictionaries. - Themes provide named resource sets that can be applied dynamically. - Control-level themes refine appearance for specific components. - Views consume resources through static references and data binding. ```mermaid sequenceDiagram participant App as "App.axaml" participant Merged as "Merged Dictionaries" participant Colors as "Colours.xaml" participant Theme as "DarkTheme.xaml" participant Icons as "Icons.xaml" participant ControlTheme as "GroupBox.Theme.xaml" participant View as "MainWindow.axaml" App->>Merged : "Merge theme resources" Merged->>Colors : "Load color tokens" Merged->>Theme : "Load theme palette" Merged->>Icons : "Load icon definitions" Merged->>ControlTheme : "Load control overrides" View->>Merged : "Resolve resources via StaticResource" Note over View,Merged : "View uses theme tokens and icons" ``` **Diagram sources** - [App.axaml](file://ClassicAssist.Avalonia/App.axaml) - [ResourceDictionary.xaml](file://ClassicAssist/Resources/ResourceDictionary.xaml) - [Colours.xaml](file://ClassicAssist/Resources/Colours.xaml) - [DarkTheme.xaml](file://ClassicAssist/Resources/DarkTheme.xaml) - [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml) - [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml) - [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml) ## Detailed Component Analysis ### Resource Dictionary Structure - Aggregation: A central dictionary merges multiple theme-related dictionaries to keep resources modular and maintainable. - Scope: Resources are available application-wide when merged at the app level; local scopes can override as needed. - Organization: Semantic tokens (colors), theme palettes (dark/light), icons, and control-specific themes are separated into distinct files. Practical implications: - Adding a new theme involves creating a new theme dictionary and merging it at the app level. - Overriding a single token is straightforward by redefining the key in a higher-priority dictionary. **Section sources** - [ResourceDictionary.xaml](file://ClassicAssist/Resources/ResourceDictionary.xaml) - [App.axaml](file://ClassicAssist.Avalonia/App.axaml) ### Color Schemes and Theme Definitions - Color tokens: Defined in a dedicated file to ensure consistency across the UI. - Theme sets: Provide complete palettes (e.g., dark theme) including background, foreground, accent, and state colors. - Switching mechanism: At runtime, replace the active theme dictionary or update resource keys to reflect the selected theme. Guidelines: - Use semantic keys rather than hard-coded values. - Keep theme dictionaries self-contained and keyed consistently. - Ensure contrast and accessibility requirements are met for each theme. **Section sources** - [Colours.xaml](file://ClassicAssist/Resources/Colours.xaml) - [DarkTheme.xaml](file://ClassicAssist/Resources/DarkTheme.xaml) - [App.axaml](file://ClassicAssist.Avalonia/App.axaml) ### Theme Switching Mechanisms Two common approaches: - Dictionary replacement: Swap the active theme dictionary in the merged resources collection. - Resource key updates: Update specific resource keys (e.g., colors) to reflect the new theme without full replacement. Implementation notes: - Perform theme changes on the UI thread to avoid synchronization issues. - Ensure views resolve resources after the change; most XAML-based frameworks automatically refresh when resources change. Example flow: ```mermaid flowchart TD Start(["User selects theme"]) --> Choose["Determine target theme"] Choose --> Replace{"Replace dictionary
or update keys?"} Replace --> |Replace| MergeUpdate["Update merged dictionaries"] Replace --> |Update Keys| KeyUpdate["Set new values for resource keys"] MergeUpdate --> Refresh["UI resolves updated resources"] KeyUpdate --> Refresh Refresh --> End(["Theme applied"]) ``` [No diagram sources since this is a conceptual flow] **Section sources** - [App.axaml](file://ClassicAssist.Avalonia/App.axaml) - [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs) ### Icon System Implementation - Centralized icons: Icons are defined in a dedicated dictionary and referenced by name across views and controls. - Usage pattern: References use static resource lookups by icon key. - Extensibility: New icons are added to the icon dictionary and consumed via their keys. Best practices: - Keep icon assets consistent in size and style. - Prefer vector formats where possible for scalability. - Avoid duplicating icon definitions; always reference the central dictionary. **Section sources** - [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml) - [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml) ### Font Management - Fonts should be embedded as Avalonia resources and referenced by family name. - Use consistent font families across themes to maintain readability. - For cross-platform compatibility, verify font availability and fallbacks. Recommendations: - Define font family tokens in resources for easy overrides. - Test rendering on Windows, macOS, and Linux to ensure consistent appearance. **Section sources** - [App.axaml](file://ClassicAssist.Avalonia/App.axaml) ### Cross-Platform Styling Considerations - Platform differences: Window chrome, DPI scaling, and font rendering vary across platforms. - Responsive behavior: Use relative sizing and flexible layouts to adapt to different screen sizes and densities. - Accessibility: Ensure sufficient contrast and scalable text across themes. Guidance: - Avoid platform-specific assumptions in shared resources. - Validate visual fidelity on each target OS during development. **Section sources** - [App.axaml](file://ClassicAssist.Avalonia/App.axaml) ### Creating Custom Themes Steps: 1. Create a new theme dictionary with consistent resource keys. 2. Define color tokens and any control-specific overrides. 3. Merge the new theme dictionary at the app level. 4. Provide a runtime switch to activate the new theme. Tips: - Mirror existing theme structure for predictability. - Test all major views and controls under the new theme. **Section sources** - [DarkTheme.xaml](file://ClassicAssist/Resources/DarkTheme.xaml) - [App.axaml](file://ClassicAssist.Avalonia/App.axaml) ### Overriding Default Styles Approaches: - Control-level theme dictionaries: Override styles for specific controls (e.g., GroupBox). - Local scope overrides: Apply style overrides within a view’s resource scope. - Global overrides: Redefine resource keys at the app level to affect all instances. Example focus: - GroupBox theme overrides demonstrate targeted control customization. **Section sources** - [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml) ### Implementing Responsive Design Patterns Patterns: - Use flexible panels and grid layouts to adapt to window resizing. - Leverage Avalonia’s built-in layout primitives for responsiveness. - Adjust spacing and typography based on available space. Validation: - Test on various resolutions and DPI settings. - Ensure content remains readable and accessible. **Section sources** - [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml) - [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml) ### Dynamic Theme Switching Example Flow Runtime sequence: ```mermaid sequenceDiagram participant User as "User" participant View as "MainWindow.axaml" participant App as "App.axaml.cs" participant Res as "Resources" User->>View : "Select theme option" View->>App : "Invoke theme switch command" App->>Res : "Update merged dictionaries / resource keys" Res-->>View : "Resources refreshed" View-->>User : "New theme applied" ``` **Diagram sources** - [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs) - [App.axaml](file://ClassicAssist.Avalonia/App.axaml) - [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml) ### Style Inheritance Hierarchies Conceptual hierarchy: - Base tokens (colors, fonts) - Theme palettes (dark/light) - Control-level themes (control-specific overrides) - View-level overrides (local scope) ```mermaid classDiagram class BaseTokens { +Color Primary +Color Secondary +FontFamily Main } class DarkTheme { +Brush Background +Brush Foreground +Brush Accent } class ControlThemes { +Style GroupBox +Style Button } class ViewOverrides { +Local ResourceScope } DarkTheme --> BaseTokens : "extends" ControlThemes --> DarkTheme : "uses" ViewOverrides --> ControlThemes : "overrides" ``` [No diagram sources since this is a conceptual hierarchy] ## Dependency Analysis The theming system depends on a clear separation between resources and views: - App-level merges orchestrate resource loading order. - Theme dictionaries depend on base tokens. - Control themes depend on theme palettes. - Views depend on resolved resources. ```mermaid graph LR Tokens["Base Tokens (Colours.xaml)"] --> Theme["Theme (DarkTheme.xaml)"] Theme --> ControlTheme["Control Theme (GroupBox.Theme.xaml)"] ControlTheme --> View["Views (MainWindow.axaml, DialogWindow.axaml)"] Icons["Icons (Icons.xaml)"] --> View App["App.axaml"] --> Tokens App --> Theme App --> ControlTheme App --> Icons ``` **Diagram sources** - [Colours.xaml](file://ClassicAssist/Resources/Colours.xaml) - [DarkTheme.xaml](file://ClassicAssist/Resources/DarkTheme.xaml) - [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml) - [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml) - [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml) - [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml) - [App.axaml](file://ClassicAssist.Avalonia/App.axaml) **Section sources** - [App.axaml](file://ClassicAssist.Avalonia/App.axaml) - [ResourceDictionary.xaml](file://ClassicAssist/Resources/ResourceDictionary.xaml) ## Performance Considerations - Minimize resource churn: Prefer replacing entire theme dictionaries rather than updating many individual keys when switching themes. - Cache frequently used resources: Let the framework handle caching; avoid redundant lookups in code-behind. - Optimize icon assets: Use vector icons to reduce memory footprint and improve scaling performance. - Avoid heavy animations during theme switches to maintain responsiveness. [No sources needed since this section provides general guidance] ## Troubleshooting Guide Common issues and remedies: - Missing resource keys: Ensure all referenced keys exist in the active theme dictionary. - Incorrect merge order: Verify that base tokens are merged before theme palettes and control themes. - Platform-specific rendering differences: Validate fonts and DPI scaling on each target OS. - Runtime theme not applying: Confirm that resource updates occur on the UI thread and that views resolve resources after updates. Diagnostic steps: - Inspect merged dictionaries at runtime to confirm presence of required keys. - Temporarily revert to a known-good theme to isolate regressions. - Check for typos in resource keys and file paths. **Section sources** - [App.axaml](file://ClassicAssist.Avalonia/App.axaml) - [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs) ## Conclusion ClassicAssist.Avalonia’s theming system leverages a modular resource dictionary structure, semantic color tokens, and theme palettes to enable consistent and extensible styling. By separating concerns—base tokens, theme sets, control-level themes, and view usage—the system supports dynamic theme switching, easy customization, and cross-platform consistency. Following the guidelines here will help you create robust custom themes, override styles effectively, and implement responsive designs. [No sources needed since this section summarizes without analyzing specific files] ## Appendices - Quick checklist for adding a new theme: - Create a new theme dictionary with consistent keys. - Merge it at the app level. - Provide a runtime switch to activate it. - Validate across views and platforms. [No sources needed since this section provides general guidance]