Table of Contents

DBTools.Themes

The DBTools.Themes project provides a unified dark theme system for all DBTools WPF applications. It establishes design tokens, brush definitions, and control styles that ensure visual consistency across the application while avoiding conflicts with Revit's host environment.

Overview

DBTools.Themes solves several key challenges:

  1. Host Isolation: Revit's UI can interfere with WPF resource dictionaries. This project uses vendored, renamed libraries (e.g., DBTools.HandyControl instead of HandyControl) to prevent conflicts with pyRevit or other add-ins.

  2. Consistent Branding: Implements the DBTools brand colors (deep blue #1946B9 and golden yellow #FEC425) across all UI controls.

  3. WCAG Accessibility: Text colors are designed to meet WCAG AA contrast requirements (min 4.5:1 ratio on dark backgrounds).

  4. Template Boundary Crossing: The BrushKeys system using ComponentResourceKey allows brushes to propagate correctly across DataTemplate and ControlTemplate boundaries.

Source: src/DBTools.Themes/DBTools.Themes.csproj:1-73

Project Structure

DBTools.Themes/
├── DBTools.Themes.csproj        # Project configuration
├── BrushKeys.cs                 # ComponentResourceKey definitions
├── Assets/
│   └── (linked) db_tools_icon.png  # Application icon (source: src/Assets/Icons/db_tools_icon.png)
└── Themes/
    ├── App.Theme.xaml           # Root dictionary (entry point)
    ├── App.Tokens.xaml          # Design tokens (spacing, sizing)
    ├── App.Brushes.xaml         # Color/brush definitions
    ├── App.Converters.xaml      # Value converters
    ├── App.Controls.Base.xaml   # Base control styles
    ├── App.DataGrid.xaml        # DataGrid-specific styles
    ├── App.Menus.xaml           # Menu/ContextMenu styles
    ├── App.Components.xaml      # Higher-level component styles

Source: src/DBTools.Themes/DBTools.Themes.csproj:38-51

Key Files

App.Theme.xaml - Root Entry Point

The root resource dictionary that merges all theme components. This is what consuming projects reference.

<ResourceDictionary.MergedDictionaries>
    <!-- HandyControl Foundation -->
    <ResourceDictionary Source="pack://application:,,,/DBTools.HandyControl;component/Themes/SkinDark.xaml"/>
    <ResourceDictionary Source="pack://application:,,,/DBTools.HandyControl;component/Themes/Theme.xaml"/>

    <!-- DBTools Custom Themes -->
    <ResourceDictionary Source="App.Tokens.xaml" />
    <ResourceDictionary Source="App.Brushes.xaml" />
    <!-- ... additional dictionaries ... -->
</ResourceDictionary.MergedDictionaries>

Source: src/DBTools.Themes/Themes/App.Theme.xaml:1-22

BrushKeys.cs - ComponentResourceKey System

Defines strongly-typed keys for all theme brushes. This pattern enables brushes to work correctly inside DataTemplate and ControlTemplate boundaries where DynamicResource with string keys may fail.

public static class BrushKeys
{
    public static ComponentResourceKey Primary => new(typeof(BrushKeys), "Brush.Primary");
    public static ComponentResourceKey Secondary => new(typeof(BrushKeys), "Brush.Secondary");
    // ... 100+ additional keys
}

Usage in XAML:

<Border Background="{DynamicResource {x:Static theme:BrushKeys.Primary}}" />

Source: src/DBTools.Themes/BrushKeys.cs:1-140

Design Tokens

Design tokens provide consistent spacing, sizing, typography, and other visual constants.

Spacing Tokens

Token Value Usage
Spacing4 4px Tight spacing (icon margins)
Spacing8 8px Standard spacing
Spacing12 12px Medium spacing
Spacing16 16px Large spacing
Spacing32 32px Section spacing

Scalar variants (Spacing8.Value, etc.) are provided for properties that require Double instead of Thickness.

Source: src/DBTools.Themes/Themes/App.Tokens.xaml:5-18

Padding Tokens

Token Value Usage
Pad4 4px uniform Compact padding
Pad8 8px uniform Standard padding
Pad16 16px uniform Large padding
Pad8x4 8px H, 4px V Button padding
Card.Padding 16px H, 12px V Card content

Source: src/DBTools.Themes/Themes/App.Tokens.xaml:24-56

Gap Tokens

Directional margins for layout:

Token Value Description
TGap8 Top 8px Top margin
BGap8 Bottom 8px Bottom margin
LGap8 Left 8px Left margin
RGap8 Right 8px Right margin
VGap8 Top/Bottom 8px Vertical margin
HGap8 Left 8px Horizontal gap

Source: src/DBTools.Themes/Themes/App.Tokens.xaml:30-64

Typography Tokens

Token Size Usage
FontSize.Caption 11px Captions, timestamps
FontSize.Body.Small 12px Secondary text
FontSize.Body 13px Default body text
FontSize.Subtitle 14px Subtitles
FontSize.Title 16px Section titles
FontSize.Header 20px Page headers

Source: src/DBTools.Themes/Themes/App.Tokens.xaml:66-72

Corner Radius Tokens

Token Value Usage
Radius4 4px Buttons, inputs
Radius6 6px Cards, chips
Radius8 8px Dialogs, overlays
Radius12 12px Large surfaces

Source: src/DBTools.Themes/Themes/App.Tokens.xaml:43-46

Control Size Tokens

Token Value Usage
MinHeight.Control 32px Minimum control height
Size.CheckBox.Box 18px Checkbox dimensions
Size.ToggleTrack.Width 44px Toggle switch track
Size.DataGridRow.MinHeight 32px Grid row height
Size.ScrollBar.Width 10px Scrollbar width

Source: src/DBTools.Themes/Themes/App.Tokens.xaml:98-114

Color System (App.Brushes.xaml)

The color system is built around the DBTools brand colors with carefully designed semantic roles.

Brand Colors

Key Color Description
Primary #1946B9 Deep blue - primary actions
PrimaryLight #3D6AD4 Hover state
PrimaryDark #0D2E7A Pressed state
Secondary #FEC425 Golden yellow - accents
SecondaryLight #FFD54F Hover state
SecondaryDark #C79100 Pressed state

Source: src/DBTools.Themes/Themes/App.Brushes.xaml:14-19

Surface Colors

Neutral dark palette with reduced blue tint:

Key Color Description
Paper #181820 Window background
Surface #222228 Card/panel background
SurfaceAlt #1C1C22 Alternate surface
SurfaceHover #2A2A32 Hover state
CardSurface #1E1E24 Card background
CardSurfaceElevated #282830 Elevated cards

Source: src/DBTools.Themes/Themes/App.Brushes.xaml:24-30

Text Colors (WCAG Compliant)

Key Color Contrast Description
Body / Text #E6E6E6 ~12:1 Primary text
BodyLight / TextSecondary #BDBDBD ~9:1 Secondary text
TextMuted / Muted #999999 ~7:1 Muted text
OnAccent #FFFFFF - Text on colored bg
OnSecondary #181820 - Text on yellow

Source: src/DBTools.Themes/Themes/App.Brushes.xaml:35-44

Selection & Highlight Colors

Alpha transparency reference: #33 = 20%, #44 = 27%, #55 = 33%, #66 = 40%, #99 = 60%

Key Color Description
Selection #441946B9 (27%) Standard selection
SelectionStrong #661946B9 (40%) Strong selection
SelectionGold #33FEC425 (20%) Row highlighting
SelectionGoldStrong #55FEC425 (33%) Strong gold
Hover #33FEC425 (20%) Hover state

Source: src/DBTools.Themes/Themes/App.Brushes.xaml:59-78

Status Colors

Key Color Description
Success #4CAF50 Success state
Warning #FFA000 Warning state
Error #CF6679 Error state
Info #1946B9 Informational

Each status color has Light and Background variants for subtle backgrounds.

Source: src/DBTools.Themes/Themes/App.Brushes.xaml:84-95

Specialized Brush Categories

The brush system includes specialized categories for:

  • DataGrid: Header, row, cell, selection colors
  • Input Controls: Background, border, focus states
  • Buttons: Primary, secondary, accent, danger variants
  • Checkbox/Toggle: Box, checked, indeterminate states
  • Tabs: Background, indicator, hover states
  • ScrollBar/Slider: Track, thumb, hover/pressed states
  • VTC Diff View: Add/remove/missing background colors

Source: src/DBTools.Themes/Themes/App.Brushes.xaml:100-232

BrushKeys System

Why ComponentResourceKey?

WPF has a limitation where DynamicResource with string keys doesn't always resolve correctly inside DataTemplate or ControlTemplate boundaries. ComponentResourceKey solves this by creating type-safe keys that the resource system can resolve across template boundaries.

Key Categories

The BrushKeys class defines 100+ keys organized into categories:

Category Example Keys Count
Brand Primary, Secondary, PrimaryLight 6
Surface Paper, Surface, CardSurface 7
Text Body, Text, TextMuted 10
Border Border, Divider, BorderSubtle 4
Selection Selection, SelectionGold, Hover 12
Status Success, Warning, Error, Info 12
DataGrid DataGridHeader, DataGridRow, etc. 14
Input InputBackground, InputBorder 5
Button ButtonPrimary, ButtonDanger 10
Checkbox CheckBox, CheckChecked 6
Toggle ToggleTrackOn, ToggleThumb 7
Tab TabBackground, TabIndicator 5
ScrollBar ScrollBarTrack, ScrollBarThumb 4
Slider SliderTrack, SliderThumb 5
Progress ProgressTrack, ProgressFill 3
Toolbar ToolbarChipBackground, etc. 6
VTC Diff VtcDiffAddBackground, etc. 4

Source: src/DBTools.Themes/BrushKeys.cs:11-139

Usage Pattern

In XAML:

xmlns:theme="clr-namespace:DBTools.Themes;assembly=DBTools.Themes"

<Border Background="{DynamicResource {x:Static theme:BrushKeys.CardSurface}}"
        BorderBrush="{DynamicResource {x:Static theme:BrushKeys.CardBorder}}" />

In Code:

var brush = (Brush)FindResource(BrushKeys.Primary);

Control Styles

Window Styles

The theme provides implicit styles for DbtWindowBase and DbtRibbonWindowBase:

  • Sets the DBTools icon
  • Applies Paper background and Body foreground
  • Includes progress overlay support via ProgressOverlayService

Source: src/DBTools.Themes/Themes/App.Controls.Base.xaml:13-55

Base Control Styles

TextBlock

  • Foreground: Body brush
  • TextWrapping: Wrap
  • TextTrimming: CharacterEllipsis

Button

  • MinWidth: 88px, MinHeight: 36px
  • Hover: SecondaryHover background, Secondary border
  • Pressed: PrimaryHover background, Primary border

TextBox

  • Background: InputBackground
  • Border: InputBorder (hover: Secondary, focus: FocusBorder)
  • Validation error: Red border with tooltip

ComboBox

  • Custom dropdown template with dark popup background
  • Drop shadow effect on dropdown
  • Proper dark theme item highlighting

CheckBox / RadioButton

  • Custom templates with theme-consistent colors
  • Checked: CheckChecked background
  • Indeterminate: CheckIndeterminate fill (yellow)

Source: src/DBTools.Themes/Themes/App.Controls.Base.xaml:61-449

DataGrid Styles

Comprehensive DataGrid theming with:

Row Features:

  • Yellow accent stripe on left edge
  • Gold hover highlighting (DataGridRowHover)
  • Blue selection with yellow accent (DataGridRowSelected)
  • Keyboard focus indicator (DataGridRowFocus)

Cell Features:

  • Focus state with primary border
  • Edit mode with secondary border
  • Conflict highlighting support

Column Header:

  • Hover state
  • Sort direction indicators (yellow arrows)
  • Resizable column grippers

Source: src/DBTools.Themes/Themes/App.DataGrid.xaml:1-476

Component Styles (App.Components.xaml)

Higher-level UI component styles:

Style Key Target Description
ToolBar ToolBar Dark themed toolbar
StatusBar StatusBar Dark themed status bar
ToolbarChip ToggleButton Pill-shaped filter buttons
OverlayCard Border Modal dialog container
Card Border Standard card surface
Card.Elevated Border Card with drop shadow
Dbt.Section GroupBox Section with accent stripe
Dbt.Callout Border Info callout box
WarningBar Border Warning message container

Typography Styles:

  • HeaderText, SubtitleText, BodyText, DescriptionText, CaptionText

Source: src/DBTools.Themes/Themes/App.Components.xaml:1-414

Custom templates for proper dark theme rendering in Revit:

  • ContextMenu: Dark background, rounded corners, drop shadow
  • MenuItem: Hover highlighting, keyboard shortcut display
  • MenuSeparator: Subtle divider

Source: src/DBTools.Themes/Themes/App.Menus.xaml:1-136

Vendored Library Integration

Why Vendored Libraries?

Revit hosts multiple add-ins that may use conflicting versions of UI libraries like HandyControl. By vendoring and renaming these libraries, DBTools avoids:

  1. Assembly version conflicts
  2. Resource dictionary collisions
  3. pyRevit theme interference

Vendored Assemblies

Original Vendored Purpose
HandyControl DBTools.HandyControl Control library foundation
<Reference Include="DBTools.HandyControl">
  <HintPath>$(DBT_VendorArtifactsRoot)handycontrol\$(TargetFramework)\DBTools.HandyControl.dll</HintPath>
</Reference>

Source: src/DBTools.Themes/DBTools.Themes.csproj:55-71

Build Configuration

Target Frameworks

The project multi-targets:

  • net48 (Revit 2024 and earlier)
  • net8.0-windows (Revit 2025+)

XAML Compilation

Some XAML files are kept as raw resources (not compiled to BAML) to avoid requiring a project reference to DBTools.Core:

<Page Remove="Themes\App.Converters.xaml" />
<Resource Include="Themes\App.Converters.xaml" />

Source: src/DBTools.Themes/DBTools.Themes.csproj:38-46

Dependency Rules

Critical: DBTools.Themes must NOT reference DBTools.Core to avoid circular dependencies. Theme dictionaries that need Core types are defined in Core and merged via pack URIs.

Source: src/DBTools.Themes/DBTools.Themes.csproj:31-34

How to Extend

Adding New Brushes

  1. Add the ComponentResourceKey to BrushKeys.cs:

    public static ComponentResourceKey MyNewBrush => new(typeof(BrushKeys), "Brush.MyNew");
    
  2. Define the brush in App.Brushes.xaml:

    <SolidColorBrush x:Key="{x:Static theme:BrushKeys.MyNewBrush}" Color="#FF123456" />
    

Adding New Tokens

Add to App.Tokens.xaml following existing patterns:

<sys:Double x:Key="Size.MyNew">24</sys:Double>
<Thickness x:Key="Pad.MyNew">8,4</Thickness>

Creating New Control Styles

  1. For base controls, add to App.Controls.Base.xaml
  2. For higher-level components, add to App.Components.xaml
  3. Use DynamicResource with BrushKeys for all colors
  4. Use token resources for spacing/sizing

Adding Converters

  1. Implement converter in DBTools.Core.UI.Converters
  2. Add resource entry in App.Converters.xaml:
    <conv:MyConverter x:Key="Converter.MyConverter" />
    

Cross-References

Value Converters

Available converters (defined in App.Converters.xaml):

Key Type Description
Converter.BoolToVisibility BooleanToVisibilityConverter Standard bool-to-visibility
Converter.InverseBoolToVisibility InverseBooleanToVisibilityConverter Inverted visibility
Converter.NullToVisibility NullToVisibilityConverter Collapsed when not null
Converter.NullToInverseVisibility NullToInverseVisibilityConverter Collapsed when null
Converter.RowKindToVisibility RowKindToVisibilityConverter DataGrid row type filtering

Source: src/DBTools.Themes/Themes/App.Converters.xaml:1-12