Skip to content

Upgrade Parent Tag Configuration handling for Accessibility - #4254

Merged
idaiv merged 2 commits into
2026.xfrom
parent-tag-configuration-accessibility
Oct 23, 2026
Merged

idaiv merged 2 commits into
2026.xfrom
parent-tag-configuration-accessibility

Conversation

@idaiv

@idaiv idaiv commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Moving a tag was only possible by dragging it onto another tag, which leaves out anyone who cannot use drag and drop. The tag context menu action is now "Edit" and changes the name and the parent in one modal.

  • The modal keeps the existing name field and adds a "Move under" select, so renaming and moving happen in one save
  • Every tag is offered as a destination, labelled with its full path, rather than only tags that already have children. Indentation is never announced, so the path is what tells a screen reader where a tag sits
  • The edited tag and its subtree are left out, since moving a tag into its own branch would detach it from the tree
  • The filter matches the whole path, so typing a parent name also finds the tags below it
  • New text is translated into all nine languages, and the two translation keys the old rename modal no longer uses are removed

The flow works by keyboard throughout: Shift+F10 opens the tag's context menu, Tab moves into it, arrows reach "Edit", and the modal is operated with Tab, typing and Enter. The select reports role="combobox" with aria-expanded, aria-autocomplete="list" and aria-activedescendant.

Two accessibility gaps remain, both outside this change:

  • After saving, focus returns to the document body rather than to the edited tag, because the context menu item that opened the modal no longer exists
  • Entering the tree's context menu needs Tab after Shift+F10; arrow keys alone do not move into it. That lives in the shared TreeElement

Resolves #942

🤖 Generated with Claude Code

- Rename the tag context menu action to "Edit" and let it change the name
  and the parent tag in one modal, so a tag can be moved without dragging
- Offer every tag as a destination, labelled with its full path, rather
  than only tags that already have children. Indentation is never
  announced, so the path is what tells a screen reader where a tag sits
- Leave out the edited tag and its subtree, which cannot be valid targets
- Filter on the whole path, so typing a parent name finds the tags below it
- Translate the new text into all nine languages and drop the two
  translation keys the rename modal no longer uses

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 22, 2026 14:25
@idaiv idaiv added this to the 2026.4.0 milestone Oct 22, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Filtered tree data hides valid move destinations, and the new modal regresses Enter-to-save behavior in the name field.

2 open issues
What changed in this PR

Verdict: Needs changes. This PR addresses #942 by adding a keyboard-accessible alternative to drag-and-drop tag moves within Tag Configuration.

Changes:

  • Replaces Rename with an Edit modal that saves the tag name and parent together.
  • Adds searchable, full-path destinations while excluding the edited tag and its descendants.
  • Adds utility tests and updates translations across nine languages.

The behavior belongs in the tags module, and no shared API signatures change. Utility tests cover destination generation, but interactive regression coverage remains incomplete. No documentation or changelog changes are included; runtime keyboard behavior was not tested during this review.

File Description
translations/​studio.sv.yaml Adds Swedish edit/move text; removes rename keys.
translations/​studio.pl.yaml Adds Polish edit/move text; removes rename keys.
translations/​studio.no.yaml Adds Norwegian edit/move text; removes rename keys.
translations/​studio.nl.yaml Adds Dutch edit/move text; removes rename keys.
translations/​studio.it.yaml Adds Italian edit/move text; removes rename keys.
translations/​studio.fr.yaml Adds French edit/move text; removes rename keys.
translations/​studio.es.yaml Adds Spanish edit/move text; removes rename keys.
translations/​studio.en.yaml Adds English edit/move text; removes rename keys.
translations/​studio.de.yaml Adds German edit/move text; removes rename keys.
assets/​js/​src/​core/​modules/​tags/​utils/​move-target-options.ts Builds and filters full-path move destinations.
assets/​js/​src/​core/​modules/​tags/​utils/​move-target-options.test.ts Tests paths, subtree exclusion, and matching.
assets/​js/​src/​core/​modules/​tags/​tag-configuration-container.tsx Connects the Edit action and combined save flow.
assets/​js/​src/​core/​modules/​tags/​components/​edit-tag-modal/​edit-tag-modal.tsx Adds the name-and-parent editing modal.

Review effort: Balanced

name="name"
rules={ [{ required: true, message: t('tag-configuration.name-required') }] }
>
<Input />

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 7b5cf19.

You are right that implicit submission never fires here: the form holds two fields that block it (the name input and the search input the destination select renders), and the Save button sits in the modal footer, outside the form, so it is no submit button of the form either. I confirmed both in a test before fixing.

The name field now handles Enter itself, <Input onPressEnter={ handleSave } />, matching how the other modal forms in this codebase restore Enter (for example use-add-document.tsx). I kept it explicit rather than associating the footer button with the form via form/htmlType="submit", because that would have made the button the form's default button and fired handleSave twice, once from the click and once from the submit.

Regression tests in edit-tag-modal.test.tsx:

  • saves on Enter in the name field, as the rename dialog did - fails on the previous code and passes now
  • leaves the form to the explicit handler rather than to implicit submission - pins the two inputs and the absence of a submit button, so the reason Enter needs explicit handling is recorded
  • does not save on Enter while the name is empty - validation still blocks the save

The test renders the real AntD form, input and select that the Studio components wrap, since the Studio ones reach antd-style's untranspiled ESM and pull in the whole app import tree under jest.

} }
rootTag={ rootTagFolder }
tag={ tagToEdit }
tags={ tags }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 7b5cf19.

Confirmed: the modal was given tags from useTagConfig(), and that collection is fetched with the toolbar filter, so searching the tree for Germany really did remove Quality from "Move under", and the modal's own search could not bring back what the collection never held.

useTagConfig now runs a second useTagGetCollectionQuery with filter: '' and exposes it as moveTargetTags, with moveTargetTagsFetching and moveTargetTagsFailed alongside. The tree keeps following the toolbar search; only the destinations ignore it. While the toolbar is empty both queries have identical arguments, so RTK Query serves them from one cache entry and this costs no extra request.

Loading and errors are handled in the modal:

  • while the collection is in flight the select is disabled and shows its loading state
  • if it fails, the select is disabled and the failure is the field's accessible description ("The list of tags could not be loaded, so only the name can be changed"), translated into all nine languages. The tag stays renameable

A side effect worth noting: the initial parentId is now always present among the options, so the select no longer risks displaying a bare id when the current parent was filtered out.

Regression tests in use-tag-config.test.tsx:

  • keeps the move destinations out of the toolbar search - sets the filter to Germany, then asserts the tree collection narrows to Countries while moveTargetTags still holds Countries and Quality, and that the collection is queried with an empty filter
  • offers a destination the tree search hides - with that same filter active, builds the options as the modal does and asserts "All Tags / Quality" is among them

I put these on the hook rather than on the container because that is where the filter was leaking into the destinations; the container test would have had to mock useTagConfig and so would have mocked away the bug.

- Restore Enter-to-save in the name field. The Save button sits in the modal
  footer, outside the form, and the destination select adds a second input to
  it, so the browser never submits the form implicitly. The name field now
  handles Enter itself, as the other modal forms in the codebase do
- Load the move destinations with an empty filter, independently of the tree
  toolbar search. Searching the tree for one tag used to drop every unrelated
  tag from the collection the modal builds its destinations from, and the
  modal's own search could not bring back what was never there
- Show the destination select as loading while that collection is in flight,
  and name the failure as the field's accessible description when it cannot be
  loaded, leaving the tag renameable
- New message translated into all nine languages
- Regression tests: Enter in the name field saves, the form carries no submit
  button of its own, validation still blocks an empty name, and the
  destinations ignore an active tree filter

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@idaiv
idaiv merged commit ca1f34a into 2026.x Oct 23, 2026
25 checks passed
@idaiv
idaiv deleted the parent-tag-configuration-accessibility branch October 23, 2026 10:28
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 23, 2026
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.

Upgrade Parent Tag Configuration handling for Accessibility

2 participants