docs(agents): update modal-pattern reference + add files-overlay layout
Two updates to AGENTS.md after the files-overlay rewrite: 1. The "canonical pattern" reference at the bottom of the inline-vs- routed modals section pointed at files-overlay.js lines ~599-664. That file is gone. Updated the reference to point at the new single-purpose location: editor.js's document-level click listener and the routedSaveClicked / routedReplaceClicked / routedDeleteClicked functions. 2. Added a "Files overlay: module layout" subsection right after the modals one. Names the four modules under static/js/files-overlay/, what each owns, the window.__filesOverlay action-registry contract, and the recipe for adding a new file-row action. Future agents touching the file manager hit a one-paragraph orientation instead of re-deriving the layout from git log. No behavior change. The "Modals: inline vs routed" decision tree itself stays accurate post-rewrite: editor is routed; new-folder, delete-confirm, conflict stay inline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8dc14f0cca
commit
e1723f751c
1 changed files with 46 additions and 1 deletions
47
AGENTS.md
47
AGENTS.md
|
|
@ -46,11 +46,56 @@ Hooks: `<a data-routed-modal href="<path>">` opens (full-page nav fallback if JS
|
|||
|
||||
- **The outermost element of `{% block content %}` is a `<div>`, NOT a `<dialog>`.** The persistent slot in `base.html` already provides top-layer + backdrop + focus-trap + Esc-to-close semantics. Nested `<dialog>` collapses to 2 px in every browser.
|
||||
- **Close buttons use `data-routed-modal-dismiss`** (NOT the inline-modal attribute). `modals.js` delegates at document level.
|
||||
- **Form-bearing content needs document-level event delegation** for submit/save/delete, gated on `event.target.closest("#modal-content")`. Direct binding to elements in the swapped-in fragment only works in standalone mode — HTMX-swapped content arrives as fresh DOM nodes with no listeners attached. See `files-overlay.js` lines ~599-664 for the canonical pattern (read `data-*` attributes from the swapped DOM, NOT from JS state set during open).
|
||||
- **Form-bearing content needs document-level event delegation** for submit/save/delete, gated on `event.target.closest("#modal-content")`. Direct binding to elements in the swapped-in fragment only works in standalone mode — HTMX-swapped content arrives as fresh DOM nodes with no listeners attached. See `static/js/files-overlay/editor.js`'s document-level click listener + the `routedSaveClicked` / `routedReplaceClicked` / `routedDeleteClicked` functions for the canonical pattern (read `data-*` attributes from the swapped DOM, NOT from JS state set during open).
|
||||
- **CSS classes targeting modal chrome are scoped to the outer slot** — `dialog.modal, div.modal` in `components.css`. The inner content div should NOT carry `class="modal modal-wide"` (the outer dialog owns chrome; otherwise both paint card-in-a-card).
|
||||
|
||||
**Reference:** `docs/superpowers/specs/2026-05-17-url-addressable-modals-design.md` (design + verification matrix) and the plan errata at the top of `docs/superpowers/plans/2026-05-17-url-addressable-modals.md`.
|
||||
|
||||
### Files overlay: module layout
|
||||
|
||||
The file-manager JS for files-type overlays is split across four
|
||||
modules under `l4d2web/l4d2web/static/js/files-overlay/`, all loaded
|
||||
with `defer` from `templates/overlay_detail.html`. They cooperate via
|
||||
the `window.__filesOverlay` action registry that `core.js` sets up:
|
||||
|
||||
- **`core.js`** — manager-element detection (`.files-manager` guard),
|
||||
derived state (`overlayId`, `baseUrl`, `treeRoot`, `csrfToken`),
|
||||
shared helpers (`joinPath`, `parentOf`, `basename`, `humanSize`,
|
||||
`fetchJson`, `postJson`, `postForm`, `refreshFolder`,
|
||||
`findRowByPath`, `cssEscape`, `scheduleRefresh`), and the
|
||||
document-level click listener that dispatches `[data-action]`
|
||||
clicks through `__filesOverlay.handleAction(op, path, actionEl)`
|
||||
into per-feature handlers.
|
||||
- **`editor.js`** — URL-addressable editor only. Handles the new-file
|
||||
route (`/files/new?at=...`), edit route for text + binary
|
||||
(`/files/edit?path=...`), and the save / replace / delete delegated
|
||||
click handlers scoped to `#modal-content`. Registers `"new-file"`
|
||||
and `"edit"` into the registry.
|
||||
- **`dialogs.js`** — the three inline `<dialog>` modals (new-folder,
|
||||
delete-confirm, conflict). Module-scope state per dialog (one
|
||||
delegated listener each, no clone-and-rebind). Exposes
|
||||
`askConflict(path) → Promise<"overwrite"|"keep-both"|"cancel">`
|
||||
on `__filesOverlay` for use by editor.js + uploads.js. Registers
|
||||
`"new-folder"` and `"delete"` into the registry.
|
||||
- **`uploads.js`** — upload queue (concurrency 3, XHR-based progress,
|
||||
`data-upload-id` delegated cancel), drag-drop on `treeRoot`
|
||||
(direct-bound — 5 coordinated events share highlight state), and
|
||||
the `"zip"` registry handler. Exposes
|
||||
`withCollisionSuffix(path) → suffixedPath` for the upload + save
|
||||
conflict paths. Drag-drop on `treeRoot` is the **only** direct-bound
|
||||
listener block in the four modules; everything else is document-level
|
||||
delegation (see escape-hatch comments in-source).
|
||||
|
||||
When adding a new file-row action, the contract is:
|
||||
|
||||
1. Render the `<button data-action="my-op" data-target-path="...">` in
|
||||
`templates/_overlay_file_node.html` (gated on the right capability
|
||||
flag).
|
||||
2. Pick the module that owns the action and register a handler:
|
||||
`fo.registerHandler("my-op", (path, actionEl) => { ... })`.
|
||||
3. The dispatch wiring in `core.js` takes care of catching the click
|
||||
and calling the handler. No new listeners needed.
|
||||
|
||||
### Dev server and filesystem paths
|
||||
|
||||
- **Production paths (`/var/lib/left4me`, `/usr/local/lib/systemd/system`, `/usr/local/libexec/left4me`, `/etc/left4me`) exist only on Linux deploy hosts.** Never create or write to these on a developer machine. They are referenced in `l4d2host/l4d2host/paths.py` and the spec only as the production layout.
|
||||
|
|
|
|||
Loading…
Reference in a new issue