Skip to content

CmdPal: Native Adaptive Cards charts and redesigned Performance Monitor cards - #51125

Closed
Clint Rutkas (crutkas) wants to merge 29 commits into
mainfrom
crutkas-dock-performance-cards-redesign
Closed

Clint Rutkas (crutkas) wants to merge 29 commits into
mainfrom
crutkas-dock-performance-cards-redesign

Conversation

@crutkas

@crutkas Clint Rutkas (crutkas) commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

Summary of the Pull Request

The Performance Monitor cards in the Command Palette dock looked rough: each chart was a fixed 268x86 SVG image, values were pinned to the card's edges, and most of the card was empty. This PR rebuilds them as Task Manager-style dashboards and keeps them plain Adaptive Cards: no fork of the renderer, no new dependencies, and card JSON that uses only what the Adaptive Cards schema defines.

  • Native Adaptive Cards visuals. Command Palette now renders Chart.Line, Chart.Gauge, Chart.Donut, Chart.Pie, Chart.VerticalBar, Chart.HorizontalBar, Chart.HorizontalBar.Stacked, ProgressBar, Badge, and Icon with native WinUI controls, through the WinUI 3 renderer's public custom element APIs. Every extension can use them, with a fallback for other hosts. They're in a new library, Microsoft.CmdPal.AdaptiveCards.Polyfills, with nothing specific to Command Palette in it, so each one can move to the renderer upstream and be deleted here.
  • Schema only. The renderers read only the properties on each element's page of the element reference, with its defaults. The look comes from how Command Palette draws them, such as smooth, filled lines, sparklines when a line chart is narrow, and gauges that fill in the current segment's color.
  • Theme-aware host config. Generated from Fluent theme resources, the accent color, and high contrast colors, and refreshed when the theme changes. Containers, column sets, and columns support roundedCorners and showBorder.
  • High contrast. Chart data takes the contrast theme's system colors in turn, line series also differ by dash pattern, and every third and fourth slice, segment, or part is an outline, so items stay distinct in every contrast theme.
  • Live updates in place. The incremental updater patches chart data and text in the existing controls, so charts scroll instead of the card being rebuilt every second.
  • Redesigned cards. A new Overview card (and dock band) with six tiles, and deeper CPU, Memory, GPU, Disk, Network, and Battery cards: utilization per logical processor and top processes, memory composition and hardware, GPU engines and memory, disk type and response time, connection type and addresses, and battery health. Details such as per-processor utilization and top processes are read only while their card is open.

Network card, before and after

Disk card, before and after

Overview card, dark and light

Every card in dark and light, the Samples gallery, high contrast, and Icon fallback

CPU, Memory, and GPU cards, dark

Disk, Network, and Battery cards, dark

CPU, Memory, and GPU cards, light

Disk, Network, and Battery cards, light

Charts and visuals page in the Samples extension

Charts and visuals page with the Aquatic and Desert contrast themes' colors

Icons without a glyph draw their fallback

The screenshots come from a local harness that renders the real templates and live data through the same renderer and controls, at the dock window's content width. The Network card's addresses are replaced with documentation addresses, and the "before" images are from #50720. The harness can't switch the system to a contrast theme, so the high contrast images use the colors from each contrast theme's .theme file. Progress bars take their color from the app's theme resources, so there they still show the accent color.

PR Checklist

  • Communication: I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected
  • Tests: Added/updated and all pass
  • Localization: All end-user-facing strings can be localized
  • Dev docs: Added/updated
  • New binaries: Added on the required places. Microsoft.CmdPal.AdaptiveCards.Polyfills.dll ships inside the Command Palette MSIX, which is what's signed, and CI runs every *UnitTest* project, so like Microsoft.CmdPal.AdaptiveCards.IncrementalRendering it only needed solution entries, not these:
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx (N/A)

Detailed Description of the Pull Request / Additional comments

How it fits together

  • Microsoft.CmdPal.AdaptiveCards.Polyfills, a new class library: one model and one control per element, roundedCorners and showBorder for containers, and the fallback workaround below. Models parse the element JSON without WinUI, so unit tests cover them directly (Microsoft.CmdPal.AdaptiveCards.Polyfills.UnitTests), and controls draw with XAML shapes, built in code. Command Palette registers it with three calls in ContentFormControl and passes in the chart strings, which stay in its Resources.resw. The README explains the pieces, how to add an element, and how to delete each one when the renderer supports it.
  • AdaptiveCardsConfig, AdaptiveCardThemeTokens, and AdaptiveHostConfigJson build the host config, cached per theme, and ContentFormControl.xaml has the theme-aware container styles that roundedCorners and showBorder apply. These are Command Palette's design, so they stay in Microsoft.CmdPal.UI.
  • Microsoft.CmdPal.AdaptiveCards.IncrementalRendering: registered elements implement IIncrementalAdaptiveElementControl, so the updater moves new data into the existing control, and their data no longer counts toward the card's semantic fingerprint.
  • Performance Monitor: new templates and data (PerformanceChartData, ProcessCpuSampler, MemoryHardware, DiskVolumes, NetworkConnectionDetails, and more), an Overview page and dock band, and one shared sample per second for each metric.
  • Extension authors: references/charts-and-visuals.md in the extension template's add-adaptive-card-form skill, and a live "Charts and visuals" page in the Samples extension.

Adaptive Cards compliance

The cards use only element types, properties, and values from the current element reference, and the renderers read nothing else. A script checked every element of the expanded cards (the seven Performance Monitor cards, the Samples page, and an Icon fallback card) against the reference: 1,565 elements, no problems. Command Palette doesn't support all of the schema yet: Chart.VerticalBar.Grouped and ProgressRing are dropped, even with a fallback (see the renderer bug below); thickness, valueColor, showOutlines, maxWidth, and Icon.selectAction are ignored; and Icon draws the 130 catalog names that have a matching Segoe Fluent Icons glyph, and the icon's fallback for other names.

Worth a careful look

  • On main, the incremental updater never patches in place in release builds. Release builds use native AOT, where CsWinRT finds an object's type by name and needs its metadata. Element tags came back as bare IInspectable objects, so every update rebuilt the whole card. 03a557d3bb keeps that metadata with DynamicDependency, and also fixes an InvalidCastException in chart legends and the high contrast colors, which only failed under AOT.
  • The host config changes every extension's cards, not just these. Card and container padding goes from 8 to 12 px. Medium, large, and extra large spacing go from 20, 30, and 40 to 16, 24, and 32 px, on Fluent's 4 px grid. Separator lines go from 0 to 1 px, so separator: true now draws a line. The medium and extra large font sizes go from 14 and 26 to 16 and 28. The font changes from a web font stack to Segoe UI Variable, with Cascadia Mono for monospace, and colors come from theme resources instead of fixed values. Small and default spacing, image sizes, and action settings don't change.
  • The WinUI 3 renderer never shows an element's fallback. XamlBuilder::RenderAsUIElement renders it and then returns an empty result (since [UWP Renderer] Allow nested fallbacks AdaptiveCards#8234). So on main too, Command Palette drops an unknown element even when it has a fallback. Command Palette's own elements draw their fallback themselves (AdaptiveFallbackRenderer), which is how an Icon without a glyph shows its fallback. The upstream fix is one line.
  • AdaptiveCustomElementJson, from main, moves into the new library and becomes public, since both the library's elements and Command Palette's settings inputs use it.
  • Chart elements reach third-party extensions right away. They render only in Command Palette builds with this change, and the docs require a fallback.
  • Line history isn't padded. The schema's y is a number with no "missing" value, so a history that's still filling up spans the whole chart until 60 samples arrive. Dock bands sample while the dock is visible, so a card opened from the dock usually has a full history.

Also fixed along the way:

  • A metric shown in two places was sampled twice, so its history moved at double speed.
  • A one-second "No battery" or placeholder flash when a card opened, and very long GPU names in the dock label.
  • The Disk list item said Disk (0 C:) while its card said Disk 0 (C:).
  • Plugged in and full, the Battery card showed a "Discharge rate" next to "Not discharging", and rebuilt itself as that row came and went.
  • Chart axis labels and tooltips shortened large numbers with hard-coded K, M, B, and T suffixes. The suffixes now come from resources, so they can be translated.
Found while testing, not changed here
  • The dock's acrylic renders solid black on the ARM64 test machine, so in the light theme its glyphs and labels are invisible.
  • Dock bands are named Microsoft.CmdPal.UI.ViewModels.Dock.DockBandViewModel in UI Automation, and the dock buttons can't be invoked, so screen readers can't use the dock.
  • A settings file without DockSettings.Side loads the dock on the left, although the default is the top.
  • With Command Palette's theme set to Dark on a light system, the window's backdrop and footer stay light.
  • The debug build badge has no accessible name.

Size and where to look

29 commits, mostly one per step: +12,558 and −1,127 lines in 130 files. About half is generic Adaptive Cards code that any host could use, and the rest is Command Palette's. About 6,100 of the added lines are C# code outside the tests, with about 560 lines of comments. The last two commits move the generic code into its own library; the first of them only moves files.

Area Lines added What it is
Generic Adaptive Cards 6,627 Code any Adaptive Cards host could use
Polyfills library 4,686 The 10 elements and the renderer fixes: drawing (1,843), parsing (1,214), shared palette, theme, geometry, and formatting (990), registration with the renderer and its fixes (360), the icon name table (177), and the README and project (102)
Polyfills tests 1,317 89 test methods
Incremental updater 624 (−64) Patching registered elements in place (390), and 17 test methods (234)
Command Palette 5,912 Command Palette's own code
Performance Monitor code 2,072 (−520) Readers and samplers for CPU, GPU, memory, disk, and network (1,474), and the pages that feed the cards and dock bands (598)
Performance Monitor card templates 1,636 (−209) Adaptive Card JSON
Performance Monitor tests 838 60 test methods
Performance Monitor strings and build 237 (−3) Resource strings, NativeMethods.txt, and the project file
Card host 403 (−326) The theme-aware host config and container styles, the chart strings, and the library's registration
Samples extension 489 The "Charts and visuals" page
Extension author docs 237 (−1) The charts reference in the extension template
Solution and spelling files 19

For review, this could split along the projects: (1) the polyfills library and its tests; (2) the host config and Command Palette's wiring; (3) the Performance Monitor cards and data, with the samples.

Validation Steps Performed

On an ARM64 Windows 11 machine, with the final code:

  • MSBuild.exe <project> -nologo -m -restore -v:minimal -p:Configuration=Debug -p:Platform=ARM64 -p:RuntimeIdentifier=win-arm64 -p:CIBuild=false -p:GeneratePackageLocally=false -p:GenerateAppxPackageOnBuild=false -p:PublishAppxPackage=false -p:SkipLongPathsCheck=true for Microsoft.CmdPal.AdaptiveCards.Polyfills, Microsoft.CmdPal.UI, SamplePagesExtension, and the four test projects below: exit code 0. These projects run the trim and AOT analyzers, with warnings as errors.
  • vstest.console.arm64.exe ARM64\Debug\WinUI3Apps\CmdPal\tests\Microsoft.CmdPal.UI.UnitTests.dll /Platform:ARM64: 686 passed.
  • vstest.console.arm64.exe ARM64\Debug\WinUI3Apps\CmdPal\tests\Microsoft.CmdPal.AdaptiveCards.Polyfills.UnitTests.dll /Platform:ARM64: 128 passed (the chart tests, which were in the UI tests before the move).
  • vstest.console.arm64.exe ARM64\Debug\WinUI3Apps\CmdPal\tests\Microsoft.CmdPal.AdaptiveCards.IncrementalRendering.UnitTests.dll /Platform:ARM64: 43 passed.
  • vstest.console.arm64.exe ARM64\Debug\WinUI3Apps\CmdPal\tests\Microsoft.CmdPal.Ext.PerformanceMonitor.UnitTests.dll /Platform:ARM64: 166 passed.
  • The same build command with -p:Configuration=Release -p:Platform=x64 -p:RuntimeIdentifier=win-x64 for the library's tests (which build the library), Microsoft.CmdPal.UI, and the UI tests: exit code 0.
  • Local harness (not in the repo): every card in dark and light for 65 seconds of live data. All render, and every card updates in place; the CPU card rebuilds once, when its per-processor and top process sections first appear.
  • High contrast in the harness, with each contrast theme's colors (Aquatic, Desert, Dusk, and Night sky): lines differ by color and dash pattern, parts alternate between fills and outlines, and the legends match.
  • Battery-style gauges at 12%, 35%, and 100%, and a gauge without segments or a needle, in dark, light, and the Aquatic and Desert colors.
  • An Icon fallback card in the harness: Calendar draws its glyph, and Bot draws a TextBlock fallback, a Container fallback whose text updates, or nothing with drop. 14 updates, none of them full replacements.
  • The same harness published with native AOT, optimized, with the UI project's CsWinRT settings: every card renders and updates in place. Rerun after the review fixes (with the Aquatic colors) and after the gauge restyle (dark and light): no warnings, and every card that it ran renders and updates in place, including the gauges and the Icon fallback card.
  • After the move, the harness built against the library's DLL, under JIT and native AOT (no warnings): every card renders and updates in place, as before. Compared with the build before the move, with the Samples page's seeded data, the gauges, and the Icon fallback card: identical in dark and light, apart from anti-aliasing that differs by one level and the indeterminate progress bar's animation. With the contrast themes' colors, only the line chart changed: its axis labels and grid lines take the contrast theme's text color, as they already did in a real contrast theme through the XAML resources it no longer uses.
  • Schema check of the expanded cards: 1,565 elements, no problems, and again after the move. The cards before the compliance commit (6ef65d69ed) had 669 problems, such as null samples, chart properties that the schema doesn't define, and chart colors on progress bars.
  • A local approximation of the check-spelling workflow is clean, and so is .pipelines\verifyCommonProps.ps1.
  • After the move, the packaged app (Microsoft.CommandPalette.Dev, registered from the build output), light theme: it loads Microsoft.CmdPal.AdaptiveCards.Polyfills.dll from its package folder, and the Overview, CPU, Memory, GPU, Network, and Battery cards opened from the real dock draw every chart natively: line charts and sparklines, the per-processor bar chart, the top process bars, the memory composition bar, the restyled battery gauge, icons, and badges.
  • At 6ef65d69ed, the packaged app, cards opened from the real dock: the CPU card patches in place (the same UI Automation element, with its up time changing); the Battery card shows the segmented gauge, and no discharge rate while plugged in.

Earlier in the branch:

  • Before the code review fixes (4c07d44cbe), x64 Release builds of the UI and the test projects passed, and so did their tests.
  • At 870941431f, every card was opened from the real dock in the packaged app, and all rendered.

Not verified yet in the packaged app: dark theme, a real contrast theme, and 150% scale. Also not done: a native AOT publish of Command Palette itself.

Clint Rutkas (crutkas) and others added 23 commits October 8, 2026 00:23
Adds Command Palette support for the Adaptive Cards Chart.Line element as a
custom WinUI element (XAML shapes, theme-aware palette, monotone smoothing,
gradient fill, latest-value marker, Task Manager style corner labels), so
extensions can send standard chart JSON instead of SVG images.

- IncrementalRendering: custom elements can opt in to in-place patching via
  IncrementalPatchableElements + IIncrementalAdaptiveElementControl, so live
  charts update (and scroll-animate) without replacing the card.
- Container/ColumnSet/Column now honor roundedCorners and showBorder through
  a decorator around the built-in renderers.
- Performance Monitor CPU card: 60-second history chart, speed, base speed,
  processes, threads, handles, up time, logical processors, and CPU name.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
… elements

Command Palette now renders more of the current Adaptive Cards schema natively,
so extension cards can show rich, theme-aware visuals and still stay standard
Adaptive Cards JSON:

- Chart.Gauge, Chart.Donut, Chart.Pie, Chart.VerticalBar, Chart.HorizontalBar,
  and Chart.HorizontalBar.Stacked, plus ProgressBar and Badge. Every element
  registers through one registry (AdaptiveVisualElements), parses leniently
  with warnings, and patches in place through the incremental updater.
- The host config now uses Fluent design tokens (type ramp, spacing, semantic
  and container colors) for light, dark, and high contrast, and follows the
  system accent color. Cards re-render when the theme changes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…and battery cards

Each card now leads with its key numbers and draws a 60-second native
Chart.Line history, then adds the details that matter for that metric:

- Memory: in use and available, plus a composition bar (in use, modified,
  standby, free) like Task Manager's.
- Disk: read and write rates on one auto-scaled axis, plus a capacity bar for
  each volume on the disk that turns warning or attention as it fills up.
- Network: send and receive throughput in the user's unit, plus link speed.
  The old chart plotted bytes against link speed, so it was usually flat.
- GPU: a utilization history alongside the existing details.
- Battery: a charge bar colored by level, plus charge or discharge rate,
  health, and full charge capacity from the aggregate battery report.

The DevHome-era SVG chart images are removed.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ier sampling

- Overview: the list starts with a card that shows every metric at a glance,
  one tile per metric with its value and the last minute as a sparkline. The
  tiles show the metric pages' own data, so values match the detail cards, and
  the detail pages are commands on the card.
- GPU: the card adds engine utilization (3D, Copy, Video decode, Video
  encode) and dedicated and shared GPU memory, as in Task Manager. Short GPU
  names drop driver details in parentheses, which also shortens the dock label.
- Colors: each metric has its own color, and flows use one pair on every card:
  teal for data coming in and marigold for data going out.
- Sampling: pages that show the same metric share its stats, so each stats
  object is sampled at most once per interval and charts keep one sample per
  second. A page now samples as soon as it opens, so cards don't start with
  placeholder values.
- Battery: the card hides the time remaining when there isn't one.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- Donut: the track ring lined up half a ring inside the slices, because an
  ellipse strokes inside its bounds while arcs stroke on the radius.
- Gauge: segments reach both ends of the arc, and the title aligns with the
  other charts' titles.
- Vertical bars: the zero label no longer floats below the category labels;
  the minimum is labeled only when it isn't zero.
- Add a README for the native visuals: how elements work, theming, and how to
  add one.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- The extension template's Adaptive Cards skill now covers Chart.Line,
  Chart.Gauge, Chart.Donut, Chart.Pie, the bar charts, ProgressBar, Badge,
  and rounded, bordered tiles: properties, colors, live updates, and
  fallbacks for hosts that don't support them.
- The Samples extension has a "Charts and visuals" page that shows every
  element, with a line chart, gauge, and progress bar that update each second.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The overview can now be pinned to the dock. The band is a single Overview
button: its metrics start sampling only when the overview opens, so pinning
it costs nothing while the dock is idle. Histories live in the shared stats,
so metrics that other pinned bands sample show their last minute right away.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The host config cache held one config, so light and dark card hosts on screen
at the same time replaced each other's config, and the next Loaded or theme
change re-rendered a card that hadn't changed. Keep the latest few configs.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The CPU card ends with a bar for each logical processor, like Task Manager's
logical processor view. All processors are read in one batch, and only while
a CPU card is open: the dock band and the overview don't request them.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The network card shows the adapter's connection type (Wi-Fi, Ethernet, or
Cellular) and its IPv4 and IPv6 addresses, preferring public addresses over
private and link-local ones. The all-adapters view describes the connection
with the default gateway. Adapter details are cached for 15 seconds, so the
card doesn't enumerate adapters every second. The Wi-Fi network name isn't
shown because reading it needs location access.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The disk card shows what kind of disk it is, such as SSD (NVMe), and its
average response time, as Task Manager does. The disk type comes from a
storage property query that needs no access rights, so it works without
elevation, and it's read once per disk. Also remove the chart history
overload that only the old SVG charts used.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…mory

The memory card adds the hardware details from Task Manager's memory page:
speed, slots used, form factor, and hardware reserved memory. Speed, slots,
and form factor come from the firmware's SMBIOS memory device records, and
reserved memory is installed memory that Windows can't use. They don't change
while Windows runs, so they're read once.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The CPU card now lists the five processes using the most CPU, as a share of
all processors like Task Manager, averaged over the last three seconds so
the list stays steady. Processes are read with one NtQuerySystemInformation
snapshot per sample, only while the card is open, and the snapshot buffer
is released when it closes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Adds the Icon element from the current Adaptive Cards schema (name, size,
style, color, horizontalAlignment) and the Badge icon and iconPosition
properties. Icon names come from the Fluent System Icons catalog that
Adaptive Cards uses; Command Palette draws them with Segoe Fluent Icons,
which it already uses, through a map of 130 catalog names to the glyphs that
draw the same symbols, with filled variants where Segoe has them.

Performance Monitor uses icons in the overview tile headers (CPU, memory,
GPU, disk, network type, battery level, up time) and in the network, disk,
and battery badges. The Samples gallery and the extension-author docs cover
the new element.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The GPU card's engine tiles (3D, Copy, Video decode, Video encode) now show a
sparkline of the last minute, like Task Manager's engine graphs, instead of a
bar of the current value. The engine values were already read every sample,
so keeping their history adds no counter reads. Engine and overview
sparklines share one scale rule: the top rounds up to the next 10%.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…path

CPUStats still carried Dev Home's top-processes code (one performance counter
per windowed process, a kill-process helper, and DataType.CpuWithTopProcesses),
which nothing enabled. The CPU card's top processes now come from
ProcessCpuSampler, so the old path, its timing scaffolding, and the
commented-out template bindings are removed.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Rewords comments and names that check-spelling would flag (grid lines, the
monotone cubic reference, SpeedMegaTransfers, sample week labels) and four
sentences that matched the forbidden article pattern. Terms that cards show
or Windows APIs use are added to expect.txt: dimm, sodimm, hdd, nvme,
sparkline, rsmb (the SMBIOS firmware table), and wdk (Windows.Wdk).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- Incremental rendering: a registered element without requires always renders
  itself, so its fallback is never drawn. The fingerprint now ignores that
  fallback instead of counting its TextBlocks as unmapped text, which made
  every text change rebuild cards whose charts have TextBlock fallbacks (the
  battery card and the Samples gallery). Fallbacks of elements with requires
  still count.
- CPU card: per-processor bars wait for a second sample instead of showing
  0%, and samples older than three seconds are discarded, so reopening the
  card doesn't show an average over the time it was closed.
- Process sampler: the snapshot buffer is pinned, because the snapshot holds
  absolute pointers into it.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
A horizontal bar chart sized its label column to the longest label, so a
long process name could squeeze the bars on the CPU card's top processes.
Labels are now at most 40% of the chart's width, trimmed with an ellipsis,
with the full label in a tooltip when it's trimmed.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The Performance Monitor list titled the disk with the raw counter instance,
such as "Disk (0 C:): 3%", while the disk card says "Disk 0 (C:)". The list
now uses the card's name: "Disk 0 (C:): 3%". The format string changed
meaning, so it has a new resource key.

Found while checking the cards in the packaged app.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Release builds compile Command Palette with native AOT. There, CsWinRT finds
the projected type of an object it receives by name, which needs the type's
metadata. Several values the cards read arrive as plain objects or base types,
and without the metadata they came back as bare IInspectable objects:

- The incremental updater couldn't read element tags or recognize plain text
  runs, so every update rebuilt the whole card instead of patching it. The
  methods that read tags, text blocks, images, and runs now keep that metadata
  with DynamicDependency.
- Text styles and container borders resolved only because other preserved
  types happen to pull in Style and Border. Without them the line chart legend
  threw InvalidCastException. The chart text styles and the container
  decorator now declare those dependencies.
- High contrast colors were read as colors boxed in the resources, which can't
  be unboxed under native AOT, so high contrast cards fell back to fixed
  colors. They're now read with UISettings.UIElementColor: the same system
  colors the SystemColor*Color resources use.

Checked with a native AOT build of the card harness: every card renders in
both themes and updates in place, as in the JIT build.
… something

Plugged in and fully charged, the battery is idle, but its report still gives
small readings that come and go, such as a 1.1 W discharge. The card showed
them as "Discharge rate" next to "Not discharging", and the row appearing and
disappearing rebuilt the card every few seconds.

The card now shows a charge rate only while charging and a discharge rate only
on battery power.
The chart renderers and the Performance Monitor cards used properties that the
Adaptive Cards schema doesn't define, so the cards weren't portable and failed
strict schema validation: fill, curve, style, minHeight, and valueFormat on
Chart.Line; valueFormat on Chart.VerticalBar; yMin, yMax, showBarValues, and
valueFormat on Chart.HorizontalBar; and color on Chart.Gauge. Line history was
padded with null samples, which the schema's numeric y doesn't allow, and two
progress bars used a chart color.

The renderers now read only the properties on each element's page of the
element reference, with its defaults:
- Titles show only with showTitle, legends show by default, and gauges draw
  their needle unless showNeedle is false.
- Chart.HorizontalBar supports displayMode. ProgressBar colors are accent,
  good, warning, or attention, and badges are circular by default.
- Line chart values are objects, and a missing y is 0.
- What used to need extra properties is now how charts render: lines are
  smooth and filled, and a line chart narrower than 400 pixels draws as a
  sparkline.

The Performance Monitor cards follow: history charts send only real samples,
top processes are rows of text and progress bars, and the battery gauge uses
segments. The Samples page and the author docs list only schema properties.

Checked every element of the expanded cards against the element reference:
1,538 elements with no problems, where the cards before this change had 669.
@github-actions github-actions Bot added the Product-Command Palette Refers to the Command Palette utility label Oct 8, 2026
@michaeljolley

Copy link
Copy Markdown
Contributor

This is beautiful

@daverayment

Copy link
Copy Markdown
Collaborator

Whoa!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review generated with .github/prompts/review-pr.prompt.md (Copilot CLI).

Full review of all 118 files at 6ef65d69ed. No high-severity issues; the incremental patching of chart elements, host-config refresh, template bindings/resources, and the new Performance Monitor data readers check out.
Findings: 0 high, 1 medium, 2 low (inline below).

  • Medium: high contrast collapses every chart series/slice/segment to the same system color.
  • Low: unsupported Icon names render nothing and ignore fallback (docs say to rely on it); the skill reference's accent-color default doesn't match the code.

Info (no action needed): the new host config also changes padding/spacing/separator thickness for every extension card (AdaptiveHostConfigJson.cs:18-29); K/M/B/T axis suffixes are hard-coded; the PR could follow the split the description proposes.

@michaeljolley

Copy link
Copy Markdown
Contributor

Jiří Polášek (@jiripolasek) I know you've worked one something similar. Input?

- In high contrast, data colors cycle by index through the system Highlight,
  Hotlight, and WindowText colors instead of using Highlight for every item,
  and line series alternate solid, dashed, and dotted strokes.
- Docs: uncolored items take colors from colorSet (categorical by default),
  and unsupported Icon names render nothing in Command Palette; the fallback
  applies only in hosts without Icon support.

@zadjii-msft Mike Griese (zadjii-msft) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocking as discussed in teams. Can't accept a PR of this size, no sir-ee

@crutkas
Clint Rutkas (crutkas) marked this pull request as draft October 12, 2026 16:30
Clint Rutkas (crutkas) added a commit that referenced this pull request Oct 12, 2026
Redraw the Memory card with the native Adaptive Cards elements from
the layers below: memory in use and available, a 60-second Chart.Line
history, and a stacked bar that splits memory into in use, modified,
standby, and free, as Task Manager does. Tiles show committed, cached,
paged pool, and non-paged pool memory.

The card also shows the memory hardware, as Task Manager's memory page
does: speed, slots used, and form factor from the SMBIOS memory
devices, and hardware reserved memory from the installed memory. They
are read once, since they don't change while Windows runs.

Layer 6 of 13 in a stack that splits #51125.
Clint Rutkas (crutkas) added a commit that referenced this pull request Oct 12, 2026
Redraw the Disk card with the native Adaptive Cards elements from the
layers below: active time, response time, and read and write speeds at
the top, a 60-second Chart.Line history of the read and write rates,
and the disk's name and type, such as Disk 0 (C:) and SSD (NVMe), as
Task Manager's disk page shows them. Each volume on the disk gets a
capacity bar that turns to warning at 85% full and attention at 95%.

DiskStats now keeps one-second histories of active time and the read
and write rates in SampleHistory, which the Network card will share,
and reads the average response time from the Avg. Disk sec/Transfer
counter. The disk type comes from a device property query that needs
no elevation, read once per disk. The list item now names the disk as
the card does: Disk 0 (C:) instead of Disk (0 C:).

Layer 8 of 13 in a stack that splits #51125.
Clint Rutkas (crutkas) added a commit that referenced this pull request Oct 12, 2026
Adds the Chart.Gauge, Chart.Donut, and Chart.Pie elements to the
Adaptive Cards polyfills library. The WinUI 3 renderer doesn't support
them yet.

- A gauge fills its arc up to the value, in the color of the segment
  that the value falls in, and draws the segments as a thin scale
  inside it. It can show a needle, min and max labels, and a legend,
  and its value as a percentage or a fraction.
- Donut and pie charts draw a slice for each data point, with a legend
  of each slice's share. A donut can show a value in its center.
- Untitled charts get the accessible name "Gauge", "Donut chart", or
  "Pie chart", from three new strings in Resources.resw. A gauge uses
  its sub label first.

Layer 10 of 13 in a stack that splits #51125.
@crutkas

Copy link
Copy Markdown
Member Author

Split into smaller PRs so each piece can be reviewed on its own.

Independent, off main (merge in any order):

Stack #51223, merging bottom to top:

  1. CmdPal: Update custom card elements in place, including in release builds #51204 Incremental updater fix
  2. CmdPal: Add an Adaptive Cards polyfills library with native Chart.Line #51208 Polyfills library with Chart.Line
  3. CmdPal: Render Adaptive Cards ProgressBar, Badge, Icon, and rounded tiles #51209 ProgressBar, Badge, Icon, and rounded tiles
  4. CmdPal: Render Adaptive Cards bar charts natively #51210 Bar charts
  5. CmdPal: Redesign the Performance Monitor CPU card #51211 CPU card
  6. CmdPal: Redesign the Performance Monitor Memory card #51212 Memory card
  7. CmdPal: Redesign the Performance Monitor GPU card #51214 GPU card
  8. CmdPal: Redesign the Performance Monitor Disk card #51215 Disk card
  9. CmdPal: Redesign the Performance Monitor Network card #51218 Network card
  10. CmdPal: Render Adaptive Cards gauge, donut, and pie charts natively #51219 Gauge, donut, and pie charts
  11. CmdPal: Redesign the Performance Monitor Battery card #51220 Battery card
  12. CmdPal: Add a Performance Monitor Overview card and dock band #51221 Overview card and dock band
  13. CmdPal: Add a Charts and visuals sample page and author docs #51222 Samples page and author docs

Together they match this PR, plus fixes made while splitting it, where a card disagreed with Task Manager: CPU base speed, cached memory, GPU utilization, disk active time, network link speed, and bit rates in decimal units. Each PR describes its fix. The author docs also got corrections where they described behavior the code doesn't have.

Clint Rutkas (crutkas) added a commit that referenced this pull request Oct 12, 2026
Corrects five claims in charts-and-visuals.md that didn't match the
polyfills code, checked against the code and in the local card harness:

- A line chart draws as a sparkline only when it's narrower than 400
  pixels. The Tiles example had one tile that spans the card, which
  draws in full; it now has three tiles in a row, which draw
  sparklines.
- Chart.HorizontalBar draws xAxisTitle and yAxisTitle only in the
  default AbsoluteWithAxis mode.
- Without yMin and yMax, the axis of a line or vertical bar chart
  doesn't fit the data: it starts at 0, or lower for negative data,
  and its top rounds up to a grid line.
- Chart.VerticalBar thins its labels so that their centers are at
  least 56 pixels apart, without measuring them, so long labels can
  still overlap.
- On the Samples page, only the line chart, the gauge, and the
  progress bar under it update live. The page's subtitle in the
  Samples list said badges were live too.

Layer 13 of 13 in a stack that splits #51125.
Mike Griese (zadjii-msft) pushed a commit that referenced this pull request Oct 15, 2026
…ilds (#51204)

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

**This PR is layer 1 of 13 in a stack.** The stack divides #51125
(native Adaptive Cards charts and new Performance Monitor cards) into
smaller PRs. Refer to #51125 for the full design. This layer starts from
`main`. It changes only
`Microsoft.CmdPal.AdaptiveCards.IncrementalRendering` and its tests.

This PR corrects two faults in the incremental updater for Adaptive
Cards:

- **Release builds do not update cards in place.** Under native AOT, the
updater cannot read the element tags of the renderer. As a result, each
update replaces the full card.
- **Custom elements cannot update in place.** With this PR, a host can
register custom element types. The controls of these types accept new
data directly. Layer 2 (the chart polyfills library) uses this feature.
Thus, live charts scroll, and the updater does not replace the card each
second.

## Detailed Description of the Pull Request / Additional comments

### The fault in release builds

Release builds compile Command Palette with native AOT.
`.pipelines/v2/release.yml` sets `/p:EnableCmdPalAOT=true`. This
property turns on `PublishAot` for `Microsoft.CmdPal.UI`. CI builds do
not use native AOT. Thus, PR validation does not test this path.

The updater uses element tags to find the controls that it can patch. A
patchable control is a `TextBlock` or `Image` whose `Tag` is an
`ElementTagContent` for an `AdaptiveTextBlock` or `AdaptiveImage`. Under
native AOT, CsWinRT needs type metadata to identify an object that it
receives as `object` or as a base type. No code kept this metadata. As a
result, element tags came back as bare `IInspectable` objects. Text runs
came back as `Inline`, not as `Run`. The fingerprint then treated all
text and images as structure, and each update replaced the full card.

The fix adds `[DynamicDependency(DynamicallyAccessedMemberTypes.All,
typeof(...))]` to the methods that read tags and runs. The attribute
keeps the metadata for `ElementTagContent`, `AdaptiveTextBlock`,
`AdaptiveImage`, and `Run`. I found this fault in #51125 with a native
AOT build of a local card harness. The Performance Monitor cards in
`main` show the same fault (refer to Validation).

### Patches for custom elements

- `IncrementalPatchableElements` (new) is the list of custom element
types that the updater can patch. `Add(type, rendersItself)` is for a
type whose renderer sometimes shows the `fallback`.
- `IIncrementalAdaptiveElementControl` (new) is the interface for the
control of the element. The control gives a deterministic
`IncrementalState`. First, the updater calls `CanApplyIncrementalState`
on all changed controls. Then it calls `ApplyIncrementalState`.
- `IncrementalAdaptiveCardUpdater` gets the registration through a new
optional constructor parameter. Existing callers, for example
`ContentFormControl`, do not change. Without a registration, the
behavior does not change, except for the AOT fix.
- `AdaptiveCardSemanticFingerprint` does not include the data of a
registered element. Thus, a data change patches the control and does not
replace the card. A change to a host-owned property (`id`, `isVisible`,
`spacing`, `height`, or the actions) still replaces the card.
- Fallbacks: A registered element that renders itself never shows its
`fallback`. Thus, the updater ignores changes in that fallback, unless
the element has `requires`. If an element shows its fallback, the
updater cannot patch a fallback root that is a `TextBlock` or `Image`.
The updater can patch text in a fallback container.
- `README.md` tells how to register and implement a patchable element.
The examples use `Chart.Line` and `Icon`, which layers 2 and 3 add.

No code in Command Palette registers a patchable element yet. Layer 2
does this. The UI does not change, so this PR has no screenshots.
Mike Griese (zadjii-msft) pushed a commit that referenced this pull request Oct 15, 2026
Adds a "Charts and visuals" page to the Samples extension. It shows
every element that the Adaptive Cards polyfills render natively, each
with a fallback for other hosts: a line chart, a gauge, donut and pie
charts, and vertical, horizontal, and stacked bar charts in rounded,
bordered tiles, followed by progress bars, badges, and icons. The line
chart, the gauge, and the progress bar under it update every second.

For extension authors, the template's add-adaptive-card-form skill now
covers charts, and its new references/charts-and-visuals.md describes
each element: its properties, colors, how to bind and update live data,
and what Command Palette doesn't support yet. The polyfills README
points authors to both, and its steps for adding an element now end
with documenting it and adding it to the Samples extension.

Layer 13 of 13 in a stack that splits #51125.
Mike Griese (zadjii-msft) pushed a commit that referenced this pull request Oct 15, 2026
Corrects five claims in charts-and-visuals.md that didn't match the
polyfills code, checked against the code and in the local card harness:

- A line chart draws as a sparkline only when it's narrower than 400
  pixels. The Tiles example had one tile that spans the card, which
  draws in full; it now has three tiles in a row, which draw
  sparklines.
- Chart.HorizontalBar draws xAxisTitle and yAxisTitle only in the
  default AbsoluteWithAxis mode.
- Without yMin and yMax, the axis of a line or vertical bar chart
  doesn't fit the data: it starts at 0, or lower for negative data,
  and its top rounds up to a grid line.
- Chart.VerticalBar thins its labels so that their centers are at
  least 56 pixels apart, without measuring them, so long labels can
  still overlap.
- On the Samples page, only the line chart, the gauge, and the
  progress bar under it update live. The page's subtitle in the
  Samples list said badges were live too.

Layer 13 of 13 in a stack that splits #51125.
Boliang Zhang (LegendaryBlair) pushed a commit that referenced this pull request Oct 16, 2026
…ilds (#51204)

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

**This PR is layer 1 of 13 in a stack.** The stack divides #51125
(native Adaptive Cards charts and new Performance Monitor cards) into
smaller PRs. Refer to #51125 for the full design. This layer starts from
`main`. It changes only
`Microsoft.CmdPal.AdaptiveCards.IncrementalRendering` and its tests.

This PR corrects two faults in the incremental updater for Adaptive
Cards:

- **Release builds do not update cards in place.** Under native AOT, the
updater cannot read the element tags of the renderer. As a result, each
update replaces the full card.
- **Custom elements cannot update in place.** With this PR, a host can
register custom element types. The controls of these types accept new
data directly. Layer 2 (the chart polyfills library) uses this feature.
Thus, live charts scroll, and the updater does not replace the card each
second.

## Detailed Description of the Pull Request / Additional comments

### The fault in release builds

Release builds compile Command Palette with native AOT.
`.pipelines/v2/release.yml` sets `/p:EnableCmdPalAOT=true`. This
property turns on `PublishAot` for `Microsoft.CmdPal.UI`. CI builds do
not use native AOT. Thus, PR validation does not test this path.

The updater uses element tags to find the controls that it can patch. A
patchable control is a `TextBlock` or `Image` whose `Tag` is an
`ElementTagContent` for an `AdaptiveTextBlock` or `AdaptiveImage`. Under
native AOT, CsWinRT needs type metadata to identify an object that it
receives as `object` or as a base type. No code kept this metadata. As a
result, element tags came back as bare `IInspectable` objects. Text runs
came back as `Inline`, not as `Run`. The fingerprint then treated all
text and images as structure, and each update replaced the full card.

The fix adds `[DynamicDependency(DynamicallyAccessedMemberTypes.All,
typeof(...))]` to the methods that read tags and runs. The attribute
keeps the metadata for `ElementTagContent`, `AdaptiveTextBlock`,
`AdaptiveImage`, and `Run`. I found this fault in #51125 with a native
AOT build of a local card harness. The Performance Monitor cards in
`main` show the same fault (refer to Validation).

### Patches for custom elements

- `IncrementalPatchableElements` (new) is the list of custom element
types that the updater can patch. `Add(type, rendersItself)` is for a
type whose renderer sometimes shows the `fallback`.
- `IIncrementalAdaptiveElementControl` (new) is the interface for the
control of the element. The control gives a deterministic
`IncrementalState`. First, the updater calls `CanApplyIncrementalState`
on all changed controls. Then it calls `ApplyIncrementalState`.
- `IncrementalAdaptiveCardUpdater` gets the registration through a new
optional constructor parameter. Existing callers, for example
`ContentFormControl`, do not change. Without a registration, the
behavior does not change, except for the AOT fix.
- `AdaptiveCardSemanticFingerprint` does not include the data of a
registered element. Thus, a data change patches the control and does not
replace the card. A change to a host-owned property (`id`, `isVisible`,
`spacing`, `height`, or the actions) still replaces the card.
- Fallbacks: A registered element that renders itself never shows its
`fallback`. Thus, the updater ignores changes in that fallback, unless
the element has `requires`. If an element shows its fallback, the
updater cannot patch a fallback root that is a `TextBlock` or `Image`.
The updater can patch text in a fallback container.
- `README.md` tells how to register and implement a patchable element.
The examples use `Chart.Line` and `Icon`, which layers 2 and 3 add.

No code in Command Palette registers a patchable element yet. Layer 2
does this. The UI does not change, so this PR has no screenshots.

(cherry picked from commit 28acb1b)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Clint Rutkas (crutkas) added a commit that referenced this pull request Oct 28, 2026
…ames (#51206)

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Independent PR split out of #51125, which redesigns the Performance
Monitor cards; see it for the full picture. This PR can merge in any
order with the rest of that split.

It fixes two Performance Monitor bugs on `main`:

- **A metric shown in two places records its history at double speed.**
For example, with the Memory dock band pinned and the Performance
Monitor page open, two one-second timers each add a point to the same
chart history, so the chart fills twice as fast and covers half the time
it should. Now every metric (CPU, memory, network, disk, GPU, and
battery) gets one sample per second, however many places show it.
- **Some GPU names make the dock label too long.** Some drivers append
details in parentheses: `NVIDIA RTX Spark N1X (6144-core Blackwell RTX
GPU)` showed as `RTX Spark N1X (6144-core Blackwell RTX GPU)`. It now
shows as `RTX Spark N1X`.

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] Closes: N/A. Split out of #51125.
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized (no
new strings)
- [ ] **Dev docs:** Added/updated (N/A)
- [ ] **New binaries:** Added on the required places (N/A: no new
binaries or projects)
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx (N/A)

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

### Double-speed histories

On `main`, `PerformanceMonitorCommandsProvider` creates the main page,
the combined dock band, and a dock band for each metric. Each is a
`PerformanceWidgetsPage` with its own `SystemXxxUsageWidgetPage` for
each metric it shows, and each of those has its own `DataManager` with a
one-second timer that runs while the page or band is shown. Every
`DataManager` samples the same `SystemData.Shared` stats, and for CPU,
memory, network, disk, and GPU, each sample appends a point to the
shared chart history (`ChartHelper.AddNextChartValue`). So each extra
place that shows a metric adds another point per second.

`DataManager.ShouldSample` records when each stats object was last
sampled, in a `ConditionalWeakTable` keyed by the stats object, and
skips the sample if the last one was less than 750 ms ago. The check
runs under the stats lock that each sampler already takes. 750 ms leaves
room for timer jitter: a late tick from the same timer still samples,
but a second timer's tick within the same second doesn't. Every timer
still calls its page's update, so every place keeps showing the latest
values.

All six metrics are gated: CPU, memory, network, disk, GPU, and battery.
Every CPU page on `main` uses `DataType.CPU`, so all CPU timers ask for
the same sample; `includeTopProcesses` and
`DataType.CpuWithTopProcesses` are unchanged.

### Long GPU names

`GpuAdapterNames.GetShortName` removes known branding, such as `NVIDIA`,
`GeForce`, `(R)`, `(TM)`, and a trailing ` GPU`. Nothing removed a
trailing part in parentheses, so it stayed in the label. It's now
dropped before the other rules run, so they see the model name. Names
without one are unchanged.

### Tests

- `DataManagerTests` (new) covers `ShouldSample`: the first sample, a
second timer within the same second, a late tick, and separate schedules
for each stats object.
- `GpuAdapterNamesTests` gets a row for `NVIDIA RTX Spark N1X (6144-core
Blackwell RTX GPU)`.

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed

ARM64, Debug, from the repo root:

- `MSBuild.exe
src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.PerformanceMonitor\Microsoft.CmdPal.Ext.PerformanceMonitor.csproj
-nologo -m -restore -t:Build -v:minimal -p:Configuration=Debug
-p:Platform=ARM64 -p:RuntimeIdentifier=win-arm64 -p:CIBuild=false
-p:GeneratePackageLocally=false -p:GenerateAppxPackageOnBuild=false
-p:PublishAppxPackage=false -p:SkipLongPathsCheck=true`: exit code 0, 0
warnings.
- The same command for
`src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.PerformanceMonitor.UnitTests\Microsoft.CmdPal.Ext.PerformanceMonitor.UnitTests.csproj`:
exit code 0, 0 warnings.
- `vstest.console.arm64.exe
ARM64\Debug\WinUI3Apps\CmdPal\tests\Microsoft.CmdPal.Ext.PerformanceMonitor.UnitTests.dll
/Platform:ARM64`: 103 passed, 0 failed, including the four new
`DataManagerTests` and the new GPU name row.
- With `main`'s `GpuAdapterNames.cs`, the new GPU name row fails:
`Expected:<RTX Spark N1X>. Actual:<RTX Spark N1X (6144-core Blackwell
RTX GPU)>`.
- A throwaway test (not in this PR) reproduced the double-speed history.
It called the samplers of two `DataManager` instances for the same
metric 500 ms apart, once per second each, for 5 seconds, with the real
`MemoryStats` and `CPUStats`:

  | Metric | History points without this PR | With this PR |
  |---|---|---|
  | Memory | 10 | 5 |
  | CPU | 10 | 5 |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Product-Command Palette Refers to the Command Palette utility

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants