# Theme and Appearance
**Referenced Files in This Document**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
- [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml)
- [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml)
- [HuePickerWindow.axaml](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml)
- [HuePickerWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml.cs)
- [HueEntryToRectanglesValueConverter.cs](file://ClassicAssist.Avalonia/Misc/HueEntryToRectanglesValueConverter.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml)
- [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml)
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
## 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 appearance customization system in ClassicAssist.Avalonia. It covers the Avalonia-based styling architecture, resource dictionary organization, color scheme management (including hue selection and dynamic updates), font configuration and typography, layout customization, icon system and asset management, custom theme development guidelines, style extension patterns, cross-platform appearance consistency, and platform-specific optimizations. The goal is to help you understand how themes are applied at runtime and how to extend or replace them safely across platforms.
## Project Structure
The Avalonia UI layer organizes styles, resources, and views under dedicated folders:
- Assets: global icons and shared assets
- Controls: control templates and themed styles
- Views: window and page XAML that consume resources
- Misc: converters and behaviors used by themed controls
- App-level configuration for application-wide resources and theme switching
```mermaid
graph TB
subgraph "ClassicAssist.Avalonia"
A["App.axaml
Application resources"]
B["Program.cs
Startup entry"]
C["Assets/Icons.xaml
Icon definitions"]
D["Controls/GroupBox.Theme.xaml
Control template/style"]
E["Views/MainWindow.axaml
Main window UI"]
F["Views/DialogWindow.axaml
Dialog window UI"]
G["Views/HuePickerWindow.axaml(.cs)
Hue selection UI"]
H["Misc/StringToResourceConverter.cs
Resource lookup converter"]
I["Misc/HueEntryToRectanglesValueConverter.cs
Hue visualization"]
end
B --> A
A --> C
A --> D
E --> A
F --> A
G --> A
E --> H
G --> I
```
**Diagram sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
- [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)
- [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml)
- [HuePickerWindow.axaml](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml)
- [HuePickerWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [HueEntryToRectanglesValueConverter.cs](file://ClassicAssist.Avalonia/Misc/HueEntryToRectanglesValueConverter.cs)
**Section sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
## Core Components
- Application resource orchestration: centralizes theme resources and provides a single place to switch themes at startup or runtime.
- Icon system: centralized icon definitions consumed by buttons, toolbars, and menus.
- Control-level themes: reusable control templates and styles encapsulated per control.
- Hue selection UI: interactive picker to choose hues and propagate changes dynamically.
- Converters: bridge between data values and visual properties (e.g., string-to-resource, hue-to-rectangles).
Key responsibilities:
- Resource loading order and precedence
- Dynamic theme switching without restart
- Consistent typography and spacing tokens
- Cross-platform rendering parity
**Section sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml)
- [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml)
- [HuePickerWindow.axaml](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml)
- [HuePickerWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [HueEntryToRectanglesValueConverter.cs](file://ClassicAssist.Avalonia/Misc/HueEntryToRectanglesValueConverter.cs)
## Architecture Overview
At runtime, Avalonia merges resource dictionaries from multiple sources. The application-level file defines base resources and theme variants. Individual windows and controls reference these resources via keys. When a theme is switched, the active resource dictionary is replaced or updated, causing immediate re-render with new colors, fonts, and icons.
```mermaid
sequenceDiagram
participant User as "User"
participant App as "App.axaml"
participant View as "View (XAML)"
participant Res as "Resources (Colors/Icons/Fonts)"
participant Theming as "Theme Switcher"
User->>Theming : "Select theme / change hue"
Theming->>App : "Update resource dictionary"
App-->>Res : "Re-resolve keys"
App-->>View : "Apply new styles"
View-->>User : "Updated appearance"
```
**Diagram sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml)
- [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml)
## Detailed Component Analysis
### Application-Level Styling and Resource Management
- Centralizes theme resources and sets up resource merging order.
- Provides a mechanism to swap theme dictionaries at runtime.
- Ensures consistent fallbacks when a key is missing.
Best practices:
- Keep base tokens (colors, brushes, fonts) in a common dictionary.
- Define theme-specific overrides in separate dictionaries.
- Use explicit keys for all consumable resources.
**Section sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
### Icons System and Asset Management
- Icons are defined centrally and referenced by name across the UI.
- Using a single source simplifies replacement and theming.
- Prefer vector-friendly formats where possible for crisp scaling.
Guidelines:
- Group icons by category in the icon dictionary.
- Provide light/dark variants via keyed resources if needed.
- Avoid hardcoding paths; use resource keys.
**Section sources**
- [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml)
### Control-Level Themes
- Control templates and styles are isolated per control to improve maintainability.
- Styles should be composable and override only what is necessary.
- Use named resources for colors and sizes to enable theme swapping.
Example focus:
- GroupBox themed template demonstrates how to encapsulate control visuals.
**Section sources**
- [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml)
### Hue Selection and Dynamic Color Updates
- HuePickerWindow provides an interactive way to select hues.
- The selected hue is propagated to resources and reflected immediately.
- HueEntryToRectanglesValueConverter helps visualize available hues.
Flow:
- User selects a hue.
- ViewModel updates the active hue value.
- Resources bound to the hue update.
- All views refresh with the new color.
```mermaid
flowchart TD
Start(["Open Hue Picker"]) --> Select["Pick a hue"]
Select --> UpdateVM["Update ViewModel property"]
UpdateVM --> Notify["Notify bindings"]
Notify --> UpdateRes["Update resource value"]
UpdateRes --> Refresh["Views re-render"]
Refresh --> End(["New hue applied"])
```
**Diagram sources**
- [HuePickerWindow.axaml](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml)
- [HuePickerWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml.cs)
- [HueEntryToRectanglesValueConverter.cs](file://ClassicAssist.Avalonia/Misc/HueEntryToRectanglesValueConverter.cs)
**Section sources**
- [HuePickerWindow.axaml](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml)
- [HuePickerWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml.cs)
- [HueEntryToRectanglesValueConverter.cs](file://ClassicAssist.Avalonia/Misc/HueEntryToRectanglesValueConverter.cs)
### Typography and Font Configuration
- Fonts are loaded once at the application level and referenced by name.
- Use semantic font families (e.g., primary, monospace) to simplify theming.
- Ensure fallback fonts are specified for cross-platform compatibility.
Recommendations:
- Centralize font family names in resources.
- Provide size tokens for headings, body text, captions.
- Test on Windows, Linux, and macOS due to font availability differences.
**Section sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
### Layout Customization and Responsive Design
- Window sizing and control spacing should rely on margins, paddings, and grid/star sizing rather than fixed pixel values.
- Use Avalonia’s built-in responsive features (e.g., VisualStateManager or adaptive layouts) where appropriate.
- Dialog windows demonstrate standard sizing and padding conventions.
Practical tips:
- Prefer relative units and flexible panels.
- Define spacing tokens for consistent gaps.
- Validate minimum window sizes for usability.
**Section sources**
- [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml)
- [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml)
### Resource Lookup Converter
- StringToResourceConverter enables dynamic resource resolution by key at runtime.
- Useful for localized strings or theme-driven content.
Usage pattern:
- Bind a string key to a property using the converter.
- Ensure the key exists in the current resource scope.
**Section sources**
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
### UI Thread Integration
- AvaloniaUIInvoker abstracts UI thread dispatching for background tasks updating appearance.
- Ensures safe updates to resources and controls from non-UI threads.
**Section sources**
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
## Dependency Analysis
The following diagram shows how core theming components depend on each other:
```mermaid
graph LR
Program["Program.cs"] --> App["App.axaml"]
App --> Icons["Assets/Icons.xaml"]
App --> CtrlTheme["Controls/GroupBox.Theme.xaml"]
MainWindow["Views/MainWindow.axaml"] --> App
DialogWindow["Views/DialogWindow.axaml"] --> App
HuePicker["Views/HuePickerWindow.axaml(.cs)"] --> App
HuePicker --> HueConv["Misc/HueEntryToRectanglesValueConverter.cs"]
MainWindow --> StrRes["Misc/StringToResourceConverter.cs"]
HuePicker --> StrRes
```
**Diagram sources**
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [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)
- [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml)
- [HuePickerWindow.axaml](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml)
- [HuePickerWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml.cs)
- [HueEntryToRectanglesValueConverter.cs](file://ClassicAssist.Avalonia/Misc/HueEntryToRectanglesValueConverter.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
**Section sources**
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
## Performance Considerations
- Minimize resource dictionary churn: batch theme changes instead of frequent small updates.
- Prefer static resources for immutable tokens; use dynamic resources only when necessary.
- Cache frequently used converted values (e.g., hue rectangles) to avoid repeated computation.
- Avoid heavy operations on the UI thread during theme switches; use the UI invoker to marshal work.
[No sources needed since this section provides general guidance]
## Troubleshooting Guide
Common issues and resolutions:
- Missing resource key errors: verify keys exist in the active resource dictionary and that resource loading order includes your theme.
- Blank icons after theme switch: ensure icon resources are included in the merged dictionaries and not overridden unintentionally.
- Incorrect font rendering on some platforms: provide fallback font families and test on target OSes.
- Non-responsive UI after resizing: review layout containers and avoid fixed sizes; use flexible sizing and constraints.
- Slow theme switching: reduce number of dynamic resources and defer expensive conversions off the UI thread.
**Section sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml)
- [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml)
- [HuePickerWindow.axaml](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml)
- [HuePickerWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml)
- [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml)
## Conclusion
ClassicAssist.Avalonia’s theming system leverages Avalonia’s resource dictionaries and converters to deliver a flexible, extensible appearance framework. By centralizing resources, isolating control-level themes, and providing interactive hue selection, it supports both simple and advanced customization scenarios. Following the guidelines here will help you create consistent, performant, and cross-platform themes while maintaining a clean separation between look and behavior.
[No sources needed since this section summarizes without analyzing specific files]
## Appendices
### Creating a Custom Theme
Steps:
- Create a new resource dictionary with your color tokens, brushes, and typography settings.
- Merge your dictionary into the application resources, ensuring correct precedence.
- Reference your resources by key throughout views and controls.
- Provide a theme switcher method to swap dictionaries at runtime.
Validation checklist:
- Verify all referenced keys exist.
- Test on Windows, Linux, and macOS.
- Confirm icons and fonts render correctly.
**Section sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml)
### Extending Existing Styles
Approach:
- Target existing control styles by type and set only the properties you need to override.
- Use named resources for colors and sizes to keep overrides minimal.
- For complex changes, copy the control template and adjust as needed.
**Section sources**
- [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml)
### Cross-Platform Appearance Consistency
Guidelines:
- Use semantic resource keys instead of hardcoded values.
- Provide fallback fonts and scalable icons.
- Avoid platform-specific assumptions in XAML; handle platform differences in code-behind if necessary.
**Section sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml)