From 4b604bfbcf432deac652f370bcd3c2e3313f3133 Mon Sep 17 00:00:00 2001 From: Dmytro Kirpa Date: Mon, 2 Mar 2026 15:25:54 +0100 Subject: [PATCH 01/14] initial plan --- docs/plans/fluent-cli.md | 441 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 441 insertions(+) create mode 100644 docs/plans/fluent-cli.md diff --git a/docs/plans/fluent-cli.md b/docs/plans/fluent-cli.md new file mode 100644 index 0000000000000..1bf70660439a3 --- /dev/null +++ b/docs/plans/fluent-cli.md @@ -0,0 +1,441 @@ +# Fluent UI v9 Agentic Migration — Project Spec + +## 1) Objective + +Build an **agentic migration solution** for Fluent UI React v9 that consists of exactly two products: + +1. **Agent Skills** — deterministic instructions/workflows AI coding agents can follow for complex migrations. +2. **CLI** — executable migration engine that performs Nx-style migrations and AST transformations. + +The skills are the **primary source of migration logic and sequencing**; the CLI is a **supportive execution utility** for codemods, reporting, and deterministic automation steps. + +--- + +## 2) Problem Statement + +Current migrations (v8 → v9 and v9 minor upgrades) are inconsistent and largely manual: + +- no official migration skill system that encodes migration strategy, +- no stable bridge between agent workflow decisions and codemod execution, +- no repeatable agent workflows tied to deterministic transform tooling. + +Result: high migration cost, inconsistent outcomes, and low confidence for large codebases. + +--- + +## 3) Scope + +### In scope (MVP) + +- Define and version **agent skills** for v8 → v9 migration. +- Publish a CLI package (`@fluentui/cli`) as a support tool with: + - codemod execution (`migrate`) for skill-selected steps, + - AST-based transforms (jscodeshift initially), + - migration diagnostics/reporting (`report`), + - dry-run support and machine-readable output for agents. +- Ensure skills invoke CLI only for deterministic/mechanical edits and analysis. +- Implement and ship the two required MVP codemods: `deprecated-packages`, `deprecated-props`. + +### Out of scope (MVP) + +- Full auto-migration for every v8 component. +- IDE plugin UI. +- New runtime shim framework. +- Cross-framework migrations beyond React/TS. +- Migration recommendation hints in `report` output (Phase 2). + +--- + +## 4) Success Criteria + +- Agent can execute end-to-end migration workflow on a sample app with no custom prompts. +- Skills own migration planning decisions; CLI only executes requested codemods reliably. +- CLI provides deterministic output (`dry-run` + applied mode) and idempotent transforms. +- For MVP migrations, at least 80% of targeted mechanical edits are automated. +- Type-check/test failure count after migration is lower than baseline manual approach. + +--- + +## 5) Architecture + +### 5.1 Agent Skills Layer + +Skills are the migration control plane and contain: + +- decision trees (when to run which migration), +- sequencing rules (report → dry-run → apply → verify), +- stop conditions (unsafe diff size, parser failures, unresolved imports), +- escalation rules (manual review checkpoints). + +Skills select migration steps, call CLI commands, and evaluate outcomes before proceeding. + +### 5.2 CLI Layer + +CLI is an execution/data plane and contains: + +- transform runner, +- reporting/analysis commands, +- structured result output for agent consumption. + +Primary transform engine for MVP: **jscodeshift** (TS/TSX parser defaults). CLI does not own migration strategy. + +--- + +## 6) CLI Spec + +CLI command behavior is intentionally minimal and execution-focused; migration strategy remains in skills. + +### 6.1 Commands + +#### `migrate` + +Run codemods selected by skills (from `migrations.json` or by migration name). + +```sh +npx @fluentui/cli migrate [migration-name] [path] [options] + +# Registry-driven run (Nx-style): +npx @fluentui/cli migrate --run-migrations=migrations.json src/ + +# Direct migration run: +npx @fluentui/cli migrate deprecated-packages src/ + +# Semver-filtered run (typically skill-driven): +npx @fluentui/cli migrate src/ --from 8 --to 9 +``` + +Options: + +- `--run-migrations ` — registry file path +- `--from ` — lower bound +- `--to ` — upper bound +- `-d, --dry-run` — preview without writing +- `-l, --list` — list known migrations +- `--cpus ` — worker count +- `--parser ` — default: `tsx` +- `--json` — emit machine-readable result summary to stdout + +#### `report` + +Produce diagnostics data for agents to decide migration steps. Writes structured JSON to a file by default (output can be large). + +```sh +npx @fluentui/cli report [path] [options] +``` + +Options: + +- `--output ` — default: `./fluent-report.json` +- `--print` — print compact summary to stdout instead of writing file +- `--json` — emit full JSON to stdout (for agent piping) + +Output sections: + +1. **Environment** — Node, OS, npm versions (always included). +2. **Installed packages** — all `@fluentui/*` and `@fluentui-contrib/*` versions (always included). +3. **Usage inventory** — imports + JSX props per component across scanned path (only when `[path]` is provided). + +Terminal summary always printed after file write: + +```sh +Report written to fluent-report.json + +Node: 22.21.1 | OS: darwin-arm64 | npm: 10.9.4 +Installed: @fluentui/react-components@9.73.1 @fluentui/react@8.125.5 (+1 more) +Usage: 312 usages across 14 components in src/ +``` + +JSON schema (`fluent-report.json`): + +```json +{ + "generatedAt": "2026-03-02T10:00:00.000Z", + "env": { "node": "22.21.1", "os": "darwin-arm64", "npm": "10.9.4" }, + "packages": { + "@fluentui/react-components": "9.73.1", + "@fluentui/react": "8.125.5" + }, + "usage": { + "scannedPath": "src/", + "totalUsages": 312, + "components": [ + { "name": "Button", "package": "@fluentui/react-components", "usages": 142, "props": ["appearance", "icon"] }, + { "name": "DefaultButton", "package": "@fluentui/react", "usages": 37, "props": ["text", "onClick"] } + ] + } +} +``` + +`usage` is `null` when no path is provided. + +Migration recommendation hints are **Phase 2** — MVP `report` is data-only. + +--- + +### 6.2 Migration Registry Contract (`migrations.json`) + +`migrations.json` is an execution catalog consumed by CLI; it is not the migration strategy source. + +```json +{ + "version": "1", + "migrations": [ + { + "name": "deprecated-packages", + "version": "9.0.0", + "fromVersion": "8.0.0", + "description": "Replace deprecated @fluentui package imports with supported equivalents", + "package": "@fluentui/react-components", + "kind": "ast", + "implementation": "./dist/transforms/v9/deprecated-packages.js", + "idempotent": true + }, + { + "name": "deprecated-props", + "version": "9.0.0", + "fromVersion": "8.0.0", + "description": "Replace @deprecated props across v9 components with their supported replacements", + "package": "@fluentui/react-components", + "kind": "ast", + "implementation": "./dist/transforms/v9/deprecated-props.js", + "idempotent": true + } + ] +} +``` + +Fields: + +- `kind`: `ast` | `nx-generator` | `composite` +- `implementation`: path to compiled entrypoint, resolved from package root +- `idempotent`: required declaration — transforms that cannot guarantee idempotency are not permitted in MVP + +--- + +### 6.3 Migration Types + +1. **AST transform** (default): codemods for imports, props, JSX shape. Implemented as standard jscodeshift transforms. +2. **Nx-style migration wrapper**: invokes migration-style scripts through the unified CLI contract. +3. **Composite migration**: ordered list of atomic migrations with shared context. + +--- + +## 7) Agent Skills Spec + +Skills are the authoritative migration source for this project. + +### 7.1 Location + +`skills/.md` at the **repo root**. Versioned with the codebase. Distributed via the `npx skills add` tooling (external). + +> Note: `packages/react-components/react-components-agent-skills/` exists as an empty placeholder — it is **not used** for this project. + +### 7.2 Skill Inventory (MVP) + +| Skill file | Purpose | +| ------------------------------------- | ------------------------------------- | +| `skills/fluentui-migrate-v8-to-v9.md` | End-to-end v8 → v9 migration workflow | + +### 7.3 Skill Workflow Contract + +Every skill must follow this baseline sequence: + +1. Run `@fluentui/cli report [path] --json` and parse the JSON output. +2. Determine applicable migration plan from skill rules. +3. Resolve needed codemod steps against CLI migration list (`migrate --list --json`). +4. Run `migrate --dry-run --json` and evaluate risk signals against safety thresholds. +5. Run `migrate --json` (apply step) if safe; confirm with user if large-diff gate triggers. +6. Run verification (`npx nx run-many -t type-check` on touched projects). +7. Produce final summary: migrations run, files changed, remaining manual follow-ups. + +### 7.4 Skill Safety Thresholds + +Defined as named constants in the skill file (hardcoded defaults, documented for review): + +| Constant | Default | Meaning | +| ------------------------- | ------- | ----------------------------------------------------- | +| `PARSE_ERROR_RATE_LIMIT` | `0.05` | Stop if >5% of files fail to parse | +| `LARGE_DIFF_FILE_COUNT` | `100` | Require human confirmation if >100 files changed | +| `UNRESOLVED_IMPORT_LIMIT` | `0` | Stop if any unresolved imports remain after transform | + +### 7.5 Safety Rules + +- Never run apply step before dry-run succeeds. +- Stop if parser error rate exceeds `PARSE_ERROR_RATE_LIMIT`. +- Stop if transform claims success but outputs unresolved imports. +- Require human confirmation when changed file count exceeds `LARGE_DIFF_FILE_COUNT`. + +--- + +## 8) Required Codemods (MVP) + +### `deprecated-packages` + +Rewrites imports from deprecated `@fluentui` packages to their current equivalents. + +Deprecated packages (source: `packages/react-components/deprecated/`): + +| Deprecated import | Replacement | Note | +| ----------------------------- | ------------------------------------- | ------------------------------------------------------------------- | +| `@fluentui/react-alert` | `@fluentui/react-toast` | Insert `// TODO: also consider @fluentui/react-message-bar` comment | +| `@fluentui/react-infobutton` | `@fluentui/react-infolabel` | Rename component `InfoButton` → `InfoLabel` | +| `@fluentui/react-virtualizer` | `@fluentui-contrib/react-virtualizer` | Package moved to contrib | + +**Source of truth**: read `packages/react-components/deprecated/*/README.md` before implementing. + +### `deprecated-props` + +Renames (or removes) deprecated component props to their supported replacements. + +Known deprecated props (source: `@deprecated` JSDoc tags in `packages/react-components/`): + +| Component | Deprecated prop | Replacement | +| -------------------- | --------------------- | ------------------------------------ | +| `TableSelectionCell` | `hidden` | `invisible` | +| `Popover` | `legacyTrapFocus` | `inertTrapFocus` | +| `Calendar` (compat) | `overlayedWithButton` | `overlaidWithButton` | +| `PositioningOptions` | `positionFixed` | `strategy="fixed"` (value transform) | +| `TagPickerList` | `disableAutoFocus` | _(remove — prop has no effect)_ | + +**Source of truth**: search `@deprecated` across `packages/react-components/` before implementing to catch any additions. + +### Transform conventions + +```typescript +import type { Transform, API, FileInfo } from 'jscodeshift'; +const transform: Transform = (file: FileInfo, api: API): string | void => { ... }; +export default transform; +// Return undefined → nochange (no write). Must be idempotent. +``` + +--- + +## 9) Package Layout + +```sh +packages/cli/ +├── bin/fluentui.js # #!/usr/bin/env node shebang +├── migrations.json # execution catalog (ships in npm package) +├── src/ +│ ├── index.ts # yargs root — registers migrate + report +│ ├── types.ts # MigrationEntry, RunnerOptions, ReportOutput, ... +│ ├── commands/ +│ │ ├── migrate.ts +│ │ └── report.ts +│ ├── runner/ +│ │ ├── MigrationRunner.ts # loads registry, filters, invokes jscodeshift Runner API +│ │ └── semverFilter.ts # normaliseVersion(), filterMigrationsByRange() +│ ├── report/ +│ │ ├── packageScanner.ts # globs node_modules for @fluentui/* versions +│ │ └── UsageCollector.ts # jscodeshift read-only visitor for imports + JSX props +│ ├── transforms/ +│ │ └── v9/ +│ │ ├── deprecated-packages.ts +│ │ └── deprecated-props.ts +│ └── __tests__/ +│ ├── semverFilter.test.ts +│ ├── MigrationRunner.test.ts +│ ├── report/packageScanner.test.ts +│ └── transforms/ +│ ├── deprecated-packages/ # golden input/output fixtures +│ └── deprecated-props/ # golden input/output fixtures +├── package.json +├── project.json # @nx/js:swc build target, platform:node tag +├── .swcrc # copy from tools/visual-regression-assert/.swcrc +├── tsconfig.json +├── tsconfig.lib.json +├── tsconfig.spec.json +├── jest.config.ts +└── eslint.config.js +``` + +Skills (repo root, versioned with code): + +```sh +skills/ +└── fluentui-migrate-v8-to-v9.md +``` + +--- + +## 10) Build Tooling + +Mirrors `tools/visual-regression-assert/` — the canonical modern Node CLI package in the repo. + +| Concern | Tool | +| -------------- | ----------------------------------------------------------------------------- | +| Build executor | `@nx/js:swc` — output to `packages/cli/dist/` | +| SWC config | `.swcrc` — copy from `tools/visual-regression-assert/.swcrc` | +| Tests | `@swc/jest` reading `.swcrc`, `testEnvironment: node` | +| TypeScript | Solution config: `tsconfig.json` → `tsconfig.lib.json` + `tsconfig.spec.json` | +| Lint | ESLint flat config, `@fluentui/eslint-plugin` `flat/node` base | + +Workspace changes required: + +| File | Change | +| -------------------- | ----------------------------------------------------------- | +| `nx.json` | Add `"packages/cli/**"` to workspace plugin `include` array | +| `tsconfig.base.json` | Add `"@fluentui/cli": ["packages/cli/src/index.ts"]` | + +--- + +## 11) Implementation Phases + +### Phase 0 — Scaffold + +- Create `packages/cli/` with all config files (build, test, lint, TypeScript). +- Update `nx.json` + `tsconfig.base.json`. +- Verify `nx build cli` and `nx test cli` pass on empty stubs. + +### Phase 1 — Core Engine + +- Implement `types.ts`, `semverFilter.ts`, `MigrationRunner.ts` with tests. +- Implement `migrate` command shell + `--list`, `--dry-run`, `--json` modes. +- Create `migrations.json` with two entries (stubs, implementations not yet wired). +- Verify CLI responds correctly to all flags against stub transforms. + +### Phase 2 — Codemods + +- Implement `deprecated-packages.ts` with golden tests + idempotency test. +- Implement `deprecated-props.ts` with golden tests + idempotency test. +- Wire transforms into `migrations.json`. + +### Phase 3 — Report Command + +- Implement `packageScanner.ts` + tests. +- Implement `UsageCollector.ts` + tests. +- Implement `report.ts` command (file write, `--print`, `--json`). + +### Phase 4 — Agent Skill + +- Author `skills/fluentui-migrate-v8-to-v9/SKILL.md` with safety thresholds, 7-step workflow, CLI invocations. +- Validate workflow against real CLI output on a sample v8 codebase. + +--- + +## 12) Verification Strategy + +- **Unit tests**: runner, semver filter, registry parsing. +- **Golden tests**: each transform has `*.input.tsx` / `*.output.tsx` fixture pairs. +- **Idempotency test**: run each transform twice — second run must return `undefined` (no change). +- **Integration test**: sample v8 app → CLI migrate → typecheck passes. +- **Skill E2E**: simulated agent execution path using real CLI `--json` outputs. + +--- + +## 13) Risks and Mitigations + +- **API drift**: registry versioning + semver gates. +- **False-positive transforms**: conservative AST matching + dry-run diff review. +- **Agent overreach**: enforce skills-first policy; CLI is execution-only. +- **Large monorepo runtime cost**: path scoping + `--cpus` worker control + incremental runs. + +--- + +## 14) Open Decisions — Resolved + +| Decision | Resolution | +| ------------------------------ | ------------------------------------------------------------------------------------------------------ | +| Skills packaging location | `skills/.md` at repo root. `react-components-agent-skills/` placeholder not used. | +| Report migration hints in MVP | Phase 2 only. MVP `report` is data-only. | +| Safety gate threshold defaults | Hardcoded named constants in skill file: parse error 5%, diff gate 100 files, zero unresolved imports. | From 09aa6bb3f7a993d1c651e35c32e37f27d8a9e1b7 Mon Sep 17 00:00:00 2001 From: Dmytro Kirpa Date: Mon, 2 Mar 2026 16:29:53 +0100 Subject: [PATCH 02/14] wip --- docs/plans/fluent-cli.md | 4 +- skills/fluentui-migrate-v8-to-v9/SKILL.md | 169 ++++++++ .../references/codemod-catalog.md | 363 ++++++++++++++++++ 3 files changed, 533 insertions(+), 3 deletions(-) create mode 100644 skills/fluentui-migrate-v8-to-v9/SKILL.md create mode 100644 skills/fluentui-migrate-v8-to-v9/references/codemod-catalog.md diff --git a/docs/plans/fluent-cli.md b/docs/plans/fluent-cli.md index 1bf70660439a3..6daf71ef2396d 100644 --- a/docs/plans/fluent-cli.md +++ b/docs/plans/fluent-cli.md @@ -226,9 +226,7 @@ Skills are the authoritative migration source for this project. ### 7.1 Location -`skills/.md` at the **repo root**. Versioned with the codebase. Distributed via the `npx skills add` tooling (external). - -> Note: `packages/react-components/react-components-agent-skills/` exists as an empty placeholder — it is **not used** for this project. +`skills//SKILL.md` at the **repo root**. Versioned with the codebase. Distributed via the `npx skills add` tooling (external). ### 7.2 Skill Inventory (MVP) diff --git a/skills/fluentui-migrate-v8-to-v9/SKILL.md b/skills/fluentui-migrate-v8-to-v9/SKILL.md new file mode 100644 index 0000000000000..9b618b2bea173 --- /dev/null +++ b/skills/fluentui-migrate-v8-to-v9/SKILL.md @@ -0,0 +1,169 @@ +--- +name: fluentui-migrate-v8-to-v9 +description: > + Orchestrates end-to-end migration of a codebase from Fluent UI React v8 (@fluentui/react) to v9 + (@fluentui/react-components) using the @fluentui/cli toolchain. Use this skill when asked to + migrate a project, run migration codemods, analyze what needs to change, or generate a migration + plan. Covers: CLI report/migrate commands, codemod selection and sequencing, safety evaluation, + verification, and identifying what requires manual migration vs. what can be automated. +--- + +# Fluent UI v8 → v9 Migration Workflow + +## Safety Thresholds + +``` +PARSE_ERROR_RATE_LIMIT = 0.05 # Stop if >5% of files fail to parse +LARGE_DIFF_FILE_COUNT = 100 # Require human confirmation if >100 files changed +UNRESOLVED_IMPORT_LIMIT = 0 # Stop if any unresolved imports remain after transform +``` + +## Safety Rules + +- **Never run apply before dry-run succeeds.** +- Stop if parse error rate exceeds `PARSE_ERROR_RATE_LIMIT`. +- Stop if transform succeeds but leaves unresolved imports. +- Require user confirmation when changed file count exceeds `LARGE_DIFF_FILE_COUNT`. + +--- + +## 7-Step Migration Workflow + +### Step 1 — Assess (Report) + +```sh +npx @fluentui/cli report --json +``` + +Parse the JSON output. Check: + +- Which `@fluentui/*` packages are installed and at what versions +- Total usage count and per-component breakdown +- Presence of both v8 and v9 packages (mixed mode) + +Save the report path for later reference: + +```sh +npx @fluentui/cli report src/ --output ./fluent-report.json +``` + +### Step 2 — Plan + +From the report output, decide which codemods apply. Use [codemod-catalog.md](references/codemod-catalog.md) to: + +1. Identify Tier 1 (mechanical) transforms to run immediately +2. Identify Tier 2 (partial) transforms that need post-run validation +3. Identify Tier 3 (manual) patterns that need human migration — estimate scope from usage counts + +List available codemods: + +```sh +npx @fluentui/cli migrate --list --json +``` + +### Step 3 — Dry Run + +Run selected codemods in dry-run mode: + +```sh +# Single codemod +npx @fluentui/cli migrate deprecated-packages --dry-run --json + +# All applicable codemods from registry +npx @fluentui/cli migrate --run-migrations=migrations.json --dry-run --json +``` + +Evaluate dry-run output: + +- Check `parseErrors` count against `PARSE_ERROR_RATE_LIMIT` +- Check `filesChanged` against `LARGE_DIFF_FILE_COUNT` +- Check `unresolvedImports` against `UNRESOLVED_IMPORT_LIMIT` +- Stop and report if any threshold is exceeded + +### Step 4 — Confirm (if threshold triggered) + +If `filesChanged > LARGE_DIFF_FILE_COUNT`, pause and show the user: + +- Total files that will be changed +- Breakdown by codemod +- Ask for explicit confirmation before proceeding + +### Step 5 — Apply + +```sh +npx @fluentui/cli migrate deprecated-packages --json +npx @fluentui/cli migrate deprecated-props --json +# ... additional codemods in sequenced order +``` + +Run codemods in this sequence (order matters for idempotency): + +1. `deprecated-packages` — fix package imports first +2. `deprecated-props` — fix deprecated props +3. `import-paths` — consolidate deep path imports to barrel +4. `aria-props` — aria prop renames +5. `component-ref` — componentRef → ref +6. `component-renames` — 1:1 renames +7. `button-variants` — button variant transforms +8. Remaining Tier 2 codemods + +After each codemod, check returned JSON for errors before proceeding. + +### Step 6 — Verify + +Run type-check on all touched packages: + +```sh +# In the fluentui monorepo: +npx nx run-many -t type-check --projects= + +# In a standalone project: +npx tsc --noEmit +``` + +Report any type errors to the user. Type errors after mechanical transforms indicate either: + +- A codemod missed a pattern → investigate and fix manually +- A Tier 3 change still needed → direct user to manual steps + +### Step 7 — Summarize + +Produce a final summary: + +- Codemods run and files changed per codemod +- Remaining manual migration items (from Tier 3 detection in report) +- Any type-check failures still open +- Recommended next actions + +--- + +## Codemod Decision Guide + +Load [codemod-catalog.md](references/codemod-catalog.md) to determine: + +- Which patterns in the codebase are mechanical (run codemod) +- Which are partial (run codemod + validate) +- Which are manual (flag with TODO, estimate effort) + +**Key question per usage**: "Can this be transformed without reading surrounding context?" → Yes = Tier 1-2, No = Tier 3. + +## Common Flags + +```sh +# Run with TypeScript/TSX parser (default): +npx @fluentui/cli migrate src/ --parser tsx + +# Control parallelism for large codebases: +npx @fluentui/cli migrate src/ --cpus 4 + +# Version-filtered run (skill-driven): +npx @fluentui/cli migrate src/ --from 8 --to 9 +``` + +## Component-Specific Migration Guidance + +For detailed prop mapping and examples when doing manual or partial migration steps, refer to the companion `fluentui-v8-to-v9` skill which contains: + +- Per-component migration guides (Button, Menu, Input, Tabs, Stack, Theme) +- Full component mapping table +- Troubleshooting guide diff --git a/skills/fluentui-migrate-v8-to-v9/references/codemod-catalog.md b/skills/fluentui-migrate-v8-to-v9/references/codemod-catalog.md new file mode 100644 index 0000000000000..e224f934e0a9e --- /dev/null +++ b/skills/fluentui-migrate-v8-to-v9/references/codemod-catalog.md @@ -0,0 +1,363 @@ +# Codemod Catalog: FluentUI v8 → v9 + +This catalog classifies every known v8→v9 migration pattern by how much can be automated. + +## Tier Classification + +| Tier | Label | Definition | +| ----- | ---------- | ---------------------------------------------------------------------------------------------- | +| **1** | Mechanical | Safe, idempotent, 1:1 transforms. Full automation with high confidence. | +| **2** | Partial | Automatable with caveats — value transforms, structural prop moves, require validation. | +| **3** | Manual | Architectural changes requiring human judgment. Flag with TODO comment, do not auto-transform. | + +--- + +## Tier 1 — Mechanical (Safe to Automate) + +### 1.1 Deprecated Package Imports → Supported Packages + +> Codemod name: `deprecated-packages` + +| Deprecated import | Replacement | Extra action | +| ----------------------------- | ------------------------------------- | ---------------------------------------------------------------- | +| `@fluentui/react-alert` | `@fluentui/react-toast` | Add `// TODO: also consider @fluentui/react-message-bar` comment | +| `@fluentui/react-infobutton` | `@fluentui/react-infolabel` | Rename `InfoButton` → `InfoLabel` in same file | +| `@fluentui/react-virtualizer` | `@fluentui-contrib/react-virtualizer` | | + +**Source of truth**: `packages/react-components/deprecated/*/README.md` + +### 1.2 Hook Import Migration + +| v8 import | v9 import | +| ------------------------------------ | ---------------------------------------- | +| `useId` from `@fluentui/react-hooks` | `useId` from `@fluentui/react-utilities` | + +### 1.3 Deprecated Props → Supported Replacements + +> Codemod name: `deprecated-props` + +| Component | Deprecated prop | Replacement | Transform type | +| -------------------- | --------------------- | ---------------------- | --------------- | +| `TableSelectionCell` | `hidden` | `invisible` | Rename | +| `Popover` | `legacyTrapFocus` | `inertTrapFocus` | Rename | +| `Calendar` (compat) | `overlayedWithButton` | `overlaidWithButton` | Rename | +| `PositioningOptions` | `positionFixed` | `strategy="fixed"` | Value transform | +| `TagPickerList` | `disableAutoFocus` | _(remove — no effect)_ | Remove prop | + +**Source of truth**: search `@deprecated` across `packages/react-components/` before implementing. + +### 1.4 Aria Prop Renames (All Components) + +All components: v8 used camelCase custom props; v9 uses native HTML attributes. + +| v8 prop | v9 prop | +| ------------------- | ------------------ | +| `ariaLabel` | `aria-label` | +| `ariaHidden` | `aria-hidden` | +| `ariaDescribedBy` | `aria-describedby` | +| `ariaLabelledBy` | `aria-labelledby` | +| `ariaPositionInSet` | `aria-posinset` | +| `ariaSetSize` | `aria-setsize` | + +### 1.5 Ref Migration (All Components) + +| v8 | v9 | +| -------------- | ----- | +| `componentRef` | `ref` | + +### 1.6 Import Path Consolidation + +v8 allowed deep path imports (e.g. `@fluentui/react/lib/Button`). v9 uses the barrel export only. + +```ts +// v8 (both forms valid) +import { Button } from '@fluentui/react'; +import { Button } from '@fluentui/react/lib/Button'; + +// v9 (only barrel) +import { Button } from '@fluentui/react-components'; +``` + +Codemod: rewrite any `@fluentui/react/lib/*` to the barrel `@fluentui/react-components` (with correct named export per component-mapping). + +### 1.7 Direct Component Renames (1:1, No Prop Changes) + +| v8 component | v9 component | Notes | +| ------------------- | ---------------- | ---------------------------------------- | +| `Separator` | `Divider` | Same import package | +| `Toggle` | `Switch` | | +| `Shimmer` | `Skeleton` | | +| `ProgressIndicator` | `ProgressBar` | | +| `ComboBox` | `Combobox` | Case change only | +| `ThemeProvider` | `FluentProvider` | theme prop also needs migration (Tier 2) | +| `Fabric` | `FluentProvider` | | +| `Panel` | `Drawer` | | +| `Layer` | `Portal` | | +| `DocumentCard` | `Card` | | +| `SearchBox` | `SearchBox` | Same name, new package | +| `Breadcrumb` | `Breadcrumb` | Same name, new package | +| `Spinner` | `Spinner` | Same name, new package | +| `Tooltip` | `Tooltip` | Same name, new package | +| `Slider` | `Slider` | Same name, new package | +| `MessageBar` | `MessageBar` | Same name, new package | +| `Nav` | `Nav` | Same name, new package | + +--- + +## Tier 2 — Partially Automatable (Validate Output) + +### 2.1 Button Variant → appearance Prop + +| v8 component | v9 equivalent | Transform | +| ------------------ | --------------------------------- | ------------------ | +| `DefaultButton` | `Button` | Rename | +| `PrimaryButton` | `Button appearance="primary"` | Rename + add prop | +| `ActionButton` | `Button appearance="transparent"` | Rename + add prop | +| `CommandButton` | `Button` | Rename | +| `CommandBarButton` | `Button` | Rename | +| `ToggleButton` | `ToggleButton` | Import change only | +| `CompoundButton` | `CompoundButton` | Import change only | + +**Caveat**: `IconButton` requires removing text children — flag if children exist. + +### 2.2 Button `text` Prop → `children` + +```tsx +// v8 + +// v9 + +``` + +Automatable when `text` is a static string literal. Flag if `text` is a variable or expression — generate TODO comment. + +### 2.3 Button `primary` Prop → `appearance` + +```tsx +// v8: