@@ -68,168 +68,45 @@ are close to shutting down.
6868
6969## Webviews
7070
71- The extension uses React-based webviews for rich UI panels. Webviews are built
72- with Vite and live in ` packages/ ` as a pnpm workspace .
71+ The extension uses React-based webviews for rich UI panels, built with Vite and
72+ organized as a pnpm workspace in ` packages/ ` .
7373
7474### Project Structure
7575
7676``` text
7777packages/
78- ├── shared/ # Shared utilities and config
79- │ ├── src/
80- │ │ ├── index.ts # WebviewMessage type
81- │ │ └── react/ # VS Code API hooks
82- │ │ ├── api.ts # postMessage, getState, setState
83- │ │ └── hooks.ts # useMessage, useVsCodeState
84- │ ├── tsconfig.json
85- │ ├── tsconfig.webview.json # Base tsconfig for all webviews
86- │ └── vite.config.base.ts # Shared Vite config factory
87- └── tasks/ # Task panel webview
88- ├── src/
89- │ ├── index.tsx # Entry point
90- │ └── App.tsx # Root component
91- ├── package.json
92- ├── tsconfig.json # Extends ../shared/tsconfig.webview.json
93- └── vite.config.ts # Uses createWebviewConfig from shared
78+ ├── shared/ # Shared types, React hooks, and Vite config
79+ │ └── extension.d.ts # Types exposed to extension (excludes React)
80+ └── tasks/ # Example webview (copy this for new webviews)
9481
9582src/webviews/
96- ├── util.ts # getWebviewHtml() - generates HTML with CSP
97- └── tasks/
98- └── TasksPanel.ts # WebviewViewProvider implementation
83+ ├── util.ts # getWebviewHtml() helper
84+ └── tasks/ # Extension-side provider for tasks panel
9985```
10086
101- ### How It Works
87+ Key patterns:
10288
103- ** Extension side** (` src/webviews/ ` ):
104-
105- - Implements ` WebviewViewProvider ` to create the panel
106- - Uses ` getWebviewHtml() ` to generate secure HTML with nonce-based CSP
107- - Communicates via ` webview.postMessage() ` and ` onDidReceiveMessage `
108-
109- ** React side** (` packages/ ` ):
110-
111- - Uses ` @coder/shared/react ` hooks for message passing
112- - ` postMessage() ` sends messages to the extension
113- - ` useMessage() ` listens for messages from the extension
114- - ` useVsCodeState() ` persists state across panel visibility changes
89+ - ** Type sharing** : Extension imports types from ` @coder/shared ` via path mapping
90+ to ` extension.d.ts ` . Webviews import directly from ` @coder/shared/react ` .
91+ - ** Message passing** : Use ` postMessage() ` /` useMessage() ` hooks for communication.
92+ - ** Lifecycle** : Dispose event listeners properly (see ` TasksPanel.ts ` for example).
11593
11694### Development
11795
118- Run these in separate terminals:
119-
12096``` bash
12197pnpm watch # Rebuild extension on changes
122- pnpm dev:webviews # Rebuild webviews on changes
98+ pnpm dev:webviews # Rebuild webviews on changes (run in separate terminal)
12399```
124100
125- Then press F5 to launch the Extension Development Host. When you edit webview
126- code, use "Developer: Reload Webviews" or close/reopen the panel to see updates .
101+ Press F5 to launch the Extension Development Host. Use "Developer: Reload Webviews"
102+ to see webview changes .
127103
128104### Adding a New Webview
129105
130- 1 . ** Create the package:**
131-
132- ``` bash
133- cp -r packages/tasks packages/< name>
134- ```
135-
136- Update ` packages/<name>/package.json ` :
137-
138- ``` json
139- { "name" : " @coder/<name>-webview" }
140- ```
141-
142- Update ` packages/<name>/vite.config.ts ` :
143-
144- ``` typescript
145- import { createWebviewConfig } from " ../shared/vite.config.base" ;
146-
147- export default createWebviewConfig (" <name>" , __dirname );
148- ```
149-
150- 2 . ** Create the provider** in ` src/webviews/<name>/<Name>Panel.ts ` :
151-
152- ``` typescript
153- import * as vscode from " vscode" ;
154- import { getWebviewHtml } from " ../util" ;
155-
156- export class MyPanel implements vscode .WebviewViewProvider {
157- public static readonly viewType = " coder.myPanel" ;
158-
159- constructor (private readonly extensionUri : vscode .Uri ) {}
160-
161- resolveWebviewView(webviewView : vscode .WebviewView ): void {
162- webviewView .webview .options = {
163- enableScripts: true ,
164- localResourceRoots: [
165- vscode .Uri .joinPath (this .extensionUri , " dist" , " webviews" ),
166- ],
167- };
168- webviewView .webview .html = getWebviewHtml (
169- webviewView .webview ,
170- this .extensionUri ,
171- " <name>" ,
172- );
173- }
174- }
175- ```
176-
177- 3 . ** Register in ` package.json ` ** under ` contributes.views.coder ` :
178-
179- ``` json
180- {
181- "type" : " webview" ,
182- "id" : " coder.myPanel" ,
183- "name" : " My Panel" ,
184- "icon" : " media/logo-white.svg"
185- }
186- ```
187-
188- 4 . ** Register in ` src/extension.ts ` :**
189-
190- ``` typescript
191- import { MyPanel } from " ./webviews/<name>/<Name>Panel" ;
192-
193- // In activate():
194- context .subscriptions .push (
195- vscode .window .registerWebviewViewProvider (
196- MyPanel .viewType ,
197- new MyPanel (context .extensionUri ),
198- ),
199- );
200- ```
201-
202- ### Shared Package (` @coder/shared ` )
203-
204- The extension can import types from ` @coder/shared ` via path mapping in ` tsconfig.json ` .
205- The mapping points to ` extension.d.ts ` , which re-exports only the types meant for
206- extension use (excluding ` @coder/shared/react ` which is webview-only).
207-
208- Type-safe message passing between extension and webview:
209-
210- ``` typescript
211- // In React component
212- import { postMessage , useMessage } from " @coder/shared/react" ;
213-
214- // Send message to extension
215- postMessage ({ type: " refresh" });
216-
217- // Listen for messages from extension
218- useMessage ((msg ) => {
219- if (msg .type === " data" ) {
220- setData (msg .data );
221- }
222- });
223-
224- // Persist state across visibility changes
225- const [count, setCount] = useVsCodeState (0 );
226- ```
227-
228- ### Stack
229-
230- - ** React 19** with TypeScript
231- - ** Vite** with SWC for fast builds
232- - ** @vscode-elements/react-elements ** for native VS Code styling
106+ 1 . Copy ` packages/tasks ` to ` packages/<name> ` and update the package name
107+ 2 . Create a provider in ` src/webviews/<name>/ ` (see ` TasksPanel.ts ` for reference)
108+ 3 . Register the view in ` package.json ` under ` contributes.views `
109+ 4 . Register the provider in ` src/extension.ts `
233110
234111## Testing
235112
0 commit comments