Agent Skills › microsoft/rayfin › vscode-react-webview-architecture

vscode-react-webview-architecture

GitHub

定义 Rayfin VS Code 扩展中 React Webview 的架构规范,涵盖渲染管线、文件组织、状态管理及闭包问题处理。用于创建新组件、集成 Fluent UI 及调试渲染异常。

.github/skills/vscode-react-webview-architecture/SKILL.md microsoft/rayfin

Trigger Scenarios

创建或修改 VS Code Webview 在 webviews 目录下添加新组件 使用 React Context 管理状态 调试事件处理中的过时闭包问题

Install

npx skills add microsoft/rayfin --skill vscode-react-webview-architecture -g -y
More Options

Non-standard path

npx skills add https://github.com/microsoft/rayfin/tree/main/.github/skills/vscode-react-webview-architecture -g -y

Use without installing

npx skills use microsoft/rayfin@vscode-react-webview-architecture

指定 Agent (Claude Code)

npx skills add microsoft/rayfin --skill vscode-react-webview-architecture -a claude-code -g -y

安装 repo 全部 skill

npx skills add microsoft/rayfin --all -g -y

预览 repo 内 skill

npx skills add microsoft/rayfin --list

SKILL.md

Frontmatter
{
    "name": "vscode-react-webview-architecture",
    "description": "Architecture patterns for React-based webviews in the Rayfin VS Code extension (packages\/tools\/vscode). Use when creating new webview components, working with state management (Context API), integrating Fluent UI components, solving stale closure bugs with refs, or debugging webview rendering issues. Does NOT cover tRPC messaging (see vscode-webview-trpc-messaging skill)."
}

React Webview Architecture

Patterns and conventions for React webviews in Project Rayfin.

Related skills (do not duplicate):

  • vscode-webview-trpc-messaging — tRPC routers, procedures, telemetry, AbortSignal, subscriptions, WebviewController

Full reference: See references/REACT_ARCHITECTURE_GUIDELINES.md

When to Use

  • Creating or modifying a webview
  • Adding new components inside packages/tools/vscode/src/webviews/
  • Working with React Context state management
  • Integrating Monaco Editor
  • Debugging stale closure issues in event handlers

Rendering Pipeline

Every webview boots through packages/tools/vscode/src/webviews/index.tsx:

root.render(
  <DynamicThemeProvider useAdaptive={true}>
    <WithWebviewContext vscodeApi={vscodeApi}>
      <Component />
    </WithWebviewContext>
  </DynamicThemeProvider>,
);
  • DynamicThemeProvider — adapts Fluent UI theming to VS Code's active color theme
  • WithWebviewContext — provides vscodeApi (postMessage) via React Context
  • WebviewRegistry — maps webview names → React components (in packages/tools/vscode/src/webviews/api/configuration/WebviewRegistry.ts)

Configuration from the extension host is read via useConfiguration<T>().

File Organization

viewName/
├── ViewName.tsx            # Main component
├── viewName.scss           # Styles
├── viewNameContext.ts      # Context + state types (if complex)
├── viewNameController.ts   # WebviewController subclass (extension-side)
├── viewNameRouter.ts       # tRPC router (extension-side, see vscode-webview-trpc-messaging skill)
├── constants.ts
├── components/             # Sub-components
├── hooks/                  # Custom React hooks
├── types/                  # TypeScript types
└── utils/                  # Helpers

Component Hierarchy

Example component hierarchy for a typical view:

MyView
├── Header
├── ToolbarActions
├── TabList
│   ├── ContentTab
│   │   └── ContentPanel
│   └── EditorTab
│       └── MonacoEditor
└── StatusBar

State Management

Simple views: local useState + props

Complex views: React Context with [state, setState] tuple

export const MyViewContext = createContext<
    [MyViewContextType, React.Dispatch<React.SetStateAction<MyViewContextType>>]
>([DefaultMyViewContext, () => {}]);

// Provider in parent
const [currentContext, setCurrentContext] = useState(DefaultMyViewContext);
<MyViewContext.Provider value={[currentContext, setCurrentContext]}>

// Consumer in child
const [currentContext, setCurrentContext] = useContext(MyViewContext);

Always use functional updates when state depends on previous value:

setCurrentContext((prev) => ({
  ...prev,
  isLoading: true,
  activeQuery: { ...prev.activeQuery, pageNumber: 1 },
}));

Stale Closure Pattern (CRITICAL)

Third-party components that bind event handlers at initialization don't update when state changes. Always use refs to access current data in those handlers:

const dataRef = useRef(data);
useEffect(() => {
  dataRef.current = data;
}, [data]);

const onClick = useCallback((event) => {
  const item = dataRef.current[event.detail.args.row]; // ✅ always current
  // NOT: data[event.detail.args.row]; ❌ stale closure
}, []); // stable deps only

Why: Some third-party components bind handlers once at init time. Without refs, handlers see the data from initialization, not the latest state.

Fluent UI Integration

Use @fluentui/react-components (v9), themed via DynamicThemeProvider:

Component Usage
ProgressBar Loading states
Button, ToggleButton Toolbar actions
Tab, TabList View switching
Dropdown, Option Selection (ViewSwitcher)
Badge Status/preview indicators
MessageBar Info/warning messages
Skeleton, SkeletonItem Loading placeholders

Styling

  • Each component gets its own .scss file, imported directly
  • Shared styles in sharedStyles.scss, applied via @extend
  • Consistent spacing unit: 10px with flexbox row-gap/column-gap
  • No inline styles — move to SCSS files
  • Avoid negative margins — fix layout with proper flexbox
.myView {
  display: flex;
  flex-direction: column;
  height: 100vh;
  row-gap: 10px;
}

Custom Hooks

Hook Location Purpose
useSelectiveContextMenuPrevention() packages/tools/vscode/src/webviews/api/webview-client/utils/ Prevents browser context menu everywhere except Monaco editors. Call once in top-level view.

Conditional Rendering Patterns

Object-based switch:

Version History

  • 0979439 Current 2026-10-18 22:48

Same Skill Collection

.github/skills/hotfix-release/SKILL.md
.github/skills/launch-vscode-extension/SKILL.md
.github/skills/openspec-apply-change/SKILL.md
.github/skills/openspec-archive-change/SKILL.md
.github/skills/openspec-bulk-archive-change/SKILL.md
.github/skills/openspec-continue-change/SKILL.md
.github/skills/openspec-explore/SKILL.md
.github/skills/openspec-ff-change/SKILL.md
.github/skills/openspec-new-change/SKILL.md
.github/skills/openspec-onboard/SKILL.md
.github/skills/openspec-sync-specs/SKILL.md
.github/skills/openspec-verify-change/SKILL.md
.github/skills/privacy-dfd/SKILL.md
.github/skills/rayfin-cli-ux/SKILL.md
.github/skills/react-best-practices/SKILL.md
.github/skills/run-cli-e2e-locally/SKILL.md
.github/skills/vscode-webview-trpc-messaging/SKILL.md
samples/data-app/.agents/skills/app-design/SKILL.md
samples/data-app/.agents/skills/app-validation/SKILL.md
samples/data-app/.agents/skills/dax-authoring/SKILL.md
samples/data-app/.agents/skills/fabric-cli/SKILL.md
samples/data-app/.agents/skills/fabric-sdk/SKILL.md
samples/data-app/.agents/skills/playwright-cli/SKILL.md
samples/data-app/.agents/skills/query-design/SKILL.md
samples/data-app/.agents/skills/schema-discovery/SKILL.md
samples/data-app/.agents/skills/visuals/SKILL.md
.github/skills/react-clean-architecture/SKILL.md
plugin/skills/rayfin-getting-started/SKILL.md
skills/rayfin-getting-started/SKILL.md

Metadata

Files
0
Version
0979439
Hash
02b7d9a8
Indexed
2026-10-18 22:48

Home - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-11-04 09:49
浙ICP备14020137号-1