Files
ClassicAssist.Avalonia/.qoder/repowiki/knowledge/en/WPF_Avalonia XAML Theme System with Design Tokens/WPF_Avalonia XAML Theme System with Design Tokens.md
T
Beyhan Oğur d5f52cc3d3 first commit
2026-09-03 04:45:36 +03:00

4.0 KiB

kind, name, category, scope, source_files
kind name category scope source_files
frontend_style WPF/Avalonia XAML Theme System with Design Tokens frontend_style
**
ClassicAssist/Resources/DarkTheme.xaml
ClassicAssist/Resources/Colours.xaml
ClassicAssist/Resources/ResourceDictionary.xaml
ClassicAssist.Avalonia/App.axaml
ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml

ClassicAssist uses a dual-frontend architecture (WPF + Avalonia) that shares a consistent dark-themed visual style through XAML Resource Dictionaries and design tokens. The styling system is built around centralized color palettes, component-level control templates, and theme-aware brushes rather than CSS or SCSS.

System overview

  • WPF frontend (ClassicAssist/) defines the primary theme in Resources/DarkTheme.xaml, which merges Colours.xaml for design tokens and provides full control templates for TreeView, ListBox, ListView, TabControl, Button, ComboBox, CheckBox, ScrollBar, GridView, TextBlock, and custom controls like EditTextBlock. A thin ResourceDictionary.xaml aggregates the theme for consumption by views.
  • Avalonia frontend (ClassicAssist.Avalonia/) mirrors the same dark aesthetic via App.axaml's RequestedThemeVariant="Dark", inline application resources, and selector-based styles. It includes AvaloniaEdit Simple theme, DataGrid Simple theme, and a custom GroupBox.Theme.xaml control template.
  • Both shells reference shared icons and assets from their respective Assets/ / Resources/ folders (PNGs, fonts, syntax highlighting files).

Design tokens

  • Colours.xaml declares a palette of BackgroundColor1..6, ForegroundColor1..5, SelectionColor1/2 (with emphasized variants), and RedColor, then exposes them as SolidColorBrush keys suffixed with Brush. Semantic brushes such as ThemeBackgroundBrush, ThemeForegroundBrush, ThemeBorderBrush, ThemeInnerControlBackgroundBrush, ThemeTabBackgroundBrush, and IconForegroundBrush are defined at the bottom of the file and consumed by all control templates.
  • Token naming follows a strict <Component><State>Brush convention (e.g., ButtonHoverBackgroundBrush, ComboBoxNonEditableDisabledBorderBrush, TreeViewSelectecBackgroudBrush).

Architecture & conventions

  • Styles are organized per-component inside one large DarkTheme.xaml; there is no CSS-in-JS, Tailwind, or SCSS pipeline — zero .css/.scss/tailwind.config.* files exist in the repo.
  • Control templates override default WPF chrome (CheckBox, ComboBox, ScrollBar, TreeViewItem, etc.) to use the token brushes, ensuring every state (hover, pressed, disabled, selected, inactive selection) maps to a specific brush key.
  • Views bind UI elements to these tokens via {DynamicResource ...} so the entire palette can be swapped by replacing the merged dictionary.
  • Avalonia uses its own Styles/StyleSelector syntax in App.axaml and Controls/GroupBox.Theme.xaml, but reuses the same semantic color names (ThemeForegroundBrush, ThemeBorderMidBrush, etc.) so both frontends look identical.
  • Custom reusable controls live under UI/Controls (WPF) and Controls (Avalonia) and ship paired .xaml/.cs files; they consume the same token brushes rather than hard-coding colors.

Rules developers should follow

  • Never hard-code hex colors in views or control templates; always reference a named brush from Colours.xaml (or the Avalonia equivalent). Add new tokens to Colours.xaml before using them.
  • When adding a new state to a control template (hover, focus, disabled, selected), define the corresponding <Component><State>Brush token first.
  • Keep WPF and Avalonia control templates aligned: if you customize a control's look in one shell, mirror the change in the other so both frontends stay visually consistent.
  • Place new reusable visuals in the appropriate Controls/ folder and expose them as a single .xaml resource dictionary merged into the app's root resources.
  • Avoid CSS/SCSS entirely — this project has no web stack and no build step for preprocessors.