Skip to content

[CmdPal] Add tabbed pages to Command Palette#49429

Open
michaeljolley wants to merge 4 commits into
mainfrom
dev/mjolley/cmdpal-tabbed-page
Open

[CmdPal] Add tabbed pages to Command Palette#49429
michaeljolley wants to merge 4 commits into
mainfrom
dev/mjolley/cmdpal-tabbed-page

Conversation

@michaeljolley

@michaeljolley michaeljolley commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a new Tabbed Pages capability to Command Palette. An extension can expose an ITabbedPage that renders as a strip of tabs, where each tab is its own independent IPage-derived page (list, dynamic list, or content page). For example, a GitHub extension could surface Issues, Pull Requests, and a Readme as separate tabs, each backed by whatever page type fits that content.

What's included

SDK (Microsoft.CommandPalette.Extensions)

  • New ITab and ITabbedPage interfaces in the IDL.

Toolkit (Microsoft.CommandPalette.Extensions.Toolkit)

  • Tab and TabbedPage helper base classes. TabbedPage also implements IContentPage so older hosts that don't understand tabbed pages render a static "please update Command Palette" message instead of nothing.

Host (Microsoft.CmdPal.UI / Microsoft.CmdPal.UI.ViewModels)

  • TabViewModel (per-tab title / icon / badge) and TabbedPageViewModel (host view model).
  • TabbedPage.xaml host view with a pivot-underline tab strip, a per-tab progress bar placed under the tabs, and an inner frame that hosts the active tab's page.
  • Factory routing, ShellPage navigation, and keyboard cycling between tabs.
  • Tab pages are lazily materialized on first activation and cached; the first tab is the default.
  • Badges can lazy-load and update after the first tab is active.
  • The shared search box activates/deactivates to follow the active tab (e.g. a ListPage/DynamicListPage tab enables it; a content tab disables it).

Sample & tests

  • SampleTabbedPage in the SamplePages extension (Issues / Pull Requests / Readme, with async badge counts), registered in the samples list.
  • Unit tests for the Toolkit types and the host view model (tab building, lazy child creation, unsupported-page placeholder, badge propagation, search forwarding, dynamic tab-set updates, and search-box-follows-active-tab).

Notes

  • Feature is additive; no existing IPC/JSON contracts changed.
  • v1 scope: tabs are list / dynamic list / content pages. Nested tabbed pages are out of scope.

Videos? Videos!

Screen.Recording.2026-07-20.233940.mp4

michaeljolley and others added 3 commits July 15, 2026 21:40
Introduce an additive TabbedPage container for Command Palette. An
extension can expose an ITabbedPage that renders a strip of tabs, where
each tab is its own independent IPage (list, dynamic list or content
page in v1) with its own title, optional icon and an observable count
badge.

SDK (additive, ExtensionsContract v1):
- New ITab and ITabbedPage interfaces in the IDL.
- Toolkit Tab and TabbedPage helpers. TabbedPage implements both
  ITabbedPage and IContentPage so older hosts fall back to an
  overridable "update Command Palette" message.

Host:
- TabViewModel and TabbedPageViewModel: lazy per-tab child creation and
  caching, shared search forwarded to the active tab, observable badges,
  dynamic tab sets that preserve the active tab by id, and per-tab
  loading state.
- Factory routes ITabbedPage before IContentPage.
- TabbedPage view: tab strip, per-tab progress bar under the strip,
  inner frame reusing existing page views, Ctrl+Tab / Ctrl+Shift+Tab
  cycling, and an unsupported-tab placeholder.

Tests and sample:
- Toolkit and view model unit tests.
- A sample tabbed page in the SamplePages extension with async badges.

Co-authored-by: Copilot App <[email protected]>
Copilot-Session: de7af6c2-3f22-4b85-ba1c-e45bf0361f1a
…ve tab

Reworks the TabbedPage tab strip into a pivot-underline header: the
selected-tab accent color fills the whole tab area, selection no longer
changes a tab's background, the selected indicator moved from the left
edge to a bottom underline, the selected tab label is bold, and inactive
labels use the secondary (subtitle/placeholder) foreground.

Also makes the shared search box activate or deactivate based on the
active tab instead of a static "any tab is searchable" value. HasSearchBox
now reflects the active tab's page type (list, dynamic list or
parameters), is re-raised on every tab switch so the shell re-evaluates
search-box visibility, and follows a child that revises its searchability
after async init. Tests updated to cover the active-tab semantics and a
tab-switch transition.

Co-authored-by: Copilot App <[email protected]>
Copilot-Session: de7af6c2-3f22-4b85-ba1c-e45bf0361f1a
Gives the tab strip a distinct layered background with a bottom divider so
it reads as a header band, sets the inactive (Normal) tab label to the
secondary foreground via a visual state, and adds a small top margin above
the active tab content.

Co-authored-by: Copilot App <[email protected]>
Copilot-Session: de7af6c2-3f22-4b85-ba1c-e45bf0361f1a
@github-actions github-actions Bot added the Product-Command Palette Refers to the Command Palette utility label Jul 21, 2026
The shell SearchBar only renders a typeable text box for a concrete list or parameters page, keyed on its CurrentPageViewModel. It was bound to the tabbed page container, which matched no case, so no text box ever appeared and users could not search a list/dynamic-list tab.

Add ShellViewModel.SearchHostPage, which sees through a TabbedPageViewModel to its active child, and point the SearchBar and FiltersDropDown at it. SearchHostPage is re-raised on tab switch (ActiveChild change) and on page navigation, so the text box and filters follow the active tab.

Co-authored-by: Copilot App <[email protected]>

Copilot-Session: de7af6c2-3f22-4b85-ba1c-e45bf0361f1a
@michaeljolley michaeljolley changed the title [CmdPal] Add tabbed pages (ITabbedPage) to Command Palette [CmdPal] Add tabbed pages to Command Palette Jul 21, 2026
@michaeljolley
michaeljolley requested review from jiripolasek and zadjii-msft and removed request for jiripolasek July 21, 2026 15:17
@michaeljolley
michaeljolley marked this pull request as ready for review July 21, 2026 15:17
@michaeljolley michaeljolley self-assigned this Jul 21, 2026

@Jay-o-Way Jay-o-Way left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks like you created a lot from scratch. Was there no more existing controls to use? Just thinking...


<Page.Resources>
<ResourceDictionary>
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You don't need this in WinUI (3)

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

Labels

0.102 Product-Command Palette Refers to the Command Palette utility

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants