Skip to content

Let every pane name itself, and shrink the dialog's header to suit - #1350

Merged
JeroenDeDauw merged 1 commit into
1328-schema-badgefrom
1328-pane-header
Sep 6, 2026
Merged

Let every pane name itself, and shrink the dialog's header to suit#1350
JeroenDeDauw merged 1 commit into
1328-schema-badgefrom
1328-pane-header

Conversation

@alistair3149

Copy link
Copy Markdown
Member

For #1328

Stacked on #1345 — its base is 1328-schema-badge, because this uses the badge that PR adds.
Review that one first; this diff is only the commit on top.

The dialog's header named the root Subject and carried the field that renamed it, so a nested
pane could not be renamed at all and the header described a Subject the user might not be looking
at. It named the root's Schema too, with the same problem. Neither could follow the active pane:
title is a CdxDialog prop, so binding it re-renders the dialog, and under the spec suite's
teleport stub that remounts every pane.

So the header stops naming anything. Its title is the task — "Edit subject" — and the Subject's
name, its rename control and its Schema move into the pane that edits them, where they are correct
by construction.

Decisions worth challenging

The Schema is a link that usually does not navigate. It is the badge from #1345, so it carries
that component's interactive styling honestly rather than being a styled span with a click handler.
A plain left click opens the Schema editor, as the old header link did; a modified or middle click
is left to the browser, so the Schema page stays reachable and unsaved work is never at risk from
the primary gesture. Only the root pane offers the editor, since that is the Schema
SchemaEditorDialog is bound to — a nested pane's badge is a plain link. The Schema editor itself,
and the onSaveSchema prop three call sites pass, are untouched.

The header keeps a title rather than losing one. "Edit subject" names the task, which is the
only thing about this dialog that does not change as panes are switched. neowiki-subject-editor-title
therefore takes no parameter now, and the dialog's accessible name and its visible heading say the
same thing. A header that named the active pane would have to re-render CdxDialog.

The root pane keeps no "Stored on" line. The root's Subject is on the page the editor was
opened from, so the line would say what the reader already knows. SubjectEditPane.spec asserted
that before this change and still does.

What the header costs now

49px, against the 81px a title over a subtitle needed — align-items: center and
padding-block: @spacing-50, since the row is one line of static text beside a 32px close button.
The two rules that existed to space the old title/subtitle pair go with it, as does the
&-schema block.

In the pane, the name takes the free space so the Schema and the storage line sit flush to the end,
and the row wraps rather than crushing either side once the pane is narrow enough — measured, it
holds one line down to about 260px and wraps by 200px.

Testing

1858 tests pass. Five existing tests asserted the old arrangement — the root pane being unnamed and
without a rename control, the schema link living in the dialog header, and the dialog's accessible
name carrying a Subject's display name. Each was rewritten to pin the new contract rather than
deleted, and two were added for the click behaviour: that a user who cannot edit the Schema is left
to navigate, and that a modified click is too.

Manual Browser Check

On a wiki with the demo data, logged in as a user who may edit Schemas:

  1. Open ACME Inc and click the infobox pencil. The dialog header is one shallow row reading
    Edit subject, with no Subject name and no Schema.
  2. The form's own header reads ACME Inc with a pencil, and a Company badge flush right.
    The badge is blue — it is a link.
  3. Click the badge. The Schema editor opens; the page does not navigate.
  4. Ctrl-click or middle-click it instead. Schema:Company opens in a new tab and the Schema editor
    does not open.
  5. Click a child row in the navigator. That pane names itself, shows its Schema, and adds
    "Stored on ". Rename it from its own header — this was impossible before.
  6. Return to the root. Its name is still there, and renaming it still works.
  7. As a user without neowiki-schema-edit, the badge is still a link and still reaches the Schema
    page; clicking it navigates rather than opening the editor.
  8. Narrow the window until the pane is around 200px. The pane header wraps; neither the name nor
    the badge is crushed.

AI-authored — Claude Code, Opus 5 (1M context); design chosen by @alistair3149 from options put to them in a design artifact, with the header treatment, the badge styling and the pane layout directed by them during the work; diff not yet human-reviewed; verified: 1858 vitest tests, lint and build green locally, and the header, badge states and wrap behaviour measured in a browser against a dev wiki.

@alistair3149

alistair3149 commented Sep 3, 2026

Copy link
Copy Markdown
Member Author
image image

For #1328

The dialog's header named the root Subject and carried the field that renamed it, so a nested
pane could not be renamed at all and the header described a Subject the user might not be
looking at. It named the root's Schema too, with the same problem. Neither could follow the
active pane: `title` is a CdxDialog prop, so binding it re-renders the dialog, and under the
spec suite's teleport stub that remounts every pane.

So the header stops naming anything, and with nothing left to slot it goes back to Codex's own.
`use-close-button` renders the same header the `#header` slot was reproducing line for line —
title group, `<h2>`, quiet close button — and Codex then names the dialog with
`aria-labelledby` pointing at that heading rather than an `aria-label` parallel to it. Out with
the slot go the CdxButton and icon imports, a second lookup of the same message, an `:inert`
that guarded a field no longer there, the replicated header rules and the link mixin.

Two rules survive as deliberate overrides rather than replications: `.cdx-dialog__header`'s
padding is unconditional in Codex, not a `--default` rule, so the header runs 49px against
every other dialog's 65px, and `align-items` is centred rather than baseline. Both because the
row is one line of static text beside a 32px close button, which sets the height.

The Subject's name, its rename control and its Schema move into the pane that edits them. The
Schema is the badge from the first commit, opened in a new tab for the reason the storage line
beside it already gives: this dialog holds unsaved edits for every open pane and nothing guards
a navigation away from it. A plain left click by someone who may edit the Schema opens the
editor instead; every gesture a browser uses to open a link elsewhere is left alone. Only the
root pane offers the editor, since that is the Schema `SchemaEditorDialog` is bound to, and
that restriction is asserted in the dialog as well as the pane — the pane knows the intent, the
dialog holds the consequence.

The badge takes `paneName`, so a Subject already displayed under its Schema name is not named
twice: without it the heading and the badge both read "Person" for a label-less child, which is
the duplication `schemaNameToShow` exists to remove. Its row may shrink, so the badge truncates
itself rather than pushing the header wider than the pane and giving the whole form a
horizontal scrollbar.

`neowiki-subject-editor-title` takes no parameter now, so the dialog's accessible name and its
visible heading say the same thing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R7zBSDFPUVStRFFTzjMLL8
@alistair3149
alistair3149 marked this pull request as ready for review September 3, 2026 01:54
@JeroenDeDauw
JeroenDeDauw merged commit d13ea37 into 1328-schema-badge Sep 6, 2026
20 checks passed
@JeroenDeDauw
JeroenDeDauw deleted the 1328-pane-header branch September 6, 2026 19:15
JeroenDeDauw added a commit that referenced this pull request Sep 7, 2026
* Share the visually-hidden rules as a LESS mixin

`DataExportButton` carried its own copy of the nine declarations that take an element out of
the visual layout while leaving it in the accessibility tree. A second caller is arriving, so
they move to `assets/mixins.less` beside `keyboard-focus.less`, imported by reference so
nothing is emitted until a rule calls it.

Neither Codex nor this build offers one to reuse: Codex's public mixins are `css-icon`, `link`
and `button-layout-flush`, and MediaWiki core's `.mixin-screen-reader-text()` is out of reach
because the Vite build sets no LESS include path to core.

The mixin body is the block it replaces, unchanged, so the emitted CSS for
`.ext-neowiki-data-export__sr-only` is byte-identical.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R7zBSDFPUVStRFFTzjMLL8

* Let a NeoTree node's secondary label be decorated, and give way

A `secondary` slot renders in place of a node's plain `secondaryLabel` text, inside the same
element, so a consumer can give that label a treatment of its own without the tree learning
what it means. It forwards through `NeoTreeNode` recursively, like `trailing` already does,
and keeps the plain text as its default content.

The slot decorates a label rather than replacing the decision to show one: a node with no
`secondaryLabel` renders no secondary element, and therefore no slot. That is a real limit of
the shape rather than an oversight, so a test pins it.

Separately, `__node-secondary` may now shrink. Under `flex: none` a long secondary label took
its full max-content width and squeezed the node's own name toward nothing, then pushed the
navigator into horizontal scroll; it now gives way to the name and truncates itself.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R7zBSDFPUVStRFFTzjMLL8

* Show a Subject's Schema as one badge wherever it is named

For #1328

A Subject's Schema was drawn four ways: a permission-gated link in the editor header that
opened the Schema editor rather than navigating, subtle text beside a navigator row, a
subtitle link in the infobox, and another beside a statement count in the Subjects manager.
Nothing about any of them said "this string is a Schema" — the register they shared is also
the register of statement counts, subject ids and the tree's group captions.

`SchemaNameDisplay` renders the bare name as a badge and owns the rules the surfaces used to
each decide for themselves: where the link goes, and when the name is withheld because it
would only repeat the name beside it.

Deliberately not a `CdxInfoChip`. A chip is a bordered pill at the size of a navigator row's
own text, and thirteen down the demo wiki's tree read as a wall; the badge is a step smaller
and squared off. The two stay distinct shapes for distinct ideas — the chip means Property
Type on the Schema page, and is left alone.

Where it links it takes Codex's normal-weight progressive-action button. Those colours are
polyfilled onto the badge itself: the Codex MediaWiki serves ships most of them at older
values and the two subtle hover and active fills not at all, and it defines the custom
properties it does ship, so a `var()` fallback would never reach ours. `light-dark()` supplies
both arms, since MediaWiki's dark mode sets `color-scheme` on the root, and `@supports` guards
the block so a browser without it keeps MediaWiki's own values rather than one that is invalid
at substitution. Remove that block once MediaWiki 1.47 carries the values.

`:visited`, `:hover` and `:focus` are spelled out throughout, which is load-bearing: core
styles `a:visited` and underlines `a:hover, a:focus`, each at specificity (0,1,1) — a
pseudo-class counts as a class — so they tie with a bare `a.<class>` and win on load order.

The withholding rule lives in `schemaNameToShow`, shared by the badge and by the tree's own
`secondaryLabel`, so a Subject displayed under its Schema name (ADR 31) shows it once; the
infobox and the Subjects manager printed it twice before. The infobox gates its
`role="heading"` wrapper on the same rule, or a withheld badge would leave an unnamed heading
in the accessibility tree.

Two layout fixes the badge's own `max-width` could not make: `min-width: 0` on the infobox
header's text column, because a flex item's automatic minimum size is its content's
max-content width and a 50-character Schema name pushed the badge through the infobox border;
and the tree reaching the badge through NeoTree's slot rather than a stylesheet, so one
component owns it and the row's DOM is unchanged — `SubjectTree.spec` asserts a row's children
and text exactly, to catch a re-introduced glyph, and still does.

Also here: `neowiki-infobox-type` is deleted, being declared and defined but referenced by no
code, in the repo or in wiki content.

Not here: the editor's own header, which keeps `Schema: X` until the follow-up removes that
subtitle wholesale.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R7zBSDFPUVStRFFTzjMLL8

* Let every pane name itself, and hand the header back to Codex (#1350)

For #1328

The dialog's header named the root Subject and carried the field that renamed it, so a nested
pane could not be renamed at all and the header described a Subject the user might not be
looking at. It named the root's Schema too, with the same problem. Neither could follow the
active pane: `title` is a CdxDialog prop, so binding it re-renders the dialog, and under the
spec suite's teleport stub that remounts every pane.

So the header stops naming anything, and with nothing left to slot it goes back to Codex's own.
`use-close-button` renders the same header the `#header` slot was reproducing line for line —
title group, `<h2>`, quiet close button — and Codex then names the dialog with
`aria-labelledby` pointing at that heading rather than an `aria-label` parallel to it. Out with
the slot go the CdxButton and icon imports, a second lookup of the same message, an `:inert`
that guarded a field no longer there, the replicated header rules and the link mixin.

Two rules survive as deliberate overrides rather than replications: `.cdx-dialog__header`'s
padding is unconditional in Codex, not a `--default` rule, so the header runs 49px against
every other dialog's 65px, and `align-items` is centred rather than baseline. Both because the
row is one line of static text beside a 32px close button, which sets the height.

The Subject's name, its rename control and its Schema move into the pane that edits them. The
Schema is the badge from the first commit, opened in a new tab for the reason the storage line
beside it already gives: this dialog holds unsaved edits for every open pane and nothing guards
a navigation away from it. A plain left click by someone who may edit the Schema opens the
editor instead; every gesture a browser uses to open a link elsewhere is left alone. Only the
root pane offers the editor, since that is the Schema `SchemaEditorDialog` is bound to, and
that restriction is asserted in the dialog as well as the pane — the pane knows the intent, the
dialog holds the consequence.

The badge takes `paneName`, so a Subject already displayed under its Schema name is not named
twice: without it the heading and the badge both read "Person" for a label-less child, which is
the duplication `schemaNameToShow` exists to remove. Its row may shrink, so the badge truncates
itself rather than pushing the header wider than the pane and giving the whole form a
horizontal scrollbar.

`neowiki-subject-editor-title` takes no parameter now, so the dialog's accessible name and its
visible heading say the same thing.

Claude-Session: https://claude.ai/code/session_01R7zBSDFPUVStRFFTzjMLL8

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Draw the manager row's separator only after a badge

The bullet before a row's statement count dates from when the Schema link was always there. With the badge withheld from a row named after its Schema, the count opened with a dangling bullet.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Jeroen De Dauw <jeroendedauw@proton.me>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants