Skip to content

Commit 9b458f9

Browse files
committed
Simplify the CONTRIBUTING.md webview section
1 parent 487407b commit 9b458f9

File tree

1 file changed

+19
-142
lines changed

1 file changed

+19
-142
lines changed

CONTRIBUTING.md

Lines changed: 19 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -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
7777
packages/
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
9582
src/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
12197
pnpm 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

Comments
 (0)