Skip to content

Alpaq92/Flags.Icons

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

82 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Flags.Icons

NuGet NuGet NuGet NuGet NuGet NuGet NuGet NuGet NuGet CI Release NuGet downloads (core, transitively included by every platform package) License: MIT

Flags.Icons demo

Flag icons from 5 upstream sources — Twemoji, Circle (HatScripts), Square (kapowaz), Lipis (lipis/flag-icons), FlagHub (Alpaq92 — maintained FlagKit fork) — packaged as drop-in controls for Avalonia, Eto.Forms, .NET MAUI, Aprillz.MewUI, Uno Platform, Windows Forms, WinUI 3 and WPF. Every SVG ships as an embedded resource in the core Flags.Icons package, reachable through a per-source strongly-typed enum (TwemojiFlag, CircleFlag, SquareFlag, LipisFlag, FlagHubFlag). No runtime download, no file-system access. Platform packages are thin wrappers that convert the embedded streams into the native image type for each UI stack.

Version notes

  • v3 brings back the FlagKit-style artwork that originally shipped in v1 — now sourced from Alpaq92/FlagHub, a maintained fork of the abandoned madebybowtie/FlagKit with open upstream PRs merged and packaging fixed. It joins the v2 line-up as a fifth source via the new FlagHubFlag enum / FlagHub="US" DP. Additive, non-breaking on top of v2 — existing Twemoji / Circle / Square / Lipis code keeps working unchanged. Still breaking vs v1: there is no FlagKind enum anywhere — use FlagHub="US" (or any of the other four sources) instead of the old Kind="USSVG".
  • v2 dropped the unmaintained FlagKit submodule (no flag refreshes since 2019, no newer subdivision codes) and replaced the single FlagKind enum with one typed enum per source. Migration from v1: swap <flag:FlagIcon Kind="USSVG"/> for <flag:FlagIcon Twemoji="US"/> (or Circle="US" / Square="US" / Lipis="US" / now FlagHub="US" — enum members are uppercase ISO codes regardless of how the upstream stores filenames). API surface details in the Usage section.

Bundled sources

Counts as of 2026-06-01 (latest monthly submodule bump — see .github/workflows/monthly-submodule-bump.yml). Actual numbers in any given build are whatever the upstream submodule pins currently contain; check the staging log line <Source> → assets/<dir>: N SVGs ... printed by dotnet build for the live count.

Source Style Count Member name shape (ISO uppercase)
jdecked/twemoji Emoji-style flat 262 TwemojiFlag.US, TwemojiFlag.GB_ENG
HatScripts/circle-flags Circular 430 CircleFlag.US, CircleFlag.AF_EMIRATE
kapowaz/square-flags Square 417 SquareFlag.US
lipis/flag-icons Rectangular (4×3) 271 LipisFlag.US
Alpaq92/FlagHub (FlagKit fork) Rectangular flat 259 FlagHubFlag.US

All 5 sources live as git submodules under submodules/. The build pipeline (run on every dotnet build) syncs submodules → extracts SVGs into assets/{source}/ (regenerated each build, gitignored) → embeds them as manifest resources → code-generates 5 strongly-typed enums.

Packages

Package Description Target framework(s)
Flags.Icons Core: 4 generated enums, FlagAssetLoader, FlagIcons index netstandard2.0
Flags.Icons.Avalonia Avalonia FlagIcon templated control net8.0
Flags.Icons.Eto Eto.Forms FlagIcon extending ImageView netstandard2.0
Flags.Icons.MAUI .NET MAUI FlagIcon view net10.0 + per-platform TFMs
Flags.Icons.MewUI Aprillz.MewUI fluent helpers (FlagIcon.Create / .Flag()) net10.0
Flags.Icons.Uno Uno Platform FlagIcon control net10.0 + per-platform TFMs
Flags.Icons.WinForms Windows Forms FlagIcon extending PictureBox net8.0-windows
Flags.Icons.WinUi WinUI 3 FlagIcon control net8.0-windows10.0.19041.0
Flags.Icons.WPF WPF FlagIcon control net8.0-windows

Every bundled flag is SVG. Stacks without a native SVG type (Eto, MAUI, MewUI, WinForms) rasterize at runtime through Svg.Skia. Avalonia uses Svg.Controls.Skia.Avalonia, WPF uses SharpVectors, Uno/WinUI use the framework's SvgImageSource.

Installation

dotnet add package Flags.Icons.Avalonia    # or .Eto / .MAUI / .MewUI / .Uno / .WinForms / .WinUi / .WPF

Every platform package transitively pulls in Flags.Icons core, so you don't need to reference it separately.

Usage

FlagIcon exposes one property per source — Twemoji, Circle, Square, Lipis, FlagHub. Set exactly one; the others are cleared automatically.

Avalonia

In App.axaml:

<StyleInclude Source="avares://Flags.Icons.Avalonia/App.xaml" />

Then:

<Window xmlns:flag="clr-namespace:Flags.Icons.Avalonia;assembly=Flags.Icons.Avalonia">
    <flag:FlagIcon Twemoji="US" Width="48" Height="36" />
    <flag:FlagIcon Circle="US" Width="48" Height="36" />
    <flag:FlagIcon FlagHub="US" Width="48" Height="36" />
    <Button Content="{flag:FlagIconExt Lipis=FR, Size=24}" />
</Window>

Eto.Forms

using Flags.Icons;
using Flags.Icons.Eto;

var flag = new FlagIcon { Twemoji = TwemojiFlag.US, Size = new Size(48, 36) };

.NET MAUI

<ContentPage xmlns:flag="clr-namespace:Flags.Icons.Maui;assembly=Flags.Icons.MAUI">
    <flag:FlagIcon Square="US" WidthRequest="48" HeightRequest="36" />
</ContentPage>

Aprillz.MewUI

using Flags.Icons;
using Flags.Icons.MewUi;

var flag = FlagIcon.Create(TwemojiFlag.US, 48, 36);
var img  = new Image().Flag(CircleFlag.FR).Width(24).Height(18);

Uno Platform

<Page xmlns:flag="using:Flags.Icons.Uno">
    <flag:FlagIcon Lipis="US" Width="48" Height="36" />
</Page>

Windows Forms

using Flags.Icons;
using Flags.Icons.WinForms;

var flag = new FlagIcon { Twemoji = TwemojiFlag.US, Width = 48, Height = 36 };

WinUI 3

<Window xmlns:flag="using:Flags.Icons.WinUi">
    <flag:FlagIcon Circle="US" Width="48" Height="36" />
</Window>

WPF

<Window xmlns:flag="clr-namespace:Flags.Icons.WPF;assembly=Flags.Icons.WPF">
    <flag:FlagIcon Twemoji="US" Width="48" Height="36" />
</Window>

Runtime discovery

using Flags.Icons;

// Enumerate per source
foreach (var f in FlagIcons.TwemojiFlags) { /* TwemojiFlag values, e.g. US, FR, GB_ENG, ... */ }
foreach (var f in FlagIcons.CircleFlags)  { /* CircleFlag values  */ }
foreach (var f in FlagIcons.SquareFlags)  { /* SquareFlag values  */ }
foreach (var f in FlagIcons.LipisFlags)   { /* LipisFlag values   */ }
foreach (var f in FlagIcons.FlagHubFlags) { /* FlagHubFlag values */ }

// Open the raw embedded SVG
using Stream? raw = FlagAssetLoader.OpenStream(TwemojiFlag.US);

// Original on-disk filename (preserves upstream casing)
string? fileName = TwemojiFlagFiles.GetFileName(TwemojiFlag.US);   // "US.svg"
string? fileName2 = CircleFlagFiles.GetFileName(CircleFlag.US);    // "us.svg"
string? fileName3 = FlagHubFlagFiles.GetFileName(FlagHubFlag.US);  // "US.svg"

Demos

Each UI stack ships a demo that renders every flag in a wrapping grid with country-code search, source picker (Twemoji / Circle / Square / Lipis / FlagHub / All), section headers, and click-to-copy markup snippets.

dotnet run --project Flags.Icons.Avalonia.Demo
dotnet run --project Flags.Icons.Eto.Demo       # cross-platform
dotnet run --project Flags.Icons.MAUI.Demo      # Windows or macCatalyst
dotnet run --project Flags.Icons.MewUI.Demo     # cross-platform
dotnet run --project Flags.Icons.Uno.Demo       # desktop
dotnet run --project Flags.Icons.WinForms.Demo  # Windows
dotnet run --project Flags.Icons.WinUi.Demo     # Windows (x64/ARM64)
dotnet run --project Flags.Icons.WPF.Demo       # Windows

Building from source

All 5 upstream sources are git submodules under submodules/. Clone with submodules:

git clone --recurse-submodules https://github.com/Alpaq92/Flags.Icons.git

…or after a plain clone (the first dotnet build will also auto-init if it sees submodules/ empty):

git submodule update --init --recursive

Submodule layout

Path Upstream Build picks
submodules/twemoji/ jdecked/twemoji assets/svg/*.svg, filtered to country (1f1XX-1f1YY) + subdivision (1f3f4-…-e007f) emoji, renamed to ISO codes
submodules/circle-flags/ HatScripts/circle-flags flags/*.svg (full set; ~24 Windows-clone symlink stubs auto-resolved)
submodules/square-flags/ kapowaz/square-flags flags/*.svg (curated subset, not flags-original/)
submodules/flag-icons/ lipis/flag-icons flags/4x3/*.svg
submodules/flaghub/ Alpaq92/FlagHub Assets/SVG/*.svg (maintained fork of madebybowtie/FlagKit)

Build pipeline

build/Flags.Icons.Assets.targets runs on every dotnet build and is data-driven: a single <_FlagSource> MSBuild ItemGroup describes every upstream (mode, submodule path, staging dir, logical-name prefix, enum name, human label) and every downstream target batches over it. Adding a sixth source = one new row in that ItemGroup plus a matching <submodule> entry in .gitmodules — nothing else in the targets file changes.

  1. Sync submodules_AutoSyncSubmodulesOnFirstBuild checks each _FlagSource's UpstreamPath and runs git submodule update --init --recursive if any are missing. Skipped on CI (actions/checkout submodules:true already did it). Manual force-sync: dotnet msbuild Flags.Icons/Flags.Icons.csproj -t:SyncSubmodules.

  2. Stage assets_StageFlagAssets transforms _FlagSource into one _FlagStagingJob per source and hands the batch to a single StageFlagAssets task that processes them in parallel (Parallel.ForEach). Two modes:

    • Mode="TwemojiFilter" for twemoji — regex-filters for country + subdivision codepoints and renames to ISO codes.
    • Mode="RawCopy" for the other 4 — copies every *.svg verbatim, resolving Windows-clone symlink stubs along the way.

    Both modes share write-if-different + prune-stale logic in the same task, so subsequent builds keep stable mtimes (incremental-friendly) and upstream-removed files disappear from assets/. assets/ is gitignored — pure build output.

  3. Collect & embed_CollectFlagAssets uses a two-step cross-batch: step 1 globs each source's staging dir (Include="%(_FlagSource.StagingDir)\*.svg") and stamps per-source metadata on each match; step 2 then references each item's own %(LogicalPrefix) + well-known %(Filename)%(Extension) to build the LogicalName (the split avoids the %(Filename) cross-batch ambiguity where it would otherwise bind to the _FlagSource identity). Each staged SVG becomes an EmbeddedResource at assets/{source}/{filename}.svg.

  4. Generate enums_GenerateFlagEnums invokes GenerateFlagEnum once per _FlagSource, producing {EnumName}.g.cs in obj/ (e.g. TwemojiFlag.g.cs) with the enum + a {EnumName}Files.GetFileName(flag) lookup that preserves upstream filename casing. The task receives the full staged-SVG set plus the current SourceId and filters internally — simpler than fighting MSBuild's WithMetadataValue(..., %(batch)) cross-batch resolution. _GenerateFlagEnums short-circuits via Inputs/Outputs when the staged set is unchanged; _IncludeGeneratedFlagEnums is a safety net that re-adds any existing .g.cs to Compile on those skipped second-build runs.

Runtime helpers in Flags.Icons (the core package): FlagAssetLoader.OpenStream has 5 typed overloads (one per source enum); FlagSourceDispatch.OpenActive/GetActive is the shared dispatch the 8 per-stack FlagIcon controls use to walk their 5 source properties (DependencyProperty / BindableProperty / StyledProperty / plain CLR property depending on the stack) and pick the active one.

If a submodule is missing (e.g. CI checked out without submodules), the corresponding enum will only contain None = 0 and a warning is emitted.

License

MIT for source code. Bundled flag SVGs come from:

The project icon (icon.png) is from the Jellyfin UX icon set, licensed under CC BY-SA 4.0.

Credits

Development

Parts of this codebase — the per-platform FlagIcon wrappers, demo scaffolding, and CI/CD configuration — were developed with assistance from an audit-based AI workflow, with each change reviewed and verified by a human maintainer before being merged. Bug reports and PRs are welcome.


Release history in CHANGELOG.md. Versions are driven by Conventional Commits via release-please; branch ruleset details in .github/rulesets/README.md.

About

Drop-in FlagIcon controls for C#/.NET UIs, bundling FlagKit's PNG & SVG country flag assets.

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors