Skip to content

webview: Add Template Gallery view to webview package#2278

Open
gavin-aguiar wants to merge 10 commits into
microsoft:mainfrom
gavin-aguiar:gaaguiar/templateview
Open

webview: Add Template Gallery view to webview package#2278
gavin-aguiar wants to merge 10 commits into
microsoft:mainfrom
gavin-aguiar:gaaguiar/templateview

Conversation

@gavin-aguiar
Copy link
Copy Markdown

@gavin-aguiar gavin-aguiar commented May 6, 2026

Summary

Adds a Template Gallery webview to @microsoft/vscode-azext-webview, enabling Azure extensions to share a common template browsing and project creation UI.

Architecture

  • TemplateGalleryController — Abstract class extending WebviewBaseController<TemplateGalleryConfig>. Consumers subclass and implement:
    • fetchTemplates() — fetch from their manifest
    • createProject() — scaffold the project
    • getReadme() — fetch template README
    • Optional overrides: generateWithCopilot(), createAiProject(), continueInChat(), fetchCachedTemplates()
  • TemplateGalleryConfig — Initial data passed to the webview; controls header copy, AI tab visibility, display-name maps, language filter mapping, and filter ordering (languageOrder, categoryOrder, resourceOrder).
  • React ContextTemplateGalleryConfigProvider merges extension-provided config with package defaults, accessed via useTemplateGalleryConfig() hook.
  • Bundle resolutionWebviewBaseController now falls back to ext.webviewAssetsDir (set via registerWebviewExtensionVariables) before the node_modules path, so bundled VSIXs that ship views.js/views.css in their own dist/ folder work without each controller passing a WebviewBundleLocation.

Changes

New files

File Purpose
src/extension/TemplateGalleryController.ts Abstract controller, message routing, lifecycle
src/webview/TemplateGallery/TemplateGalleryView.tsx Main React component, state management, view routing
src/webview/TemplateGallery/TemplateGalleryConfigContext.tsx React context merging extension config with defaults
src/webview/TemplateGallery/types.ts Shared types, message contracts, default display maps and orders
src/webview/TemplateGallery/components/FilterBar.tsx Language / use case / resource filters
src/webview/TemplateGallery/components/TemplateCard.tsx Card with split click targets (details vs. create)
src/webview/TemplateGallery/components/TemplateConfigView.tsx "Template Details" view — README, language/location form
src/webview/TemplateGallery/components/AiGenerateView.tsx Copilot-driven AI generation tab
src/webview/TemplateGallery/components/CreatingView.tsx "Creating project…" progress
src/webview/TemplateGallery/utils/renderMarkdown.ts Lightweight markdown → HTML renderer for README preview
src/webview/styles/templateGalleryView.scss Full gallery styling, including VS Code language colors

Modified files

File Change
src/index.ts Exports TemplateGalleryController, types, plus WebviewBaseController / WebviewController / WebviewBundleLocation
src/webview/WebviewRegistry.ts Adds templateGalleryView to the registry
src/extension/WebviewBaseController.ts getDocumentTemplate() falls back to ext.webviewAssetsDir before the node_modules path

Consumption example

import { TemplateGalleryController, type TemplateGalleryConfig, type IProjectTemplate } from '@microsoft/vscode-azext-webview';

class MyTemplateGalleryController extends TemplateGalleryController {
    public static createOrShow(context: vscode.ExtensionContext) {
        const config: TemplateGalleryConfig = {
            serviceName: 'My Service',
            headerTitle: 'Create a new My Service project',
            headerSubtitle: 'Pick a template to get started',
            supportsAiGeneration: true,
            // Optional ordering overrides:
            categoryOrder: ['starter', 'web-apis', /* ... */],
            resourceOrder: ['http', 'timer', /* ... */],
        };
        return new MyTemplateGalleryController(context, config);
    }

    protected async fetchTemplates() {
        // Fetch from your manifest, return { templates, defaultLocation }
    }

    protected async createProject(template: IProjectTemplate, language: string, location: string) {
        // Scaffold the project on disk
    }

    protected async getReadme(template: IProjectTemplate) {
        // Return the README markdown for the selected template
    }
}

Testing

  • npm run build — all four targets pass (esm, cjs, assets, webview bundle)
  • npm run lint — clean (0 errors, 0 warnings)

Screenshots

  1. **Create New Project View
image
  1. Gallery — Browse mode (default view)
    Shows the language / use case / resource filter chips with their colored borders, and the template grid with two-color cards (Featured + Explore More sections).
image
  1. Template Details view
    Click into any template card. Shows the new "Template Details" heading, the selected-template card on the left, the language dropdown / location input / "What's included" / Create Project button, and the README preview on the right.
image
  1. README opened after creation
    After a successful create, capture the README markdown preview opening in the editor pane (replacing the gallery webview).
image

Copilot AI review requested due to automatic review settings May 6, 2026 17:08
@motm32
Copy link
Copy Markdown
Contributor

motm32 commented May 6, 2026

Thanks for putting up this PR! A couple of things I noticed:

  • It seems you created most of the components for this new view. In order to stay accessibility compliant if you can utilize fluent UI components that would be great. You can take a look at the ConfirmationView for how those are used and here is a link to the component gallery they have: https://developer.microsoft.com/en-us/fluentui#/controls/web/button
  • I noticed a couple of the Github Actions are failing if you could go through and fix those issues before I do a more thorough review that would be great!

@gavin-aguiar gavin-aguiar marked this pull request as ready for review May 7, 2026 18:21
@gavin-aguiar gavin-aguiar requested a review from a team as a code owner May 7, 2026 18:21
@gavin-aguiar
Copy link
Copy Markdown
Author

Thanks for putting up this PR! A couple of things I noticed:

  • It seems you created most of the components for this new view. In order to stay accessibility compliant if you can utilize fluent UI components that would be great. You can take a look at the ConfirmationView for how those are used and here is a link to the component gallery they have: https://developer.microsoft.com/en-us/fluentui#/controls/web/button
  • I noticed a couple of the Github Actions are failing if you could go through and fix those issues before I do a more thorough review that would be great!

@motm32 that a good call. I refactored the components to use the Fluent UI. Also fixed the linting errors.

@motm32 motm32 changed the title Add Template Gallery view to webview package webview: Add Template Gallery view to webview package May 12, 2026
@motm32
Copy link
Copy Markdown
Contributor

motm32 commented May 14, 2026

Just some intial UI design feedback I had while testing:

Generate with copilot tab:

  • The examples are just floating text maybe consider making them look more like buttons since they are clickable items. I also find it a bit confusing to have the examples right above the generate button maybe consider moving them either to the top of the view or at the very bottom.
  • Maybe remove one of the titles from this section of the tab:
    image Just having the description is probably enough within this.
  • We normally put submit buttons on the far right of a screen maybe move the "Generate Project" button over to the right so it doesn't get lost in the view
  • For the "What can copilot chat do" section we usually keep that type of information under a question mark button toward the top right corner of pages.
  • For the continue in copilot chat to me it makes more sense to have the generate and continue be right next to each other as primary and secondary buttons. Otherwise people may miss that option if they aren't scrolling down the whole page.

Template Gallery tab:

  • The sizing doesn't seem to be set properly for the buttons for each template:
image - I would probably put the refresh somewhere closer to the top on a sticky tab so it is easier to access when scrolling down - The color coding language tabs look nice but depending on the theme it could be really hard to see the different colors and I could see there possibly being some accessibility issues with this.

@nturinski nturinski requested review from Copilot and removed request for Copilot May 14, 2026 18:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 8 comments.

Comment thread webview/src/webview/TemplateGallery/components/AiGenerateView.tsx Outdated
Comment thread webview/src/webview/TemplateGallery/components/AiGenerateView.tsx Outdated
Comment thread webview/src/extension/TemplateGalleryController.ts
Comment thread webview/src/webview/TemplateGallery/TemplateGalleryView.tsx Outdated
Comment thread webview/src/webview/TemplateGallery/components/AiGenerateView.tsx Outdated
Comment thread webview/src/webview/TemplateGallery/utils/renderMarkdown.ts
Comment on lines +123 to +124
if (!this.isDisposed) {
void this._panel.webview.postMessage(message);
Comment thread webview/src/webview/TemplateGallery/components/AiGenerateView.tsx Outdated
@gavin-aguiar
Copy link
Copy Markdown
Author

Just some intial UI design feedback I had while testing:

Generate with copilot tab:

  • The examples are just floating text maybe consider making them look more like buttons since they are clickable items. I also find it a bit confusing to have the examples right above the generate button maybe consider moving them either to the top of the view or at the very bottom.
  • Maybe remove one of the titles from this section of the tab:
    image Just having the description is probably enough within this.
  • We normally put submit buttons on the far right of a screen maybe move the "Generate Project" button over to the right so it doesn't get lost in the view
  • For the "What can copilot chat do" section we usually keep that type of information under a question mark button toward the top right corner of pages.
  • For the continue in copilot chat to me it makes more sense to have the generate and continue be right next to each other as primary and secondary buttons. Otherwise people may miss that option if they aren't scrolling down the whole page.

Template Gallery tab:

  • The sizing doesn't seem to be set properly for the buttons for each template:

image - I would probably put the refresh somewhere closer to the top on a sticky tab so it is easier to access when scrolling down - The color coding language tabs look nice but depending on the theme it could be really hard to see the different colors and I could see there possibly being some accessibility issues with this.

Addressed these comments.

@motm32
Copy link
Copy Markdown
Contributor

motm32 commented May 18, 2026

A couple of things I noticed with the new changes:

  • I am not really sure why we need both a "Generate Project" button and a "Continue in Chat" button. In other places we just open all copilot related things into the chat so that users can iterate if they want. Could we do that here also?
  • Depending on the view size the "Generate Project" button gets moved down to the next line. I would expect it to stay next to the "Continue in Chat" button
testing.mp4
  • It seems a bit unintuitive to have the language button at the bottom of the Generate with Copilot screen. I wonder if it makes more sense to have it before the input box.
  • On the Browse template page the color coded language filters still appears. I think this will cause some accessibility issues because with certain themes you cannot see the coloring.

@gavin-aguiar
Copy link
Copy Markdown
Author

  • I am not really sure why we need both a "Generate Project" button and a "Continue in Chat" button. In other places we just open all copilot related things into the chat so that users can iterate if they want. Could we do that here also?

I am not really sure why we need both a "Generate Project" button and a "Continue in Chat" button. In other places we just open all copilot related things into the chat so that users can iterate if they want. Could we do that here also?

The main reason for having 2 different options (Generate Project and Continue in Chat) is that if a function app is simple enough, we don't need to chat with the agent/llm. From my testing, the Generate Button gives good results. Only for more complicated apps when the function app might be too large to generate in a single prompt and more conversation with the agent is needed, the "Continue in Copilot chat" is useful.

Depending on the view size the "Generate Project" button gets moved down to the next line. I would expect it to stay next to the "Continue in Chat" button

I'll fix this.

It seems a bit unintuitive to have the language button at the bottom of the Generate with Copilot screen. I wonder if it makes more sense to have it before the input box

The language is a dropdown where the users can choose the language of the function app based on the prompt. IMO putting it after the prompt and before the generate button makes sense since that is the order one would go through before creating a function app.

On the Browse template page the color coded language filters still appears. I think this will cause some accessibility issues because with certain themes you cannot see the coloring.

I did still keep the language color coding since it before more intuitive. If it does cause some accessibility issues, I'll change it. But for now I think keeping it color coded gives it a nicer view.


// ── Actions ──


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.

Remove extra lines

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants