Skip to content

Latest commit

History

456 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ktsu.ThemeProvider

A semantic color theming library for .NET applications with 38 themes, intelligent color mapping, and framework integration.

LicenseNuGet VersionNuGet VersionNuGet DownloadsGitHub commit activityGitHub contributorsGitHub Actions Workflow Status

Introduction

ktsu.ThemeProvider is a comprehensive theming system that uses semantic color specifications rather than arbitrary color names. Instead of hardcoding colors like "blue" or "red", you define colors by their purpose (Primary, Error, Warning) and priority level, and the library generates consistent, accessible color palettes. It includes 38 carefully crafted themes from popular color schemes and provides built-in Dear ImGui integration with an extensible architecture for other UI frameworks.

Features

  • Semantic Color System: Define colors by purpose (Primary, Error, Warning, Neutral) and priority level rather than specific hues, enabling consistent theming across any UI framework
  • 38 Built-in Themes: Includes Catppuccin, Tokyo Night, Gruvbox, Everforest, Nightfox, Kanagawa, PaperColor, Nord, Dracula, VSCode, One Dark, Monokai, and Nightfly theme families
  • Centralized Theme Registry: Discover, filter, and instantiate themes by name, family, or light/dark classification with rich metadata
  • Dear ImGui Integration: Companion package ktsu.ThemeProvider.ImGui provides complete ImGui color palette mapping via ImGuiPaletteMapper
  • Perceptual Color Science: Uses Oklab perceptual color space for uniform color interpolation, extrapolation, and lightness-based priority mapping
  • WCAG Accessibility: Built-in contrast ratio calculations, accessibility level checking (AA/AAA), and automatic color adjustment to meet WCAG standards
  • Extensible Framework Mappers: Implement IPaletteMapper<TColorKey, TColorValue> to integrate with any UI framework
  • Priority-Based Color Hierarchy: Seven priority levels (VeryLow to VeryHigh) automatically mapped to appropriate lightness values, with theme-aware ordering for dark and light themes
  • Multi-Target Support: Targets .NET 5.0 through 10.0, plus .NET Standard 2.0 and 2.1

Installation

Package Manager Console

Install-Package ktsu.ThemeProvider

.NET CLI

dotnet add package ktsu.ThemeProvider

Package Reference

<PackageReferenceInclude="ktsu.ThemeProvider"Version="x.y.z" />

For Dear ImGui integration, also install:

dotnet add package ktsu.ThemeProvider.ImGui

Usage Examples

Basic Example

usingktsu.ThemeProvider;usingstaticktsu.ThemeProvider.ThemeRegistry;// Create a theme directlyvartheme=newThemes.Catppuccin.Mocha();// Or find and create via the registryThemeInfo?themeInfo=FindTheme("Catppuccin Mocha");ISemanticTheme?registryTheme=themeInfo?.CreateInstance();// Map semantic color requests to actual colorsvarrequests=new[]{newSemanticColorRequest(SemanticMeaning.Primary,Priority.Medium),newSemanticColorRequest(SemanticMeaning.Error,Priority.High),newSemanticColorRequest(SemanticMeaning.Neutral,Priority.VeryLow),};IReadOnlyDictionary<SemanticColorRequest,Color>colors=SemanticColorMapper.MapColors(requests,theme);

Theme Discovery with the Registry

usingktsu.ThemeProvider;usingstaticktsu.ThemeProvider.ThemeRegistry;// Browse all themesIReadOnlyList<ThemeInfo>allThemes=AllThemes;IReadOnlyList<ThemeInfo>darkThemes=DarkThemes;IReadOnlyList<ThemeInfo>lightThemes=LightThemes;// Browse by familyIReadOnlyList<string>families=Families;IReadOnlyList<ThemeInfo>catppuccinThemes=GetThemesInFamily("Catppuccin");// Find a specific theme by name (case-insensitive)ThemeInfo?themeInfo=FindTheme("Tokyo Night Storm");ISemanticTheme?theme=themeInfo?.CreateInstance();// Create all theme instances at onceIReadOnlyList<ISemanticTheme>allInstances=CreateAllThemeInstances();IReadOnlyList<ISemanticTheme>gruvboxInstances=CreateThemeInstancesInFamily("Gruvbox");

Complete Palette Generation

usingktsu.ThemeProvider;usingktsu.Semantics.Color;vartheme=newThemes.Nord.Nord();// Generate the complete palette (all meaning + priority combinations)IReadOnlyDictionary<SemanticColorRequest,Color>completePalette=SemanticColorMapper.MakeCompletePalette(theme);// Access any color from the palettevarprimaryMedium=completePalette[newSemanticColorRequest(SemanticMeaning.Primary,Priority.Medium)];stringhex=primaryMedium.ToHex();

Dear ImGui Integration

usingktsu.ThemeProvider;usingktsu.ThemeProvider.ImGui;usingHexa.NET.ImGui;// Create theme and mappervartheme=newThemes.Catppuccin.Mocha();varmapper=newImGuiPaletteMapper();// Get complete ImGui color paletteIReadOnlyDictionary<ImGuiCol,Vector4>imguiColors=mapper.MapTheme(theme);// Apply to ImGui stylevarstyle=ImGui.GetStyle();foreach((ImGuiColcolorKey,Vector4colorValue)inimguiColors){style.Colors[(int)colorKey]=colorValue;}

Accessibility Checking

usingktsu.ThemeProvider;usingktsu.Semantics.Color;Colorforeground=Color.FromHex("#FFFFFF");Colorbackground=Color.FromHex("#1E1E2E");// Calculate contrast ratio (1.0 .. 21.0)doublecontrastRatio=foreground.ContrastRatio(background);// Check WCAG complianceAccessibilityLevellevel=foreground.AccessibilityLevelAgainst(background,largeText:false);// Adjust a color to meet accessibility requirementsColoradjusted=foreground.AdjustForContrast(background,AccessibilityLevel.AA);// Create perceptually uniform gradientsIReadOnlyList<Color>gradient=foreground.Gradient(background,steps:10);

Advanced Usage

Creating Custom Framework Mappers

Implement IPaletteMapper<TColorKey, TColorValue> to integrate with any UI framework:

usingktsu.ThemeProvider;publicclassMyFrameworkMapper:IPaletteMapper<MyColorEnum,MyColorType>{publicstringFrameworkName=>"My UI Framework";publicIReadOnlyDictionary<MyColorEnum,MyColorType>MapTheme(ISemanticThemetheme){varrequests=newDictionary<MyColorEnum,SemanticColorRequest>{{MyColorEnum.Button,new(SemanticMeaning.Primary,Priority.Medium)},{MyColorEnum.Background,new(SemanticMeaning.Neutral,Priority.VeryLow)},{MyColorEnum.ErrorText,new(SemanticMeaning.Error,Priority.High)},};varpalette=SemanticColorMapper.MapColors(requests.Values,theme);varresult=newDictionary<MyColorEnum,MyColorType>();foreach(varkvpinrequests){if(palette.TryGetValue(kvp.Value,outvarcolor)){result[kvp.Key]=ConvertToMyColor(color.RgbValue);}}returnresult;}}

Creating Custom Themes

Declare your palette as a SemanticPalette and let it build the mapping. Colors are written as hex strings, the notation upstream color schemes publish, so a theme can be diffed against its source:

usingktsu.ThemeProvider;usingktsu.Semantics.Color;usingSystem.Collections.ObjectModel;publicclassMyCustomTheme:ISemanticTheme{privatestaticreadonlySemanticPalettePalette=new(){// Neutrals are a ramp; the mapper interpolates between them across priority levels.Neutrals=["#C0CAF5","#1A1B26"],Primary="#7AA2F7",Alternate="#BB9AF7",Success="#9ECE6A",CallToAction="#9ECE6A",Information="#7DCFFF",Caution="#FF9E64",Warning="#E0AF68",Error="#F7768E",Failure="#F7768E",Debug="#BB9AF7",};publicDictionary<SemanticMeaning,Collection<Color>>SemanticMapping=>Palette.ToSemanticMapping();publicboolIsDarkTheme=>true;}

SemanticMapping is the only contract, so a theme with unusual needs (more than two neutrals, or a meaning driven by something other than a fixed hex) can still build the dictionary itself.

API Reference

SemanticMeaning (enum)

Defines semantic color purposes.

ValueDescription
NeutralBackgrounds, borders, inactive elements
PrimaryMain brand/accent colors
AlternateSecondary accent, binary choice emphasis
SuccessSuccessful operations, confirmations
CallToActionImportant buttons and highlights demanding attention
InformationInformational content, help text
CautionCautionary content needing attention
WarningWarning states, potentially problematic
ErrorError states, incorrect conditions
FailureFailed operations (distinct from error)
DebugDebug/development information

Priority (enum)

Controls color intensity and lightness within a semantic meaning.

ValueDescription
VeryLowLowest intensity (backgrounds in dark themes, lightest in light themes)
LowLow intensity
MediumLowBelow-medium intensity
MediumDefault intensity level
MediumHighAbove-medium intensity
HighHigh intensity
VeryHighHighest intensity (foreground text in dark themes, darkest in light themes)

SemanticColorRequest

A readonly record struct combining a SemanticMeaning and Priority to specify a color.

PropertyTypeDescription
MeaningSemanticMeaningThe semantic purpose of the color
PriorityPriorityThe intensity/lightness level

SemanticColorMapper

Static class that maps semantic color requests to actual colors.

Methods

NameReturn TypeDescription
MapColors(requests, theme)IReadOnlyDictionary<SemanticColorRequest, Color>Maps a collection of requests to colors using the theme
MakeCompletePalette(theme)IReadOnlyDictionary<SemanticColorRequest, Color>Generates all possible meaning+priority combinations for a theme

ThemeRegistry

Static class providing centralized theme discovery and management.

Properties

NameTypeDescription
AllThemesIReadOnlyList<ThemeInfo>All 38 registered themes with metadata
DarkThemesIReadOnlyList<ThemeInfo>All dark themes
LightThemesIReadOnlyList<ThemeInfo>All light themes
FamiliesIReadOnlyList<string>All theme family names
ThemesByFamilyIReadOnlyDictionary<string, IReadOnlyList<ThemeInfo>>Themes grouped by family

Methods

NameReturn TypeDescription
FindTheme(name)ThemeInfo?Finds a theme by name (case-insensitive)
GetThemesInFamily(family)IReadOnlyList<ThemeInfo>Gets all themes in a family
CreateAllThemeInstances()IReadOnlyList<ISemanticTheme>Creates instances of all themes
CreateThemeInstancesInFamily(family)IReadOnlyList<ISemanticTheme>Creates instances of themes in a family

Color types (ktsu.Semantics.Color)

Colors are represented by the Color type from the ktsu.Semantics.Color package (linear RGB + alpha, gamma-correct). It is the currency type for themes (ISemanticTheme.SemanticMapping) and SemanticColorMapper.

Common members:

MemberDescription
Color.FromHex(hex)Creates a color from an sRGB hex string (proper sRGB→linear decode)
ToHex() / ToBytes()Converts back to an sRGB hex string / 8-bit channels
ToSrgbVector4()sRGB-encoded Vector4 for UI frameworks (e.g. ImGui)
ToOklab() / ToOklch()Perceptual (Oklab / polar LCh) representations
ContrastRatio(other)WCAG contrast ratio (1:1 .. 21:1)
AccessibilityLevelAgainst(bg, largeText)WCAG AA/AAA compliance (returns AccessibilityLevel)
AdjustForContrast(bg, level, largeText)Adjusts lightness to meet a WCAG level
DistanceTo(other)Perceptual (Oklab) distance
MixOklab(other, t) / Gradient(to, steps)Perceptual blend / uniform gradient

Migration note (v2.0): ThemeProvider's in-house RgbColor, SRgbColor, OklabColor, PerceptualColor, and ColorMath types were removed in favour of ktsu.Semantics.Color. This also fixed a long-standing sRGB-as-linear gamma bug — base theme colors render identically, but the semantic mapper's derived colors and accessibility numbers are now computed correctly.

IPaletteMapper<TColorKey, TColorValue>

Interface for mapping semantic themes to framework-specific color palettes.

Properties

NameTypeDescription
FrameworkNamestringThe name of the target UI framework

Methods

NameReturn TypeDescription
MapTheme(theme)IReadOnlyDictionary<TColorKey, TColorValue>Maps a theme to a framework-specific palette

Available Themes

FamilyVariantsDescription
CatppuccinLatte, Frappe, Macchiato, MochaWarm pastel themes with excellent readability
Tokyo NightNight, Storm, DayClean themes inspired by Tokyo's neon nights
GruvboxDark, Dark Hard, Dark Soft, Light, Light Hard, Light SoftRetro groove colors with warm backgrounds
EverforestDark, Dark Hard, Dark Soft, Light, Light Hard, Light SoftGreen forest colors for comfortable viewing
NightfoxNightfox, Dayfox, Duskfox, Nordfox, Terafox, Carbonfox, DawnfoxFox-inspired vibrant themes
KanagawaWave, Dragon, LotusJapanese-inspired themes
PaperColorLight, DarkMaterial Design inspired themes
VSCodeDark, LightMicrosoft VSCode default themes
Nord-Arctic-inspired theme with cool blue tones
Dracula-Gothic theme with purple and pink accents
One Dark-Atom's iconic One Dark theme
Monokai-Classic Monokai with vibrant colors
Nightfly-Dark blue theme inspired by night flying

Contributing

Contributions are welcome! Feel free to open issues or submit pull requests.

License

This project is licensed under the MIT License. See the LICENSE.md file for details.

About

A semantic color theming library for .NET applications that provides 44+ beautiful themes with intelligent color mapping, framework integration, and accessibility-first design.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages