Spaces:
Sleeping
Sleeping
| # Co-Study4Grid — Frontend | |
| React 19 + TypeScript 5.9 + Vite 7 single-page app for the | |
| Co-Study4Grid contingency-analysis UI. Talks to the FastAPI backend | |
| at `http://localhost:8000` (hardcoded in `src/api.ts`) and renders | |
| pypowsybl NAD / SLD diagrams with pan / zoom. | |
| This file is a quick orientation. For the full guide — hook split, | |
| data flow, SVG performance levers, detached / tied tabs, interaction | |
| logger contract — see [`CLAUDE.md`](./CLAUDE.md). | |
| ## Scripts | |
| ```bash | |
| npm install # install dependencies | |
| npm run dev # Vite dev server with HMR (default port 5173) | |
| npm run build # tsc -b && vite build → dist/ | |
| npm run build:standalone # tsc -b && vite build --config vite.config.standalone.ts | |
| # → dist-standalone/standalone.html (single-file bundle) | |
| npm run preview # preview the production build | |
| npm run lint # eslint . (flat config, v9+) | |
| npm run test # vitest run (~1000 specs) | |
| npm run test:watch # vitest in watch mode | |
| npm run quality:report # run the backend code-quality reporter on the whole repo | |
| npm run quality:check # gate — exits non-zero on threshold violation | |
| ``` | |
| The backend must be running on `http://localhost:8000` for the dev | |
| server to serve anything useful. Start it with: | |
| ```bash | |
| # from project root | |
| uvicorn expert_backend.main:app --host 0.0.0.0 --port 8000 | |
| ``` | |
| ## Source layout | |
| ``` | |
| src/ | |
| ├── main.tsx # React entry (StrictMode) | |
| ├── App.tsx # State orchestration hub (~1150 lines) | |
| ├── App.*.test.tsx # App-level integration tests by domain | |
| ├── api.ts # Axios HTTP client | |
| ├── types.ts # All TypeScript interfaces | |
| ├── hooks/ | |
| │ ├── useSettings.ts # Settings state + SettingsState interface | |
| │ ├── useActions.ts # Action selection / favorite / reject | |
| │ ├── useAnalysis.ts # Two-step analysis pipeline (step1 / step2) | |
| │ ├── useDiagrams.ts # NAD fetching + tab management | |
| │ ├── useContingencyFetch.ts # svgPatch fast-path + /api/contingency-diagram fallback | |
| │ ├── useDiagramHighlights.ts # Per-tab SVG highlight pipeline + Flow/Impacts view-mode | |
| │ ├── useSession.ts # Session save / reload | |
| │ ├── useDetachedTabs.ts # Detached visualization windows | |
| │ ├── useTiedTabsSync.ts # Mirror viewBox between detached + main | |
| │ ├── useSldOverlay.ts # SLD overlay state | |
| │ └── usePanZoom.ts # Per-tab viewBox, zoom-to-element | |
| ├── components/ # Presentational components (no API calls) | |
| │ ├── Header, ActionFeed, ActionCard, ActionCardPopover, | |
| │ ├── ActionOverviewDiagram, ActionSearchDropdown, | |
| │ ├── ActionTypeFilterChips, # Shared chip row | |
| │ ├── AppSidebar, SidebarSummary, StatusToasts, # Sidebar layout | |
| │ ├── VisualizationPanel, OverloadPanel, CombinedActionsModal, | |
| │ ├── ComputedPairsTable, ExplorePairsTab, | |
| │ ├── DetachableTabHost, MemoizedSvgContainer, SldOverlay, | |
| │ ├── ErrorBoundary | |
| │ └── modals/ | |
| │ ├── SettingsModal, ReloadSessionModal, ConfirmationDialog | |
| └── utils/ | |
| ├── svgUtils.ts # Barrel re-exporting every utils/svg/* module | |
| ├── svg/ # PR #104 decomposition of the old svgUtils | |
| │ ├── idMap, metadataIndex, svgBoost, fitRect, | |
| │ ├── deltaVisuals, actionPinData, actionPinRender, | |
| │ └── highlights | |
| ├── svgPatch.ts # SVG DOM recycling (PR #108) | |
| ├── actionTypes.ts # Action-type classification + filter helpers | |
| ├── overloadHighlights.ts # N-1 overload classification | |
| ├── sessionUtils.ts # buildSessionResult snapshot | |
| ├── interactionLogger.ts # Singleton replay-ready event log | |
| ├── mergeAnalysisResult.ts # Step1 + step2 field merge | |
| ├── popoverPlacement.ts # Pin-popover positioning | |
| └── fileRegistry.ts # Structure regression guard | |
| ``` | |
| ## Standalone bundle | |
| `npm run build:standalone` produces | |
| `frontend/dist-standalone/standalone.html` — a single-file HTML with | |
| React + CSS inlined via `vite-plugin-singlefile`. This is the | |
| canonical distribution artifact; the legacy hand-maintained | |
| `standalone_interface.html` has been decommissioned and frozen as | |
| `standalone_interface_legacy.html` at the project root. UI changes | |
| should land only in `frontend/src/` — the bundle inherits them on | |
| the next build. See [`CLAUDE.md`](./CLAUDE.md) for the parity story. | |
| ## Testing | |
| Tests live next to their source file as `*.test.ts` / `*.test.tsx`. | |
| The suite uses Vitest with `jsdom`, `@testing-library/react`, and | |
| `@testing-library/jest-dom`. Heavy mocking is the norm (`vi.mock` | |
| for `../api` and SVG utilities) so component tests never hit the | |
| backend. | |
| Run a single file: | |
| ```bash | |
| npx vitest run src/components/ActionFeed.test.tsx | |
| ``` | |
| Test patterns and the full inventory are documented in | |
| [`../expert_backend/tests/CLAUDE.md`](../expert_backend/tests/CLAUDE.md). | |
| ## ESLint | |
| Flat config (v9+) in `eslint.config.js` with `typescript-eslint`, | |
| `react-hooks`, and `react-refresh`. The code-quality gate | |
| (`python scripts/check_code_quality.py`, CI-enforced) rejects `any` | |
| and `@ts-ignore` in source files — see | |
| [`../CONTRIBUTING.md`](../CONTRIBUTING.md). | |
| ## Recent UX iterations (post-0.6.5) | |
| The following PRs reshaped the look-and-feel of the app without | |
| touching the analysis pipeline. The full retrospective lives in | |
| [`../docs/architecture/development-cycle.md`](../docs/architecture/development-cycle.md) | |
| section 5; design rationale comes from | |
| [`../docs/proposals/ui-design-critique.md`](../docs/proposals/ui-design-critique.md). | |
| - **PR #118 — VL-names toggle.** A `🏷 VL` button next to the | |
| Inspect field hides / shows the voltage-level labels on NAD | |
| diagrams. Hidden labels remain reachable via a native `<title>` | |
| tooltip on each bus circle. New `vl_names_toggled { show }` | |
| interaction event. | |
| - **PR #120 — Design tokens (Phases A → C).** Palette / space / | |
| radius / typography moved into `src/styles/tokens.{ts,css}`. | |
| Components consume `colors.brand`, `space[2]`, `text.xs`… | |
| Hex literals are forbidden outside the token files; SVG | |
| presentation attributes use the `pinColors` family for | |
| Chrome-safe `setAttribute` calls. | |
| - **PR #121 — Progressive-disclosure ActionCard + halo cap.** Action | |
| cards default to a compact summary and expand on demand. The NAD | |
| highlight halo radius is now capped relative to the viewBox so it | |
| cannot swamp the screen at high zoom. | |
| - **PR #122 — Tier warning system + NoticesPanel + diagram legend.** | |
| Replaces the stack of yellow banners with a single `⚠️ Notices N` | |
| pill in the sidebar header that opens a consolidated list (one | |
| entry, one place to dismiss). A unified diagram legend lands at | |
| the bottom-right of the visualization panel. | |
| `uxConsistency.test.tsx` enforces the recommendations going | |
| forward. | |
| - **`fix-notice-panel-overlap` follow-up.** The Notices popover now | |
| renders via `ReactDOM.createPortal(…, document.body)` with | |
| `position: fixed` so it escapes the sidebar's `overflow: hidden` | |
| clip and any ancestor stacking context — the visualization panel | |
| no longer paints over it on narrow sidebars. Right-aligned to the | |
| pill so it grows leftward into the sidebar rather than bleeding | |
| into the diagram. Regression test in `NoticesPanel.test.tsx` | |
| asserts the popover is NOT a descendant of an `overflow:hidden` | |
| ancestor. | |
| ## Further reading | |
| - [`CLAUDE.md`](./CLAUDE.md) — architecture deep dive | |
| - [`../CLAUDE.md`](../CLAUDE.md) — project-wide overview + API table | |
| - [`../docs/README.md`](../docs/README.md) — design, feature and | |
| performance docs index | |
| - [`../docs/architecture/development-cycle.md`](../docs/architecture/development-cycle.md) | |
| — chronological retrospective of all five development phases | |
| - [`PARITY_AUDIT.md`](./PARITY_AUDIT.md) — standalone-bundle parity | |
| audit (Layer 1–4 conformity, regression matrix) | |