# 2026-07-17 — P1-4 modal migration: Fees.tsx (Track A continuation) Branch: `feat/p1-4-modals-fees` Worktree: `.worktrees/feat-p1-4-modals-fees` ## Why P1-4 from the readiness audit asks for every inline modal to use the shared `` component Track A introduced. BankingAccounts.tsx and 8 finance/* files already migrated. This PR continues the sweep with the top-level `Fees.tsx` (4 modals). ## Changes ### `client/src/pages/Fees.tsx` Migrated 4 modals to `` + ``: - **Create Fee Group** — 2-field form (name, amount) - **Assign Fees** — 2 dropdowns (student, fee group) - **Record Payment** — dropdown + amount input - **Edit Fee Group** — name / description / amount / due date ### Notes The page's open `` header close button is removed — `` injects its own close button inside `` (already part of `` when no `icon` prop is supplied). Same back-button-on-Escape + click-outside-to-close behaviour comes for free. Each form uses an explicit `id="…-form"` so the footer-submit button can use `form="…"` to post outside the form element. This preserves the exact button placement at the modal footer (matching the `Footer` slot in Track A's reference). The `createPortal`-based row context menu (lines ~517 in the source) is NOT a modal — it's a row-popover — and was left untouched. Lint script counts it as 0 because it uses neither `fixed inset-0` nor `backdrop-blur-sm`. ## Out of scope The remaining 14 inline modals split across: - `HRManagement.tsx` (7) - `Inventory.tsx` (4) - `Library.tsx` (3) - `parent/AcademicProgress.tsx` (4) - 6 in `finance/*` (StudentGroups × 3, StudentGroupDetail, and side-drawers in Invoices + Payslips needing a sibling `` component) …land in subsequent PRs. ## Verification - `node scripts/lint-no-inline-modals.js` → `Fees.tsx` count dropped 4 → 0. - `npx tsc --noEmit` clean for `Fees.tsx` (no new TS errors).