Skip to content

Port SettingsCard/Expander from WCT and update SUI to use it#20232

Draft
carlos-zamora wants to merge 9 commits into
mainfrom
dev/cazamor/sui-rejuv/setting-container
Draft

Port SettingsCard/Expander from WCT and update SUI to use it#20232
carlos-zamora wants to merge 9 commits into
mainfrom
dev/cazamor/sui-rejuv/setting-container

Conversation

@carlos-zamora
Copy link
Copy Markdown
Member

@carlos-zamora carlos-zamora commented May 15, 2026

Summary of the Pull Request

Ports the SettingsCard and SettingsExpander from Windows Community Toolkit to the TerminalSettingsEditor project:

In order to upgrade our settings UI to use these new controls, I had the existing SettingContainer act as a wrapper for them. This provided several benefits:

  • it minimized the diff
  • it ensured we don't have to change any of the localized resources
  • the search index is still built the same way as befoer
  • SettingContainer is responsible for adding the infrastructure for the reset button, which is used in profile settings to expose inheritance.

Other notable changes as a part of using the new controls:

  • SettingContainerStyle.xaml: deduplicated some styles so that we can just have a few simple ones
  • Navigators (i.e. "Advanced" button in Profiles page, Extensions page) were also converted to use SettingsCard

Validation Steps Performed

More coming soon

  • settings search should pick up and navigate to settings properly
  • accessibility audit

PR Checklist

Related to #17000

Comment thread src/cascadia/TerminalSettingsEditor/SettingsExpander.cpp Fixed
@github-actions

This comment has been minimized.

@carlos-zamora
Copy link
Copy Markdown
Member Author

UI changes I noticed while poking around:

  • Clicking middle of expander doesn't open anymore
  • Profile > Icon: expander contents are much larger
  • Container height changed 64 px -> 66 px
  • Expander chevron has additional padding to left (against preview value)
  • Profile > Appearance > Color scheme: padding inside expander looks bad
  • Profile > Appearance > "Variable font axes" & "Font features": "+ Add new" button is misaligned

I hit a point where I could go in and make everything look the same as we have it now, but I felt that that mildly contradicted the idea behind trying to make the UI "consistent" by using these controls.

@niels9001 I'll go through and do a second pass fixing the things above. Can you also go through it and point out any inconsistencies with the UI that should be addressed? The main files that are probably of interest are:

  • src/cascadia/TerminalSettingsEditor/SettingsControlsStyle.xaml
  • src/cascadia/TerminalSettingsEditor/SettingContainerStyle.xaml

Once we figure that out and this gets reviewed/merged, we can probably use SettingsCards in #20215.

@niels9001
Copy link
Copy Markdown
Contributor

UI changes I noticed while poking around:

  • Clicking middle of expander doesn't open anymore
  • Profile > Icon: expander contents are much larger
  • Container height changed 64 px -> 66 px
  • Expander chevron has additional padding to left (against preview value)
  • Profile > Appearance > Color scheme: padding inside expander looks bad
  • Profile > Appearance > "Variable font axes" & "Font features": "+ Add new" button is misaligned

I hit a point where I could go in and make everything look the same as we have it now, but I felt that that mildly contradicted the idea behind trying to make the UI "consistent" by using these controls.

@niels9001 I'll go through and do a second pass fixing the things above. Can you also go through it and point out any inconsistencies with the UI that should be addressed? The main files that are probably of interest are:

  • src/cascadia/TerminalSettingsEditor/SettingsControlsStyle.xaml
  • src/cascadia/TerminalSettingsEditor/SettingContainerStyle.xaml

Once we figure that out and this gets reviewed/merged, we can probably use SettingsCards in #20215.

The issue is that we are now mixing-and-matching SettingsCard/SettingsExpander with SettingsContainer. The Toolkit's settings controls have all visual states and logic built-in: for example, if you host a ToggleSwitch as part of the Content, it will automatically apply the right style to make it right-aligned. Now, we are overriding that style again with a manual style. Therefore, you see a lot of inconsistencies because there are style overrides happening.

How big is the gap between SettingsContainer and the Settings controls? Like, could we deprecate it completely and port over the things that are required to SettingsCard (which gets hosted by the Expander too?

const auto helpText{ HelpText() };

// Forward HelpText into the SettingsCard / SettingsExpander Description
// slot so it renders through the WCT-ported PART_DescriptionPresenter.
Toolkit uses a muxc:AnimatedIcon wrapping AnimatedChevronUpDownSmallVisualSource.
That visual source isn't available in the WinUI 2 build the editor targets, so
we fall back to a static FontIcon and drive a RotateTransform via the
Checked*/unchecked CommonStates Storyboards (DoubleAnimation between 0° and 180°).
@github-actions

This comment has been minimized.

// be shared across cards) and a default string was rendering
// through ContentPresenter -> TextBlock, whose line-height
// padding made the Viewbox-scaled glyph visibly smaller than
// WCT's SymbolIcon default.

void SettingsCard::OnApplyTemplate()
{
// Match WCT's SettingsCard.OnApplyTemplate() which calls base first so the
// Inject the shared implicit ToggleSwitch / Slider / ComboBox / TextBox
// dictionary so child controls in our Content slot get the Windows 11
// settings-page defaults without an explicit Style attribute. Bypasses
// the WCT Setter.Value-with-inline-ResourceDictionary pattern, which
// by C++ GoToState don't reliably engage. The ContentSpacing setter
// targets PART_RootGrid.RowSpacing; set it directly here as well so the
// Vertical / RightWrapped stacked-layout cards actually get the breathing
// room between header and content that WCT shows.
// machine in sync (so _CheckVerticalSpacingState sees the right CurrentState),
// but we *also* apply the layout properties directly to PART_ContentPresenter
// because in WinUI 2, attached-property changes (Grid.Row/Grid.Column) and
// HorizontalAlignment changes inside VisualState.Setters or Storyboards
layout work happens in SettingsCard::_UpdateContentAlignmentState
via direct property writes on PART_ContentPresenter — in WinUI 2,
attached-property changes ((Grid.Row)/(Grid.Column)) inside
VisualState.Setters or Storyboards don't reliably engage when

namespace Microsoft.Terminal.Settings.Editor
{
[contentproperty("Content")]
static Windows.UI.Xaml.ResourceDictionary GetResources(Windows.UI.Xaml.DependencyObject target);
static void SetResources(Windows.UI.Xaml.DependencyObject target, Windows.UI.Xaml.ResourceDictionary value);

// Idempotently merges the project's SettingsControlsImplicitStyles.xaml
@github-actions
Copy link
Copy Markdown

@check-spelling-bot Report

⚠️ Dictionary not found

Problems were encountered retrieving check dictionaries (cspell:cpp/src/compiler-msvc.txt cspell:latex/dict/latex.txt cspell:powershell/dict/powershell.txt cspell:cpp/src/compiler-gcc.txt cspell:sql/src/tsql.txt cspell:lua/dict/lua.txt cspell:node/dict/node.txt cspell:html/dict/html.txt cspell:java/src/java-terms.txt cspell:ada/dict/ada.txt cspell:software-terms/dict/webServices.txt cspell:svelte/dict/svelte.txt cspell:cpp/src/people.txt cspell:k8s/dict/k8s.txt cspell:monkeyc/src/monkeyc_keywords.txt cspell:ruby/dict/ruby.txt cspell:cpp/src/stdlib-cerrno.txt cspell:dart/src/dart.txt cspell:cpp/src/lang-jargon.txt cspell:software-terms/dict/softwareTerms.txt cspell:python/src/python/python.txt cspell:shell/dict/shell-all-words.txt cspell:dotnet/dict/dotnet.txt cspell:cpp/src/stdlib-cpp.txt cspell:r/src/r.txt cspell:swift/src/swift.txt cspell:cpp/src/template-strings.txt cspell:sql/src/sql.txt cspell:python/src/python/python-lib.txt cspell:python/src/additional_words.txt cspell:cpp/src/lang-keywords.txt cspell:css/dict/css.txt cspell:scala/dict/scala.txt cspell:redis/dict/redis.txt cspell:elixir/dict/elixir.txt cspell:java/src/java.txt cspell:cpp/src/stdlib-cmath.txt cspell:public-licenses/src/generated/public-licenses.txt cspell:python/src/common/extra.txt cspell:cpp/src/compiler-clang-attributes.txt cspell:php/dict/php.txt cspell:clojure/src/clojure.txt cspell:cpp/src/ecosystem.txt cspell:golang/dict/go.txt cspell:haskell/dict/haskell.txt cspell:django/dict/django.txt cspell:typescript/dict/typescript.txt cspell:cpp/src/stdlib-c.txt cspell:npm/dict/npm.txt cspell:public-licenses/src/additional-licenses.txt cspell:gaming-terms/dict/gaming-terms.txt cspell:fullstack/dict/fullstack.txt cspell:docker/src/docker-words.txt cspell:rust/dict/rust.txt).

⚠️ For more information, see check-dictionary-not-found.

🔴 Please review

See the 📂 files view, the 📜action log, 👼 SARIF report, or 📝 job summary for details.

Unrecognized words (4)

contentproperty
Idempotently
Storyboards
WCT

These words are not needed and should be removed NODEFAULT notif SND

To accept these unrecognized words as correct and remove the previously acknowledged and now absent words, you could run the following commands

... in a clone of the git@github.com:microsoft/terminal.git repository
on the dev/cazamor/sui-rejuv/setting-container branch (ℹ️ how do I use this?):

curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/cfb6f7e75bbfc89c71eaa30366d0c166f1bd9c8c/apply.pl' |
perl - 'https://github.com/microsoft/terminal/actions/runs/26137443221/attempts/1' &&
git commit -m 'Update check-spelling metadata'
Available 📚 dictionaries could cover words (expected and unrecognized) not in the 📘 dictionary

This includes both expected items (2014) from .github/actions/spelling/expect/alphabet.txt .github/actions/spelling/expect/expect.txt .github/actions/spelling/expect/web.txt and unrecognized words (4)

Dictionary Entries Covers Uniquely
cspell:csharp/csharp.txt 32 2 2
cspell:aws/aws.txt 232 2 2
cspell:fonts/fonts.txt 536 1 1

Consider adding to the extra_dictionaries array (in the .github/actions/spelling/config.json file):

    "cspell:csharp/csharp.txt",
    "cspell:aws/aws.txt",
    "cspell:fonts/fonts.txt",

To stop checking additional dictionaries, put (in the .github/actions/spelling/config.json file):

"check_extra_dictionaries": []
Warnings ⚠️ (1)

See the 📂 files view, the 📜action log, 👼 SARIF report, or 📝 job summary for details.

⚠️ Warnings Count
⚠️ check-dictionary-not-found 54

See ⚠️ Event descriptions for more information.

✏️ Contributor please read this

By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.

If the listed items are:

  • ... misspelled, then please correct them instead of using the command.
  • ... names, please add them to .github/actions/spelling/allow/names.txt.
  • ... APIs, you can add them to a file in .github/actions/spelling/allow/.
  • ... just things you're using, please add them to an appropriate file in .github/actions/spelling/expect/.
  • ... tokens you only need in one place and shouldn't generally be used, you can add an item in an appropriate file in .github/actions/spelling/patterns/.

See the README.md in each directory for more information.

🔬 You can test your commits without appending to a PR by creating a new branch with that extra change and pushing it to your fork. The check-spelling action will run in response to your push -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. 😉

If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants