Improve the property panel
Currently, we have 2 panels, one for properties and one for replay. We want to simplify this and reduce it to just the property panel. There should be a mechanism to switch to replay mode within that one panel and to switch back and forth between the 2 modes.
This is a major refactor task and should be managed within a single MR so that we can test and review during the entire process.
---
## Proposed resolution (plan)
Based on @mark_dodgson's comps (2026-06-17), this refactor delivers **two
intertwined improvements**, both landing in a **single MR**:
1. **Collapse the two right-hand panels into one.** Today the modeler renders a
separate replay panel column and a property panel column. The comps show a
single panel with an `Event | Review model` header toggle that flips the same
panel between component properties and replay/listening.
2. **Add an `@`-triggered token picker inside property fields.** Today token
insertion is drag-and-drop only (from the replay panel). The comps show
typing `@` in a field opening a categorized dropdown (Step data / Global /
Template tokens, then sub-categories, then a `Use →` button per token).
A key de-risking finding: the backend already supports everything needed
(`replay_url`, `test_url` polling, session entries, the token tree). This is
almost entirely a frontend reorganization in `ui/` (React/TypeScript); no PHP
changes are required for the core scope.
### Mockup-to-feature mapping (the 10 comps)
| Comp | What it shows | Feature |
|------|---------------|---------|
| Apply tokens (Category dropdown) | `@` opens *Select token category*: Step data / Global / Template | `@` picker top level |
| Apply tokens (Poll for historical data) | Category opens with no cached data → "Polling for data" | `@` picker triggers poll |
| Apply tokens (Select event tokens) | Step-data shows session timestamp + sub-categories with counts | `@` picker drill-down |
| Apply tokens (Use token values) | Leaf tokens each with `Use →` | `@` picker insert action |
| Review model (Default state) | Header toggled to **Review model**; step list with counts | Review mode landing |
| Review model (Initiate event listener) | "Cancel event listener…" (animated), "Listening…", **Live session** | Review mode + live listener |
| Review model (Latest session data) | **Playback controls** (Play + skip-back), session dropdown, first step expanded | Review mode with data |
| Review model (Repoll / retest) | Session menu: **Poll for new data**, **Retest model**, "Available data" timestamps | Review session menu |
| Review model (Use token values) | Expanded token tree with `Use →` per leaf, in Review mode | Review mode token insert |
| Review model (Save model first) | Modal: "Unsaved changes — Save before reviewing the model." `Cancel` / `Save and review model` | Unsaved-changes guard |
### Ideal state criteria
**Unified panel shell**
- One right-hand panel renders; no separate replay column remains.
- Panel header shows a segmented `Event | Review model` toggle.
- Toggle state persists per model session, defaulting to `Event`.
- Existing single-panel resize and collapse behavior is preserved.
**Review mode (replay relocated)**
- Step list (Event/Condition/Action) with counts.
- Session dropdown (Live session + historical timestamps).
- Playback controls (Play, skip-back) when data exists.
- Session menu exposes "Poll for new data" and "Retest model".
- "Cancel event listener…" with animated icon while listening.
- Selecting a step expands its categorized token tree inline.
- Canvas ↔ step selection sync continues to work.
**`@` token picker in property fields**
- Typing `@` in a token-capable field opens a category dropdown.
- Top level lists Step data / Global (n) / Template (n) tokens.
- Drilling into Step data shows session timestamp + sub-categories with counts.
- Each leaf token row has a `Use →` action that inserts the `[token]` at the caret.
- When no step data is cached, the picker offers "Poll for data".
- Existing drag-and-drop token insertion still works (additive, not removed).
- Picker closes on Escape/selection/blur and is keyboard-navigable.
**Unsaved-changes guard**
- Entering Review/Test with unsaved changes shows the guard modal.
- Modal offers `Cancel` and `Save and review model`.
- "Save and review model" saves, then enters Review mode on success.
**Cross-cutting quality**
- All strings via `t()`; US-English spelling.
- Colors use `--modeler-*`; light + dark mode verified.
- WCAG AA: focus, roles, live regions, contrast.
- Zero TypeScript errors, zero ESLint violations.
- Unit + e2e tests updated/added; Storybook stories added.
- Documentation screenshots regenerated.
**Must NOT happen (anti-criteria)**
- Two visible panels must not remain after the refactor.
- Existing drag-and-drop token insertion must not break.
- Replay/test backend endpoints and payload shapes must not change.
- Canvas replay highlighting/sync must not regress.
- Entering review must not silently discard unsaved edits.
- No hardcoded colors; dark mode must not break.
### Resolved decisions (2026-06-25)
1. **Wording:** unify on "Review model" everywhere; no "Test model" string.
2. **Capability gating:** the Review model toggle is **shown but disabled** when
the model is unsupported or unsaved (revisit later if needed).
3. **`@` availability:** the `@` trigger is **always available** in
token-supporting fields (global tokens always exist); the empty step-data
state nudges users to "Review the model" for richer token data.
4. **Live session vs. historical:** "Live session" is the former
test-the-model listener. On entering Review with no data, **auto-start the
listener and pull historical data in parallel**. Listening requires a
**saved** model; historical data loads on **unsaved** models too.
5. **Field coverage:** `@` is available on **all fields that declare token
support** (driven by `token_support`, not field type).
### Phased plan (single MR, sequential commits)
- **Phase 0 — Scaffolding & state.** Add `panelMode: 'event' | 'review'` to the
panel store (persisted); add the header segmented toggle; Review mode renders
a placeholder. No behavior change yet.
- **Phase 1 — Relocate replay into Review mode.** Render the existing replay
content inside the property panel when in Review mode; remove the standalone
replay column from the flow layout. Keep all replay/test hooks lifted and
passed through. Verify canvas sync and indicators are unaffected.
- **Phase 2 — Unsaved-changes guard.** Reuse the existing save/validate/confirm
machinery to gate entry into Review mode.
- **Phase 3 — `@` token picker.** New token-picker component + hook driven from
the content-editable field (`@` keydown → caret-anchored popup). Reuse the
token-tree data the replay renderer already builds, so Review mode and the
`@` picker share one source. `Use →` reuses the existing insertion path.
- **Phase 4 — Polish, a11y, tests, docs.** Dark mode, keyboard nav, ARIA,
contrast; update/add unit + e2e tests and Storybook stories; regenerate
documentation screenshots.
All implementation is in `web/modules/contrib/modeler/ui/` (React/TypeScript).
issue