Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
1760e33
Add Iconography navigation handling
GID0317 Aug 30, 2025
9a9e1d3
Add Iconography navigation item to NavigationRootPage
GID0317 Aug 30, 2025
0416a0a
Add IconsDataSource class for loading icons
GID0317 Aug 30, 2025
5cb71e8
Port all icon data list available from WinUi3 gallery
GID0317 Aug 30, 2025
fe24e35
Add IconsDataSchema.json for glyph metadata
GID0317 Aug 30, 2025
7e37f93
Add Iconography section to Controls.Foundation.json
GID0317 Aug 30, 2025
0e5edff
Add EmbeddedResource for IconsData.json
GID0317 Aug 30, 2025
5f6b9e3
Change namespace import from Models to DataModel
GID0317 Aug 30, 2025
1e278c0
Add IconData class for icon representation
GID0317 Aug 30, 2025
4c82e71
Add the xaml side of iconograpy
GID0317 Aug 30, 2025
fc56035
Add the cs side for the iconography page
GID0317 Aug 30, 2025
e9f0024
Enhance clipboard copy functionality for the code example under setti…
GID0317 Aug 30, 2025
d2cc51b
Update hyperlink for FontIcon documentation
GID0317 Aug 30, 2025
5dcaaeb
Refactor IconographyPage layout and controls for consistency
GID0317 Aug 31, 2025
9cff2e7
Add 'Set' property to IconData class
GID0317 Aug 31, 2025
2012e1e
Implement icon set selection and population logic
GID0317 Aug 31, 2025
9734556
Update placeholder text in IconographyPage.xaml since tags and code c…
GID0317 Aug 31, 2025
ee1b8a9
Enhance icon loading with reflection and fallback
GID0317 Aug 31, 2025
3a5eeac
Merge branch 'iNKORE-NET:main' into Gallery-Revamp-Design-Iconography
GID0317 Aug 31, 2025
b807575
Delete source/iNKORE.UI.WPF.Modern.Gallery/DataModel/IconsData.json
GID0317 Sep 1, 2025
7db84bd
Delete source/iNKORE.UI.WPF.Modern.Gallery/DataModel/IconsDataSchema.…
GID0317 Sep 1, 2025
c4a2db6
Remove EmbeddedResource for IconsData.json
GID0317 Sep 1, 2025
fec3cbb
Refactor IconData class structure and properties
GID0317 Sep 1, 2025
a2e9209
Refactor IconsDataSource by removing fallback loading
GID0317 Sep 1, 2025
f92847a
fix: (gallery/IconographyPage) re-format XAML code
NotYoojun Sep 1, 2025
4cb1768
feat: (gallery/IconographyPage) hide tags & update sample code
NotYoojun Sep 1, 2025
d771d0d
feat: (gallery/IconographyPage) list item hover visuals
NotYoojun Sep 1, 2025
eb217ef
Enhance IconData and simplify legacy set logic
GID0317 Sep 1, 2025
0470289
Add FontFamily property to IconData class
GID0317 Sep 1, 2025
fa964c7
Update IconographyPage.xaml for font family binding
GID0317 Sep 1, 2025
580fe10
refactor: (gallery/IconsDataSource) glyph handling and update UI bind…
NotYoojun Sep 3, 2025
b131836
refactor: (gallery/IconographyPage) example control border
NotYoojun Sep 3, 2025
145a7a6
Update iconography descriptions
GID0317 Sep 3, 2025
11ce5c5
Merge branch 'iNKORE-NET:main' into Gallery-Revamp-Design-Iconography
GID0317 Sep 3, 2025
4d04221
Merge branch 'iNKORE-NET:main' into Gallery-Revamp-Design-Iconography
GID0317 Sep 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions source/iNKORE.UI.WPF.Modern.Gallery/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<SolidColorBrush x:Key="NavigationViewExpandedPaneBackground" Color="Transparent" />
<SolidColorBrush x:Key="AppContentBackgroundBrush" Color="{StaticResource SystemAltHighColor}" />
<StaticResource x:Key="ControlExampleDisplayBrush" ResourceKey="SolidBackgroundFillColorBaseBrush" />
<StaticResource x:Key="GalleryBorderBrush" ResourceKey="CardStrokeColorDefaultBrush" />
</ResourceDictionary>

<ResourceDictionary x:Key="Dark" ui:ThemeDictionary.Key="Dark">
Expand All @@ -47,6 +48,7 @@
<SolidColorBrush x:Key="AppContentBackgroundBrush" Color="#FF282828" />
<SolidColorBrush x:Key="NavigationViewExpandedPaneBackground" Color="Transparent" />
<StaticResource x:Key="ControlExampleDisplayBrush" ResourceKey="SolidBackgroundFillColorBaseBrush" />
<StaticResource x:Key="GalleryBorderBrush" ResourceKey="CardStrokeColorDefaultBrush" />
</ResourceDictionary>

<ResourceDictionary x:Key="HighContrast" ui:ThemeDictionary.Key="HighContrast">
Expand All @@ -60,6 +62,7 @@
<SolidColorBrush x:Key="SearchBoxBorderBrush" Color="{DynamicResource SystemColorWindowTextColor}" />
<SolidColorBrush x:Key="ControlExampleDisplayBrush" Color="{DynamicResource SystemColorWindowColor}" />
<SolidColorBrush x:Key="PageHeaderForegroundBrush" Color="{DynamicResource SystemColorWindowTextColor}" />
<SolidColorBrush x:Key="GalleryBorderBrush" Color="{DynamicResource SystemColorWindowColor}" />
</ResourceDictionary>
</ui:ThemeResources.ThemeDictionaries>
</ui:ThemeResources>
Expand Down
158 changes: 158 additions & 0 deletions source/iNKORE.UI.WPF.Modern.Gallery/Data/IconsDataSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using iNKORE.UI.WPF.Modern.Gallery.DataModel;

namespace iNKORE.UI.WPF.Modern.Gallery.Helpers;

internal class IconsDataSource
{
public static IconsDataSource Instance { get; } = new();

public static List<IconData> Icons => Instance.icons;

// Public list of available icon sets discovered via reflection
public List<string> AvailableSets { get; } = new();

// Current active set name (null = all)
public string ActiveSet { get; private set; }

private List<IconData> icons = new();

private IconsDataSource() { }

public object _lock = new();

public async Task<List<IconData>> LoadIcons()
{
// Yield once to keep this method truly asynchronous without changing logic.
await Task.Yield();
// If already loaded, return current list
lock (_lock)
{
if (icons.Count != 0)
{
return icons;
}
}

// Try reflection-first: enumerate types in Common.IconKeys namespace
try
{
var assembly = typeof(iNKORE.UI.WPF.Modern.Common.IconKeys.FontDictionary).Assembly;
var types = assembly.GetTypes().Where(t => t.IsClass && t.IsSealed && t.IsAbstract && t.Namespace == "iNKORE.UI.WPF.Modern.Common.IconKeys");
var discovered = new List<IconData>();

foreach (var type in types)
{
// collect a set name for the class
var setName = type.Name;
// Try public static fields and properties of type FontIconData
var fields = type.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
foreach (var f in fields)
{
if (f.FieldType.FullName == "iNKORE.UI.WPF.Modern.Common.IconKeys.FontIconData")
{
try
{
var value = f.GetValue(null);
var glyphProp = value?.GetType().GetProperty("Glyph");
var glyph = glyphProp?.GetValue(value) as string;
var familyProp = value?.GetType().GetProperty("FontFamily");
var family = familyProp?.GetValue(value) as System.Windows.Media.FontFamily;
var name = f.Name;
var data = new IconData { Name = name, Glyph = glyph, Set = setName, FontFamily = family };
discovered.Add(data);
}
catch { }
}
}

var props = type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
foreach (var p in props)
{
if (p.PropertyType.FullName == "iNKORE.UI.WPF.Modern.Common.IconKeys.FontIconData")
{
try
{
var value = p.GetValue(null);
var glyphProp = value?.GetType().GetProperty("Glyph");
var glyph = glyphProp?.GetValue(value) as string;
var familyProp = value?.GetType().GetProperty("FontFamily");
var family = familyProp?.GetValue(value) as System.Windows.Media.FontFamily;
var name = p.Name;
var data = new IconData { Name = name, Glyph = glyph, Set = setName, FontFamily = family };
discovered.Add(data);
}
catch { }
}
}

if (discovered.Any(d => d.Set == setName))
{
AvailableSets.Add(setName);
}
}

if (discovered.Count > 0)
{
lock (_lock)
{
icons = discovered.OrderBy(i => i.Name).ToList();
}
// Ensure legacy/alias sets are present so the UI can show them
EnsureLegacySets();
return icons;
}
}
catch
{
// reflection failed; no fallback
}

return icons;
}

//private static string ToCode(string glyph)
//{
// if (string.IsNullOrEmpty(glyph)) return string.Empty;
// // glyph is a single-character string; convert to hex code (without leading 0x)
// var ch = glyph[0];
// return ((int)ch).ToString("X4");
//}

// Set active set and return filtered icons
public List<IconData> SetActiveSet(string setName)
{
// Normalize legacy aliases to concrete set names when possible
//if (string.Equals(setName, "SegoeMDL2Assets", StringComparison.OrdinalIgnoreCase) ||
// string.Equals(setName, "Segoe MDL2 Assets", StringComparison.OrdinalIgnoreCase))
//{
// // These glyphs generally live in the JSON data under empty Set (or specific set names).
// // Treat this alias as a request to show all non-Fluent-only icons.
// ActiveSet = setName;
// return icons.Where(i => !i.IsSegoeFluentOnly).ToList();
//}

//if (string.Equals(setName, "SegoeIcons", StringComparison.OrdinalIgnoreCase) ||
// string.Equals(setName, "Segoe Icons", StringComparison.OrdinalIgnoreCase))
//{
// // No dedicated SegoeIcons set in the built-in keys; treat as all icons (fallback).
// ActiveSet = setName;
// return icons;
//}

ActiveSet = setName;
if (string.IsNullOrEmpty(setName)) return icons;
return icons.Where(i => i.Set == setName).ToList();
}

private void EnsureLegacySets()
{
// No-op: legacy set aliases are handled in SetActiveSet().
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,30 @@
"Description": "Design guidance and resources",
"Items":
[
{
"UniqueId": "Iconography",
"Title": "Iconography",
"Subtitle": "Segoe Fluent Icons and MDL2 Assets",
"ImagePath": "ms-appx:///Assets/ControlIcons/DefaultIcon.png",
"ImageIconPath": "ms-appx:///Assets/ControlIcons/DefaultIcon.png",
"Description": "",
"Content": "",
"IncludedInBuild": true,
"IsNew": false,
"IsUpdated": false,
"Docs":
[
{
"Title": "Iconography in Windows 11",
"Uri": "https://learn.microsoft.com/windows/apps/design/signature-experiences/iconography#system-icons"
},
{
"Title": "Segoe Fluent Icons font",
"Uri": "https://learn.microsoft.com/windows/apps/design/style/segoe-fluent-icons-font"
}
],
"RelatedControls": []
},
{
"UniqueId": "Typography",
"Title": "Typography",
Expand Down Expand Up @@ -68,4 +92,4 @@
]
}
]
}
}
47 changes: 47 additions & 0 deletions source/iNKORE.UI.WPF.Modern.Gallery/DataModel/IconData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Windows.Media;
using iNKORE.UI.WPF.Modern.Common.IconKeys;

namespace iNKORE.UI.WPF.Modern.Gallery.DataModel
{
public class IconData
{
public string Name { get; set; }
// Which icon set this icon came from (e.g. "SegoeFluentIcons", "FluentSystemIcons.Regular")
public string Set { get; set; }
public string[] Tags { get; set; } = Array.Empty<string>();
// The actual font to use for rendering this glyph (important for Fluent System Icons)
public FontFamily FontFamily { get; set; }

public string Code { get; protected set; }


private string p_glyph;
public string Glyph
{
get => this.p_glyph;
set
{
this.p_glyph = value;
this.Code = ToCode(this.p_glyph);
}
}

public string CodeGlyph => string.IsNullOrWhiteSpace(Code) ? string.Empty : "\\u" + Code;
public string TextGlyph => string.IsNullOrWhiteSpace(Code) ? string.Empty : "&#x" + Code + ";";

// WPF doesn't have Symbol enum like WinUI
public string SymbolName => null;


public static string ToCode(string glyph)
{
var codepoint = FontIconData.ToUtf32(glyph);
return $"{codepoint:X}";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@
<ui:FontIcon Glyph="&#xEB3C;" />
</ui:NavigationViewItem.Icon>
<ui:NavigationViewItem.MenuItems>
<ui:NavigationViewItem
x:Name="IconographyItem"
Content="Iconography"
Tag="Iconography">
<ui:NavigationViewItem.Icon>
<ui:FontIcon Glyph="&#xED58;" />
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<ui:NavigationViewItem
x:Name="TypographyItem"
Content="Typography"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,19 +293,36 @@ private void OnNavigationViewSelectionChanged(NavigationView sender, NavigationV
_lastItem = item;
rootFrame.Navigate(item);
}
else if (selectedItem?.Tag?.ToString() == "Iconography")
{
var iconographyId = "Iconography";
if (_lastItem?.ToString() == iconographyId) return;
_lastItem = iconographyId;

// Find Iconography item from the data source
var iconographyItem = ControlInfoDataSource.Instance.Realms
.SelectMany(r => r.Groups)
.SelectMany(g => g.Items)
.FirstOrDefault(i => i.UniqueId == "Iconography");

if (iconographyItem != null)
{
rootFrame.Navigate(ItemPage.Create(iconographyItem));
}
}
else if (selectedItem?.Tag?.ToString() == "Typography")
{
// Handle Typography navigation
var typographyId = "Typography";
if (_lastItem?.ToString() == typographyId) return;
_lastItem = typographyId;

// Find Typography item from the data source
var typographyItem = ControlInfoDataSource.Instance.Realms
.SelectMany(r => r.Groups)
.SelectMany(g => g.Items)
.FirstOrDefault(i => i.UniqueId == "Typography");

if (typographyItem != null)
{
rootFrame.Navigate(ItemPage.Create(typographyItem));
Expand Down
Loading
Loading