Skip to content

Site admin: every section in the one dialog, nested rail, and Reports as Insights - #1031

Merged
btopro merged 29 commits into
masterfrom
site-admin-sections
Oct 30, 2026
Merged

btopro merged 29 commits into
masterfrom
site-admin-sections

Conversation

@btopro

@btopro btopro commented Oct 29, 2026 •

Copy link
Copy Markdown
Member

Refs haxtheweb/issues#3180 · Stacked on #1028 (review that first; this PR's base is its branch)

Every Site settings section now renders inside the one admin dialog, with the same rail, header and action bar. This finishes steps 4–9 of the plan. What every section saves is unchanged: payload-parity tests check each save against the old code, and an independent review found no change to any save event or payload.

Plan: https://claude.ai/artifact/18ShB2eZU1XRTA5wEEeLSu · Mockups: https://claude.ai/artifact/AH4sFGWYZH2xHpVZnEoZcB

What moves in

Section Action bar Notes
Appearance form Theme Preview becomes a header action. It asks before leaving unsaved edits, and a pick made in the preview comes back as unsaved changes.
Content selection Replace moves into the bar. The bar counts matched pages ("3 pages match").
Reports none Hosted as is, with its own header. Its redesign is happening in a separate thread.
About none Two columns. Shortcuts get a Global / View / Edit switch.
Files selection Bulk Embed, Scale, Rotate, Transform, Compress, Duplicate, Rename and Delete move into the bar. They go through the same _onFileAction path, with the same prompts.
Views none Embed in page and Create as new page become header actions.
Features form Switch rows. The skeleton export that reuses this element is unchanged.
Editor form One field row, plus the toolbar preview.
Blocks form Changes are summarised for long lists ("12 unsaved changes"). Changed marks only show inside the dialog.
SEO / Author form Author is now a child route of SEO, so both groups are in one section.
Import / Export none Compact cards. The same 17 actions send the same details.
Details form Moved in #1028.

Still opening their own dialogs:

  • Structure's import step: it still opens as its own dialog. (Structure moved in in Round 5, Page history in Round 6.)
  • Revisions: being redesigned in a separate thread.
  • Theme preview: stays full-screen.

What it touches (all in elements/haxcms-elements)

  • lib/core/admin/site-admin-sections.js
    • Every section except Structure gets a tag, a loader and an action-bar mode.
    • Author becomes a child route of SEO (resolveSiteAdminRoute).
    • New header: false flag for Reports, which draws its own header.
  • lib/core/admin/haxcms-site-admin.js
    • A configureSection hook, called before a section connects.
    • reload().
    • A selection bar (selected, actions, selectionText; runAction, clearSelection).
    • Header actions (headerActions, runHeaderAction).
    • An optional change count.
    • color-scheme follows the HAX UI theme switch, so light-dark() matches the --hax-ui-* colours.
  • lib/core/haxcms-site-editor-ui.js
    • The openers for moved sections now just sync the route and show the shell.
    • Per-open values and listeners from the old openers move into _configureSiteAdminSection.
    • Labels move into _siteAdminRouteMeta.
    • Reopening a section always builds it fresh, and asks first if it is on screen with unsaved edits.
    • Removes 11 inline modal style blocks.
  • lib/core/haxcms-site-editor.js
    • New _requestAdminSave: SEO, Appearance, Features, Editor and Blocks now report haxcms-admin-save-result, like Details.
    • Every early return reports a failure.
    • Request IDs, operations and payloads are unchanged.
  • The 10 section files: each implements the section contract when inShell. Standalone use (outside the dialog) keeps its title, Save button and close-after-save.
  • Tests
    • New section suites: SEO, Editor, Blocks, Features, Appearance, Files, Content, and the sections with no action bar.
    • Shell tests for configure, child routes, header, reload, header actions and the selection bar.
    • Save-result tests for every admin save.
    • The full haxcms-elements suite passes: 40 files, ~800 tests. yarn precheck passes.

Verified in the running app

I ran this against haxcms-nodejs main with these files overlaid into its build.

  • Screenshots: every section in light and dark mode.
  • Settings e2e (Details, SEO, Theme, Blocks/Editor) pass with the companion PR. Blocks/Editor fails on main today.
  • Related e2e: outline import/ops, revisions, files ops/phase 2, export site and formats, edit content, and page management all pass (29 tests).
  • Reopen check: open Appearance, close, reopen with a preview pick. The section is built fresh, and Save lights up with "Theme".

Decisions for review

  • Files: Scale, Transform and Compress, and Embed with two or more images, open a small option panel above the bar. The options are the same as before; only the panel is new.

  • Content: Clear empties the find text, the replacement and the matches, because Content has no row checkboxes.

  • Features: there is no "Download skeleton" header action. The mockup shows one, but platform mode never had it, so adding it would be new capability.

  • Shared widgets that still look heavy inside SEO:

    • hax-upload-field's "Image info" bar.
    • haxcms-language-picker's larger text. It has no hide-label option, so its label is hidden with a size workaround.

    These are follow-ups in those components.

Follow-ups

  • Structure (plan step 10). Done in Round 5.
  • Fit Reports and Revisions to the contract when their redesigns land.
  • Cleanup (step 11): remove haxcms-site-settings-dashboard and the remaining per-section .actions CSS.
  • Locales for the new strings.

Round 2: nested rail, Reports (Insights), and review answers

Also linked to this PR: the Insights plan, HAX Insights: front-end-first work plan, with its mockups at https://claude.ai/artifact/45htsypdE83WrQ39y2zEJr. The spec gaps it raises belong on haxtheweb/haxcms-plugin-examples#1 and haxtheweb/issues#3176.

Nested rail (any section). Registry entries can list children:

  • Route children open their own page: Reports' nine screens, and SEO's Author.
  • Anchor children are headings inside a section: About, Import / Export, SEO, Details, Features and Appearance. Clicking one scrolls to the heading and opens it if it's a collapsed group.
  • Sections expand and collapse, and the rail remembers what you opened. The section you're in opens automatically.
  • Hovering a section in the rail or on a launcher card lists what it includes.
  • A section can show counts on its parts (railBadges).

Reports, rebuilt as Insights. Everything runs in the browser, with no server change.

  • lib/core/insights/:
    • insights-spec.json: thresholds and word lists.
    • A pure analyzer that turns page facts into site results.
    • A module worker, started without a blob: probe because HAXcms's CSP refuses blob: workers, with a main-thread fallback.
    • A loader: the whole-site HTML export or per-page content, plus same-origin robots.txt and llms.txt.
    • CSV builders.
  • haxcms-site-reports holds the scope, Rescan, Export CSV and density controls and a status line. One scan is kept while you move between screens.
  • Nine screens, each its own route (?admin=admin-reports-<id>), gated like Reports: Overview, Accessibility (the alt-text review table with live Fix / Check / Looks OK), Content, Links, Media, Instructional, Freshness, Metadata and Components.
  • Server-only features are disabled and marked "Coming soon", saying what they need and never naming a plugin: outside link status, YouTube captions and length, bulk alt save, media index rebuild, history, schedules, threshold settings, and the CLI.
  • Left in place: /x/api/v1/reports and the old haxcms-site-insights element. The UI now uses the new screens.

Answers from review

  • Content: each matching page gets a checkbox, all checked by default. Replace runs on the checked pages only. With every page checked, the request is exactly the old one; a subset sends nodeIds, which is new in Site admin: e2e for the one dialog, plus optional nodeIds on content replace haxcms-nodejs#157 and mirrored in siteSearch replace: optional nodeIds (site admin Content page checkboxes) haxcms-php#716. The bar shows "N of M pages selected" and Clear unchecks. Trade-off: no column sorting while replace results are listed.
  • SEO:
    • hax-upload-field gains opt-in compact and label-hidden.
    • haxcms-language-picker gains label-hidden and sizing custom properties.
    • Defaults are unchanged for every other consumer, and tests check that.
    • The hax-body docs data has been rebuilt.
  • Skeleton download: already on Import / Export as "Export site skeleton", using the same skeleton export.
  • Files: the option panel stays, for review on the preview.

Fixed along the way: Blocks' category headings are now h3 under the dialog's h2; they were h4, which skipped a heading level.

Tests: the full haxcms-elements suite (975 tests) passes three runs in a row. Precheck passes. The settings e2e tests pass against haxcms-nodejs main with these files applied.

Round 3: order, Reports first, icons, Content and Views redesigns

  • Opens on Reports. Site settings now opens on Reports, the site's dashboard. Reports is its own overview, and the rail lists its eight other screens under it. The card launcher only appears if Features turns Reports off.
  • Order follows other CMS admin menus (WordPress, Drupal, Grav):
    • Main: Reports, Content, Structure, Files, Appearance.
    • Advanced: Views, Blocks, Features, Details, Editor, SEO, Import / Export.
    • About: on its own at the bottom.
  • Titlebar: simple-modal gets opt-in hooks for title size, weight, icon size, close-icon size and breadcrumb spacing. Every other modal keeps its current look by default. The admin dialog uses the HAX UI scale, and the title icon lines up with the rail icons.
  • Admin icons: 47 hax:admin-* glyphs added to hax-iconset, all to one spec: 24×24, one filled path, ~2px weight, readable at 14–16px, based on Material Design Icons (Apache-2.0, credited in the README). Every icon in the dialog, including the section parts in the rail, now uses them. The spec is documented under "Admin icons" in hax-ui-admin.md.
  • Content redesign:
    • One toolbar of 32px controls, a summary line with paging, and a native table with status pills, relative dates and a labelled Revisions button. Sorting now covers every filtered page before paging.
    • Empty, loading and error states.
    • Replace keeps the page checkboxes and sends the same events.
  • Views redesign:
    • The builder (Source, Show, Filter, Sort groups) sits beside a framed preview.
    • The query path is shown with a Copy path button.
    • The rail lists its four groups.
    • The query, embed and create-page output is unchanged.
  • Tests: 995 in haxcms-elements pass, two runs in a row. Precheck passes.
  • One titlebar for every admin screen. SITE_ADMIN_TITLEBAR_STYLES sets it for the one dialog and for the screens not in it yet: Structure, its import step and Revisions. Their modal styles are the only change; outline designer and its save path are untouched. The outline import, outline ops and revisions e2e tests pass.
  • Breadcrumb spacing. simple-modal gets two more opt-in hooks: the gap between a breadcrumb's icon and its text (default 0) and the title text's vertical nudge (default 2px, today's value). The admin titlebar uses 6px and 0, so icons, text and the > separator line up evenly.
  • Verified against haxcms-nodejs main with these changes applied:
    • All four settings e2e tests and the outline import, outline ops and revisions e2e tests pass.
    • The unit suites pass: haxcms-elements (995 tests) and simple-modal.

Round 4: Dashboard and nesting

  • Reports is labelled Dashboard everywhere: rail, header, titlebar and breadcrumbs (Dashboard › Accessibility, …), since Site settings now opens on it. Routes stay ?admin=admin-reports(-<screen>), so existing links keep working.
  • Tree-style nesting: a section's parts sit one --hax-ui-indent in. A guide line runs down from the section's icon with a tick into each part, the same treatment outline-designer uses for its tree. The narrow icon-only rail drops the indent.
  • No repeated parts: Details and SEO no longer list themselves as their first part. Opening the section shows that content, and the rail lists only the other parts (Advanced, Author). A test makes sure no section lists itself as a part.

Round 5: Structure in the dialog, collapsible rail

  • Structure is a section of the dialog. outline-designer now sits beside the rail like every other section. The outline dialog keeps its own Save Outline button, its confirm and the same haxcms-save-outline payload. The shell only fills its body with it (registry fill: true, no action bar), so the save and failure behaviour don't change.
  • One leave check for Structure. A section that keeps its own save can expose hasUnsavedChanges and confirmLeave(). The shell's requestLeave (rail, breadcrumb, browser back) and the editor's guard call it, so you're asked once, in the same words as before. The close button still runs the dialog's own guard, which now also works when the dialog is the shell's child.
  • Collapsible rail. A button at the top of the rail collapses it to icons and opens it out again, using hax:admin-rail-collapse / hax:admin-rail-expand (new in the hax iconset). The choice is kept per browser.
    • Collapsed, every section icon stays, plus the open section's parts in one outlined group.
    • Each icon shows its name in a tooltip on hover and on keyboard focus. Esc hides it.
    • Badges become a dot on the icon.
  • Narrow screens (768px and less): the rail starts as icons and opens over the section with a scrim. It closes when you pick a section, press Esc or click outside. This replaces the forced icon rail at 1080px and the horizontal strip on phones.
  • Documented in hax-ui-admin.md (Section rail, the new icon names, a proposed --hax-ui-rail-width-collapsed token).
  • Tests:
    • haxcms-elements unit suite: 1007 pass, including new tests for the rail and Structure in the shell.
    • haxcms-nodejs e2e against this build: outline import, outline ops (rename, reorder, nest/unnest), revisions, Details, and Blocks + Editor settings all pass (11/11). Blocks + Editor failed once in an earlier back-to-back run, then passed alone and in a full rerun.
    • precheck passes.

Round 6: Page history (revisions) redesign

Revisions is now Page history, a part of Content in the dialog (?admin=admin-content-revisions), following the design in haxtheweb/issues#3191 and the clunky-UI report in haxtheweb/issues#3025.

  • Timeline.

    • Versions are grouped by day, in git's order.
    • Each row says what changed in words ("Content edit", "Find and replace", "Outline change", "Restore", "Site created"…) and who made it.
    • Pills mark the current version, AI-agent edits (actor A), system updates (S), and changes made outside HAX (X, labelled "Not labelled").
    • Filter chips (All / Content / Structure / Page details / Restores) show counts, and older versions page in.
  • Labels come from the [actor:op:txn] commit prefix. The screen uses the backend's parsed fields when it sends them (haxcms-php, and haxcms-nodejs once haxcms-nodejs#151 lands), and parses the message itself otherwise. History from before op codes gets its labels from HAX's own commit wording.

  • One version.

    • "This change" compares it with the version before it. "Compare with now" shows what a restore would bring back or remove.
    • Each comparison can show as a word diff, the rendered version, or an HTML line diff. Long unchanged stretches collapse.
    • Changes to title, description, address, published, hidden and locked are listed in a table.
    • Structure-only changes say the content wasn't edited.
    • Technical details show the op, actor, request id, commit and full message.
  • Restore explains itself instead of using confirm(). It says:

    • what goes back, with word counts;
    • that the title and description go back too, when that version saved them;
    • what stays;
    • which later changes it undoes, and by whom;
    • that nothing is deleted;
    • the commit line it records.

    A failed restore now says so: haxcms-site-editor fires haxcms-node-revision-restore-failed instead of leaving the screen spinning.

  • Shell additions.

    • A route child can render its own screen (registry tag/load/footer/fill on a child, read through siteAdminRouteView).
    • A section can name what it shows in the dialog header (headerText in haxcms-admin-section-state).
  • No backend change. It uses the same events and API, so nothing needs mirroring in PHP.

  • Not covered yet (needs Node + PHP):

    • Moves and renames that only touch site.json don't appear, because the list only includes commits that touched the page file.
    • A restore note field.
    • A compare endpoint.

    Both are in #3191.

  • Tests:

    • haxcms-elements unit suite: 1027 pass, plus new model and screen tests.
    • The haxcms-nodejs revisions e2e (updated in haxcms-nodejs#157) passes 7/7 against this build, with 0 accessibility violations. Its visual baseline needs a refresh for the new screen.
    • precheck passes.

Round 7: phones, and a bigger dialog everywhere

  • Dialog size.
    • The admin dialog takes nearly the whole screen. The margin grows from 0 on a phone to 32px on a wide screen (clamp(0px, 2vw - 8px, 32px)), up to 1680px wide, and the corners go from square to 8px the same way.
    • These values live in SITE_ADMIN_MODAL_SIZE, which Structure's import step uses too.
    • simple-modal gains opt-in --simple-modal-border-radius and --simple-modal-container-padding. web-dialog's 5vw 24px stays the default.
  • Structure.
    • The page header is dropped, since the titlebar names it.
    • Save Outline moves into outline-designer's toolbar through a new actions slot, so there is no footer bar. It's the same button, confirm and save.
    • When the designer is narrow (a container query at 640px), the toolbar fits one row: Add page, Options and Save. Options holds Collapse all, Expand all, density, Import and keyboard shortcuts.
    • Keyboard shortcuts are hidden on narrow screens unless asked for (show-hints).
    • Outline import and outline ops e2e both pass.
  • Shell on narrow screens.
    • The page header shrinks to a title and one line of help.
    • The selection bar keeps its first action and puts the rest under More.
    • Rail tooltips appear on focus only after keyboard use, so opening the dialog doesn't drop one over the page.
  • Blocks.
    • One compact list of rows on every screen size: checkbox, icon, title, a two-line description, and preview.
    • Categories are collapsible rows with an "N of M on" count and their own select all / deselect all.
    • The preview opens inside the section (a sheet on phones, a clamped panel on desktop) instead of running off screen.
  • Files.
    • Below 720px of section width, Files shows cards and one compact filter row instead of the squeezed table. Each card has a thumbnail or file-type icon, a one-line name, and the type, size and age.
    • The desktop table is unchanged.
  • Tests:
    • Unit suites: haxcms-elements 1043, outline-designer 198 (new narrow toolbar tests), simple-modal 93.
    • haxcms-nodejs e2e: outline import, outline ops, revisions, Blocks + Editor and Details all pass (11/11).
    • precheck passes.

https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk



Generated by Claude Code

@vercel

vercel Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
webcomponents Ready Ready Preview Oct 30, 2026 5:48pm UTC

Request Review

@btopro btopro changed the title Site admin: every section in the one admin dialog Site admin: every section in the one dialog, nested rail, and Reports as Insights Oct 29, 2026
@btopro
btopro added this pull request to stack #1036 October 29, 2026 18:44
@btopro
btopro force-pushed the site-admin-sections branch from a7ae83c to 6604535 Compare October 30, 2026 01:08
btopro pushed a commit to haxtheweb/haxcms-nodejs that referenced this pull request Oct 30, 2026
The revisions dialog is now Page history inside the site admin dialog
(haxtheweb/webcomponents#1031): a timeline of version rows and one
Restore button for the version on screen. The UI check now asserts it
renders in the dialog, opens on the current version with Restore off,
and that choosing an older version shows its change with Restore on.
The API checks are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
Base automatically changed from site-admin-shell to master October 30, 2026 17:45
Every Site settings section except Structure now renders inside
haxcms-site-admin: Appearance, Content, Reports, About, Files, Views,
Features, Editor, Blocks, SEO (with Author as its child route), Import /
Export and Details. Each opener syncs the route and shows the shell; the
per-open values and listeners the old openers set move into one
_configureSiteAdminSection. The shell gains a selection bar, header
actions and reload(). Every admin save (SEO, Appearance, Features,
Editor, Blocks, Details) now reports haxcms-admin-save-result through one
_requestAdminSave wrapper; requests and payloads are unchanged.

Structure, its import step, Revisions and the theme preview keep their
own openers. Refs haxtheweb/issues#3180.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
…on contract

The five settings sections stage edits, mark changed fields, report state
to the one admin dialog and save through its action bar. Each save()
fires the same haxcms-save-* event with the same detail as its old Save
button; payload-parity tests pin that. Standalone use (outside the shell,
including the skeleton export that reuses haxcms-site-platform-ui) keeps
its own title, Save button and close-after-save. Appearance's Theme
Preview becomes a header action that asks before leaving unsaved edits,
and a preview pick counts as unsaved changes. The shell accepts an
optional change count for summarised lists (Blocks). Refs
haxtheweb/issues#3180.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
claude added 25 commits October 30, 2026 13:45
- Reopening the section the dialog last showed (after it closed, or while
  it is on screen) builds it fresh, so it gets that open's values: a theme
  picked in the full-screen preview comes back as unsaved changes, and a
  Reports page scope is not stale. While on screen it asks first when the
  section has unsaved edits.
- Blocks shows changed marks only inside the admin dialog, so app-hax's
  system blocks screen (which extends it) shows none on load.
- Editor and SEO discard put a select the person changed back to the
  loaded value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
hax-upload-field gains opt-in compact and label-hidden (URL and media
buttons on one 40px row, a 32px Image info row, HAX UI colours when the
host defines them); haxcms-language-picker gains label-hidden and size
custom properties. Defaults are unchanged for every other consumer, with
tests pinning them. The SEO section uses both and drops its label-size
workaround. simple-file-upload exposes its drop zone as a part.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
In Search and replace mode each matching page gets a checkbox (all
checked after every search) and a select-all header checkbox. The admin
dialog's bar shows "N of M pages selected"; Clear unchecks; Replace is
disabled with nothing checked. With every match checked the replace
event and request are exactly as before; a subset adds nodeIds, which
haxcms-nodejs and haxcms-php now accept on replaceContent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
Foundation for the Reports section's nine Insights screens, computed in
the browser from routes both backends already serve (no server change):
insights-spec.json (thresholds and word lists), a pure analyzer (page
facts -> site results for Overview, Accessibility, Content, Links, Media,
Instructional, Freshness, Metadata, Components), a module worker with a
main-thread fallback, a loader (whole-site HTML export or per page,
plus same-origin robots.txt / llms.txt), and CSV builders. Server-only
features are reported as unavailable with what they need. Screens follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
The rail lists a section's parts under it. A section opens out (and the
rail remembers it); the section you are in opens automatically. Parts are
either their own pages (Reports' nine screens, SEO's Author) or headings
within the section (About, Import / Export, SEO, Details, Features,
Appearance), which the dialog scrolls to and opens. Hovering a section
in the rail or on a launcher card lists what it includes, and a section
can put counts on its parts (railBadges).

Reports now opens haxcms-site-reports, which runs the Insights analyzer
in the browser and shows one screen per route (reports, reports-<id>,
each with its own ?admin= address, gated like Reports). One scan is kept
while you move between screens; Rescan, scope, Export CSV and density
sit in its controls bar. /x/api/v1/reports and the old element are left
in place. Screens follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
Built from the Insights analyzer's results on the HAX UI admin layer:
Freshness (timeline, age of pages, term-specific pages, bulk saves, every
page's dates; edit history and reminders as Coming soon), Metadata (each
check in words, pages without a description, shared and generic titles),
Components (HAX and HTML elements used, flags, suggestions). Tests on the
fixture site, including accessibility checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
Links (findings with an errors/warnings/info filter, hosts the site leans
on, embed hosts, outside links; outside link status Coming soon), Media
(videos per page, pages without media, media by section, media index
check; video minutes and index rebuild Coming soon), Instructional
(activity map, practice per section, weeks without practice, Bloom levels,
objectives, walls of text; thresholds Coming soon). Tests on the fixture
site, including accessibility checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
Overview (key numbers, fix next, site health checks, folders), Accessibility
(KPIs, the alt text review table with live Fix / Check / Looks OK status as
you type, WCAG criteria, heading errors, contrast; Save alt text and YouTube
captions Coming soon), Content (sections, longest and thin pages, read
time, reading grade, every page). Tests on the fixture site, including
accessibility checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
A strict Content Security Policy (HAXcms sends one) refuses blob: workers,
so the support probe logged a violation on every scan. Module support is
now read from the real same-origin worker's options; a browser without
module workers falls back to the main thread as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
Analyzer: every page row carries slug and title; findings and component
flags carry pageList (capped by the spec) so screens open pages directly;
results.thresholds exposes the spec values screens describe in words;
term-specific pages also match dates and semesters in body text, with a
snippet; freshness age buckets get a tone; flags name their tags. Site
health is null ("Nothing to check yet") when nothing is measurable; rail
badges are null when there is nothing to flag; singular/plural text
throughout. Screens drop their own slug lookups and hard-coded numbers.

Blocks: category headings are h3 under the dialog's h2 (was h4, which
skipped a level inside the admin dialog).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
… titlebar

- Site settings opens on Reports, the site's dashboard (the card launcher
  stays as the fallback when Features turn Reports off). Reports itself is
  the overview, so its rail lists the eight other screens.
- Order follows WordPress, Drupal and Grav: Reports, Content, Structure,
  Files, Appearance; then Advanced: Views, Blocks, Features, Details,
  Editor, SEO, Import / Export; then About on its own at the bottom.
- Titlebar: simple-modal gains opt-in hooks for title size, weight, icon
  size, close icon size and breadcrumb spacing (defaults unchanged for
  every other modal). The admin dialog uses the HAX UI scale, with the
  title's icon in line with the rail's icons.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
47 glyphs (24x24, single filled path, currentColor, ~2px weight, 2px
padding, readable at 14-16px, from Material Design Icons) for every
section, Reports screen, section part and shell action in the admin
dialog. The registry, rail, titlebar, breadcrumbs, Reports and the
converted sections now use them. The spec and names are documented in
the HAX UI admin layer doc (hax-ui-admin.md, "Admin icons").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
Theme, Palette, Branding, Regions, About's four parts, Features' two
groups, SEO, Import / Export's three groups and Details' two groups get
their hax:admin-* icons, so they stay visible in the narrow icon rail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
One wrapping toolbar of 32px controls (Search / Search and replace,
search field, filter and match type, a case-sensitive switch), a summary
line with paging, and a native HAX UI table: sticky header, status pills,
relative dates with the full date on hover, muted parent and slug, and a
labelled Revisions icon button. Sorting keeps the same columns and cycle
and now sorts every filtered page before paging. Empty, loading and error
states. Replace mode keeps the page checkboxes and sends the same events
and details as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
A builder (380px) beside the preview, stacking on narrow screens. The
builder has four collapsible groups (Source, Show, Filter, Sort) with
counts in their headers, field rows with 40px controls, a two-column field
checklist, an ascending / descending control, and the query path in mono
with Copy path. The preview gets a slim header (records shown, Display as,
refresh) and a bordered surface, plus loading, empty and error states.
The query, embed, create-page and copied text are unchanged. The rail
lists Views' four groups as its parts.

Also: tests follow the hax:admin-* icon names, and the SEO shell audit
ignores the shared upload field's known autocomplete value, as the
section's own audit already did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
SITE_ADMIN_TITLEBAR_STYLES holds the admin titlebar (colour, 48px height,
padding, 16px title, 18px icons, breadcrumb spacing). The one dialog uses
it, and so do the screens not in it yet: Structure, its import step and
Revisions. Only their modal titlebar styles change; outline designer and
its save path are untouched (outline import/ops and revisions e2e pass).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
simple-modal gains two more opt-in hooks: the gap between a breadcrumb's
icon and its text (default 0) and the title text's vertical nudge
(default 2px, today's value). The admin titlebar sets 6px and 0, so
icons, words and the separator sit on one line with even spacing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
- Reports is labelled Dashboard (rail, header, titlebar and breadcrumbs:
  Dashboard › Accessibility...), since Site settings now lands on it. The
  routes stay ?admin=admin-reports(-<screen>) so existing links work.
- A section's parts sit one indent (--hax-ui-indent) in, under a guide
  line from the section's icon with a tick into each part, the way
  outline-designer draws its tree. The narrow icon rail drops the indent.
- Details and SEO no longer list themselves as their first part; opening
  the section shows that content, and only the other parts (Advanced,
  Author) are listed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
Structure (outline-designer) is now a section of the one admin dialog, so
the rail sits beside it like every other section. The outline dialog keeps
its own Save Outline button, confirm and haxcms-save-outline payload; the
shell only fills the body with it (registry `fill: true`, no action bar).
Its leave checks go through the shell: a section with its own save can
expose `hasUnsavedChanges` and `confirmLeave()`, which the shell's
requestLeave (rail, breadcrumb, browser back) calls, so the question is
asked once, in the same words as before. Closing the modal still runs the
dialog's own guard, now also when it is the shell's child.

The rail collapses to icons and opens out again from a button at its top
(hax:admin-rail-collapse / -expand, new in the hax iconset); the choice is
kept per browser. Collapsed, every section icon and the open section's
parts stay, each named in a tooltip on hover and keyboard focus (Esc hides
it), and badges become a dot. At 768px and narrower the rail starts as
icons and opens over the section with a scrim until a pick, Esc or a click
outside. This replaces the old forced icon rail at 1080px and the
horizontal strip on phones. Documented in hax-ui-admin.md (Section rail).

Tested: haxcms-elements unit suite (1007 pass, new rail and outline shell
tests), and haxcms-nodejs outline-import and outline-ops e2e against this
build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
…self

Revisions is now Page history, a part of Content in the one admin dialog
(haxtheweb/issues#3191, #3025). Route children can now render their own
screen (registry `tag`/`load`/`footer`/`fill` on a child, read through
siteAdminRouteView), and a section can name what it shows in the dialog
header (`headerText` in haxcms-admin-section-state).

- Timeline grouped by day, newest first, with filter chips (All, Content,
  Structure, Page details, Restores) and counts. Each row says what the
  change was in words ("Content edit", "Find and replace", "Outline
  change", "Restore"...), who made it, and flags AI-agent edits, system
  updates and changes made outside HAX. Older versions page in.
- Labels come from the [actor:op:txn] commit prefix: from the backend's
  parsed fields when it sends them, otherwise parsed here. History from
  before op codes is labelled from HAX's own commit wording.
- One version: "This change" (against the version before it) or "Compare
  with now" (what a restore would bring back or remove), shown as a word
  diff, the rendered version, or an HTML line diff. Long unchanged
  stretches collapse. Title, description, address, published, hidden and
  locked changes are listed in a table. Technical details hold the op,
  actor, request id, commit and message.
- Restore asks in place of confirm(): what goes back (with word counts),
  that title and description go back when the version saved them, what
  stays, which later changes it undoes and by whom, that nothing is
  deleted, and the commit line it records. A failed restore now says so
  (haxcms-node-revision-restore-failed from haxcms-site-editor) instead of
  spinning.

Same events and API as before; no backend change.

Tested: haxcms-elements unit suite (1027 pass, new model and screen
tests), haxcms-nodejs revisions e2e against this build (7/7, a11y 0).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
- Versions stay in the order git lists them. "This change" compares each
  version with the one before it in history, so a commit with an out of
  step date (a rebase, a clock, a backdated import) no longer gets
  compared with the wrong version.
- HAX's site creation commit ("A new journey begins") reads as Site
  created instead of Outside HAX.
- A change with no text edits says so instead of drawing an empty diff.
- HTML diffs and technical details use a monospace stack (the DDD
  secondary font is a serif); diff text no longer picks up template
  indentation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
- The admin dialog takes nearly the whole screen: the margin grows from 0
  on a phone to 32px on a wide screen (up to 1680px wide), corners square
  to 8px the same way (SITE_ADMIN_MODAL_SIZE, also used by Structure's
  import step). simple-modal gains opt-in --simple-modal-border-radius
  and --simple-modal-container-padding (web-dialog's 5vw 24px stays the
  default).
- Structure: the titlebar names it, so the page header is gone, and Save
  Outline moves into outline-designer's toolbar (new `actions` slot), so
  there is no footer bar either. Same button, same confirm, same save.
  On a narrow designer (container query, 640px) the toolbar is one row:
  Add page, Options and Save; Options holds Collapse all, Expand all,
  density, Import and keyboard shortcuts, which are hidden on narrow
  screens unless asked for (show-hints).
- Shell on narrow screens: a compact page header; the selection bar keeps
  its first action and puts the rest under More; rail tooltips on focus
  only appear after keyboard use, so opening the dialog does not cover
  the page with one.
- Blocks: one compact list of rows on every size (checkbox, icon, title,
  two-line description, preview), categories as collapsible rows with an
  "N of M on" count and their own select / deselect all, and a preview
  that opens inside the section (a sheet on phones, a clamped panel on
  desktop) instead of running off screen.
- Files: below 720px of section width, file cards (thumbnail or file-type
  icon, one-line name, type, size and age) and one compact filter row
  instead of the squeezed table; the desktop table is unchanged.

Tested: haxcms-elements 1043, outline-designer 198 (new narrow toolbar
tests), simple-modal 93; precheck.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
Tighter button padding in narrow bars, and the selection count no longer
shrinks, so "2 selected", Clear, the first action and More fit one row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvVUkTpLX8DucJwVoaVk
@btopro
btopro force-pushed the site-admin-sections branch from 9fbc23b to e1c2916 Compare October 30, 2026 17:46
@btopro
btopro merged commit 7c1697e into master Oct 30, 2026
10 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 30, 2026
@btopro
btopro deleted the site-admin-sections branch October 30, 2026 18:03

This branch was successfully deployed

1 active deployment
Preview — e1c2916f Deployed Oct 30, 2026 by vercel[bot]
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants