feat(modules): the list as item rows, and tree: pages | hidden with auto-open, container tabs and a prompt that is a screen #356

Merged
dominik.polakovics merged 1 commit from afk/347 into main 2026-10-24 11:52:32 +02:00

Closes #347

Stacked on #355 (issue #346, the shared item row). This branch contains #355's commit ccf488a. Merge #355 first; after that, this PR's own change is 200e3b8.

What changes

The module list (ModuleScreen.tsx, new ModuleDocheader.tsx and ModulePager.tsx)

  • Page head: the docheader carries the module icon, title (h-section) and count. There is no container badge.
  • New button: one primary "New ". Outside the default language it is disabled and a .note--info above the panel says why.
  • Panel: .page → .panel.
    • Tools: search, filters, and the sort menu in every layout. Column-header sorting is gone; the URL's sort param is unchanged.
    • Body: item rows. title is the label link. status shows as badges, with the tone from Badge.tsx (new badgeTone next to gitBadgeState). The slug is the row id. Other columns go on the summary line, drawn by FieldValueView.
    • Foot: the shared pager.
    • cards keeps its grid, drawn as .item + .item__media.
  • Row actions: Edit, Enable/Disable, ⋮. Enable/Disable comes from pageActionItems/togglePageEnabled, and the ⋮ menu from the docheader's pageActionMenuEntries, which is now exported. Rename and Delete reuse the docheader's dialogs.
  • Untranslated rows: no actions, an italic label, the default language's code tag, the state from translationState, and Translate….
  • States: empty, no-match ("Clear search"), loading and error all use the shared recipes.
  • Retired CSS: .list-table*, .module-toolbar*, .module-pager*, .module-empty*, .module-tag(s), .module-lang-tag, .module-l10n*, .module-card*.

tree: pages | hidden

  • Server: strict decode, default pages. Any other value is a load error: tree must be "pages" or "hidden", got "x". The key sits after pageTypes in the canonical order, and files without it stay byte-identical. GET /api/modules carries it.
  • Client: featureModuleDef sets nav only for pages.
  • The rule's one owner: web/src/modulecontainers.ts (moduleLanding). Containers and entries come from the server's containerFor/managedBy. FeatureModule renders the verdict, and route repair applies it through the new SiteFacts.landing hook, replacing the URL rather than pushing:
    • one container (hidden tree): the URL is repaired to it;
    • several: one tab per container, and the prompt panel while none is named;
    • none: .empty pointing at the Page module;
    • tree kept: docheader plus the prompt panel.
  • Tree rows: rejected rows are muted by colour (--chrome-text-muted in the tree pane, --color-text-muted in the picker), not opacity. Container rows wear the module icon.
  • Entry editor: "All " ghost button and crumbs " › ". return is unchanged.
  • Bundles: forms goes to v3 and categories to v4 with tree: hidden, and their hints are rewritten.

Documents and skills

  • Documents: AGENTS.md "Editor modules" (the key, a rewritten "In the editor", the list anatomy, bundle versions); docs/api.md GET /api/modules; docs/features.md (forms, categories, the one-line edit for installed sites); docs/architecture.md; a new ADR 0029, which narrows #33's rule to "where a choice exists" and records tabs rather than a merged list.
  • Styleguide: item stack and grid, .item__label--untranslated, .item__lang, .item__state, .item__media, .panel__tool, .panel--menus, with samples. New contrast pair: --chrome-text-muted on --chrome-bg-raised.
  • Skills:
    • Changed: create-feature (the tree decision and what the module screen should look like), verify-site (the module smoke test and the one-line fix for older installs), add-page-type (wording only).
    • Checked and unchanged: setup-site (it defers to the bundle hints), edit-content, migrate-site, preview-site.
  • i18n: module.* and feature.* in EN and DE. feature.selectPage and feature.selectTypedPage are removed.

Notes and known gaps

  • The count and empty copy say "entries" (e.g. "5 entries"), and "New " uses the page type's label as written. The payload has no plural noun for a module's entries.
  • containerTypeLabels in FeatureModule.tsx still reads page types to name the container type in the prompt and empty screens. It predates this change. Having the server serve that name is a possible follow-up.
  • .tree-row__label--static and --missing still dim by opacity. They are outside this issue.
  • Badges now carry badge--ok/info/warn/dashed tone classes, but the editor still colours them by state class until the token adoption (E1).
  • The editor stylesheet repeats the shared component rules, as #346 did, because styles.css does not import components.css yet.

Verification

  • tsc clean, vite build ok.
  • vitest: 137 files, 3421 tests passed.
  • go vet ./... clean, and go test ./... passes (including docs, scaffold, internal/server, internal/editormodule, cmd/harness).
  • check-contrast.py: 48 pairs, 0 failing.
  • The issue's grep on ModuleScreen.tsx finds nothing.
  • Not checked in a browser: the screens are covered by the component tests only.

🤖 Generated with Claude Code

Closes #347 **Stacked on #355 (issue #346, the shared item row).** This branch contains #355's commit `ccf488a`. Merge #355 first; after that, this PR's own change is `200e3b8`. ## What changes **The module list** (`ModuleScreen.tsx`, new `ModuleDocheader.tsx` and `ModulePager.tsx`) - **Page head:** the docheader carries the module icon, title (`h-section`) and count. There is no container badge. - **New button:** one primary "New <type>". Outside the default language it is disabled and a `.note--info` above the panel says why. - **Panel:** `.page` → `.panel`. - Tools: search, filters, and the sort menu in every layout. Column-header sorting is gone; the URL's `sort` param is unchanged. - Body: item rows. `title` is the label link. `status` shows as badges, with the tone from `Badge.tsx` (new `badgeTone` next to `gitBadgeState`). The slug is the row id. Other columns go on the summary line, drawn by `FieldValueView`. - Foot: the shared pager. - `cards` keeps its grid, drawn as `.item` + `.item__media`. - **Row actions:** Edit, Enable/Disable, ⋮. Enable/Disable comes from `pageActionItems`/`togglePageEnabled`, and the ⋮ menu from the docheader's `pageActionMenuEntries`, which is now exported. Rename and Delete reuse the docheader's dialogs. - **Untranslated rows:** no actions, an italic label, the default language's code tag, the state from `translationState`, and Translate…. - **States:** empty, no-match ("Clear search"), loading and error all use the shared recipes. - **Retired CSS:** `.list-table*`, `.module-toolbar*`, `.module-pager*`, `.module-empty*`, `.module-tag(s)`, `.module-lang-tag`, `.module-l10n*`, `.module-card*`. **`tree: pages | hidden`** - **Server:** strict decode, default `pages`. Any other value is a load error: `tree must be "pages" or "hidden", got "x"`. The key sits after `pageTypes` in the canonical order, and files without it stay byte-identical. GET /api/modules carries it. - **Client:** `featureModuleDef` sets `nav` only for `pages`. - **The rule's one owner:** `web/src/modulecontainers.ts` (`moduleLanding`). Containers and entries come from the server's `containerFor`/`managedBy`. `FeatureModule` renders the verdict, and route repair applies it through the new `SiteFacts.landing` hook, replacing the URL rather than pushing: - one container (hidden tree): the URL is repaired to it; - several: one tab per container, and the prompt panel while none is named; - none: `.empty` pointing at the Page module; - tree kept: docheader plus the prompt panel. - **Tree rows:** rejected rows are muted by colour (`--chrome-text-muted` in the tree pane, `--color-text-muted` in the picker), not opacity. Container rows wear the module icon. - **Entry editor:** "All <module>" ghost button and crumbs "<module> › <entry>". `return` is unchanged. - **Bundles:** forms goes to v3 and categories to v4 with `tree: hidden`, and their hints are rewritten. ## Documents and skills - **Documents:** `AGENTS.md` "Editor modules" (the key, a rewritten "In the editor", the list anatomy, bundle versions); `docs/api.md` GET /api/modules; `docs/features.md` (forms, categories, the one-line edit for installed sites); `docs/architecture.md`; a new **ADR 0029**, which narrows #33's rule to "where a choice exists" and records tabs rather than a merged list. - **Styleguide:** item stack and grid, `.item__label--untranslated`, `.item__lang`, `.item__state`, `.item__media`, `.panel__tool`, `.panel--menus`, with samples. New contrast pair: `--chrome-text-muted` on `--chrome-bg-raised`. - **Skills:** - Changed: `create-feature` (the `tree` decision and what the module screen should look like), `verify-site` (the module smoke test and the one-line fix for older installs), `add-page-type` (wording only). - Checked and unchanged: `setup-site` (it defers to the bundle hints), `edit-content`, `migrate-site`, `preview-site`. - **i18n:** `module.*` and `feature.*` in EN and DE. `feature.selectPage` and `feature.selectTypedPage` are removed. ## Notes and known gaps - The count and empty copy say "entries" (e.g. "5 entries"), and "New <type>" uses the page type's label as written. The payload has no plural noun for a module's entries. - `containerTypeLabels` in `FeatureModule.tsx` still reads page types to name the container type in the prompt and empty screens. It predates this change. Having the server serve that name is a possible follow-up. - `.tree-row__label--static` and `--missing` still dim by opacity. They are outside this issue. - Badges now carry `badge--ok/info/warn/dashed` tone classes, but the editor still colours them by state class until the token adoption (E1). - The editor stylesheet repeats the shared component rules, as #346 did, because `styles.css` does not import `components.css` yet. ## Verification - `tsc` clean, `vite build` ok. - vitest: 137 files, 3421 tests passed. - `go vet ./...` clean, and `go test ./...` passes (including `docs`, `scaffold`, `internal/server`, `internal/editormodule`, `cmd/harness`). - `check-contrast.py`: 48 pairs, 0 failing. - The issue's grep on `ModuleScreen.tsx` finds nothing. - Not checked in a browser: the screens are covered by the component tests only. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(modules): the list as item rows, and tree: pages | hidden with auto-open, container tabs and a prompt that is a screen
All checks were successful
ci / build-and-test (pull_request) Successful in 4m8s
ci / release (pull_request) Has been skipped
200e3b89da
The module list (ModuleScreen) is redrawn against the styleguide: the
docheader is the page head (module icon, title, count; no container badge)
with one primary "New <type>", disabled with an info note outside the
default language; one .panel in a .page holds the search, filters and a
sort menu for every layout, the entries as item rows (title as the label
link, status as badges from gitBadgeState, the slug as id, every other
column on the summary line), and the shared pager. Row actions are Edit,
Enable/Disable and a ⋮ menu built from pageactions.ts (Rename…, Delete…,
the translation items). Empty, no-match, loading and error use the shared
recipes; the .list-table/.module-* rules and .pane__hint on this screen
are gone.

Module YAML gains `tree: pages | hidden` (default pages; anything else is
a load error), served in GET /api/modules. A tree-hidden module mounts no
tree column and no rail toggle. Which container a module shows when the
URL names none of its own is one rule in web/src/modulecontainers.ts,
rendered by FeatureModule and applied by route repair: one container in a
tree-hidden module is opened (URL replaced); several give a tab per
container in the docheader; none gives an empty screen pointing at the
Page module; a module beside the tree shows the docheader and a prompt
panel listing its containers. Rejected tree rows are muted by colour, not
opacity, and containers wear the module icon. The entry editor goes back
with "All <module>" and the crumbs "<module> › <entry>".

The forms (v3) and categories (v4) bundles ship tree: hidden, with their
hints rewritten. AGENTS.md "Editor modules", docs/api.md, docs/features.md,
docs/architecture.md, the create-feature, verify-site and add-page-type
skills follow; ADR 0029 records the narrowing of #33's rule to "where a
choice exists".

Closes #347

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Author
Owner

[autoland] verdict: pass

PASS. Signal: CI aggregate success, run 372: ci / build-and-test ran npm ci, build and test, then go vet, test and build. That covers the docs, scaffold-skills, route and command drift tests. Conventions: Conventional Commits title; Closes #347 present. The diff matches the issue; #355 is merged, so the PR's own change is 200e3b8 and it merges cleanly. The new rule has one owner, web/src/modulecontainers.ts (moduleLanding), which FeatureModule, routerepair (SiteFacts.landing) and PageTreeNav all call. AGENTS.md, docs/api.md, docs/features.md, docs/architecture.md, ADR 0029 and the skills (create-feature, verify-site, add-page-type) are updated; setup-site, edit-content and migrate-site name no tree step. The new styles.css tokens match tokens.css values. Non-blocking notes the author already lists: not checked in a browser; containerTypeLabels still re-derives container types (this predates the PR).

[autoland] verdict: pass PASS. Signal: CI aggregate success, run 372: ci / build-and-test ran npm ci, build and test, then go vet, test and build. That covers the docs, scaffold-skills, route and command drift tests. Conventions: Conventional Commits title; Closes #347 present. The diff matches the issue; #355 is merged, so the PR's own change is 200e3b8 and it merges cleanly. The new rule has one owner, web/src/modulecontainers.ts (moduleLanding), which FeatureModule, routerepair (SiteFacts.landing) and PageTreeNav all call. AGENTS.md, docs/api.md, docs/features.md, docs/architecture.md, ADR 0029 and the skills (create-feature, verify-site, add-page-type) are updated; setup-site, edit-content and migrate-site name no tree step. The new styles.css tokens match tokens.css values. Non-blocking notes the author already lists: not checked in a browser; containerTypeLabels still re-derives container types (this predates the PR).
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/deckle!356
No description provided.