Feature Language Change a11y NPM Resource Changed PR-7.0-dev Pending

User tests: Successful: Unsuccessful:

avatar dgrammatiko
dgrammatiko
7 Mar 2026

Pull Request resolves #29936 .

  • I read the Generative AI policy and my contribution is either not created with the help of AI or is compatible with the policy and GNU/GPL 2 or later.

Summary of Changes

  • switch from draggula to dndkit

Testing Instructions

Apply the patch or install the package and the sample data

  • Go to Articles and click on the icon before the Featured on the table header
  • press tab till you have highlighted the 3 dots icon on any article
  • Press enter or space to initiate the drag and drop
  • press the up/down keyboard arrows to move the article ti the desired position
  • press enter or space to exit the Drag and drop mode
  • classic mouse grab to drag and drop works as before

Actual result BEFORE applying this Pull Request

Expected result AFTER applying this Pull Request

Link to documentations

Please select:

  • Documentation link for guide.joomla.org:

  • No documentation changes for guide.joomla.org needed

  • Pull Request link for manual.joomla.org:

  • No documentation changes for manual.joomla.org needed

avatar dgrammatiko dgrammatiko - open - 7 Mar 2026
avatar dgrammatiko dgrammatiko - change - 7 Mar 2026
Status New ⇒ Pending
avatar joomla-cms-bot joomla-cms-bot - change - 7 Mar 2026
Category ⇒ Repository Administration com_banners com_categories com_contact com_content com_fields com_languages com_menus com_modules com_newsfeeds com_plugins com_tags com_users com_workflow Language & Strings NPM Change
avatar dgrammatiko dgrammatiko - change - 7 Mar 2026
Labels Added: Language Change NPM Resource Changed PR-7.0-dev
avatar joomla-cms-bot joomla-cms-bot - change - 7 Mar 2026
Category Repository Administration com_banners com_categories com_contact com_content com_fields com_languages com_menus com_modules com_newsfeeds com_plugins com_tags com_users com_workflow Language & Strings NPM Change ⇒ Administration com_banners com_categories com_contact com_content com_fields com_languages com_menus com_modules com_newsfeeds com_plugins com_tags com_users com_workflow Repository NPM Change JavaScript Layout
avatar dgrammatiko dgrammatiko - change - 7 Mar 2026
Labels Removed: Language Change
avatar joomla-cms-bot joomla-cms-bot - change - 7 Mar 2026
Category Repository Administration com_banners com_categories com_contact com_content com_fields com_languages com_menus com_modules com_newsfeeds com_plugins com_tags com_users com_workflow NPM Change JavaScript Layout ⇒ Administration com_banners com_categories com_contact com_content com_fields com_languages com_menus com_modules com_newsfeeds com_plugins com_tags com_users com_workflow Repository NPM Change JavaScript
avatar joomla-cms-bot joomla-cms-bot - change - 7 Mar 2026
Category Repository Administration com_banners com_categories com_contact com_content com_fields com_languages com_menus com_modules com_newsfeeds com_plugins com_tags com_users com_workflow NPM Change JavaScript ⇒ Administration com_banners com_categories com_contact com_content com_fields com_languages com_menus com_modules com_newsfeeds com_plugins com_tags com_users com_workflow Language & Strings Repository NPM Change JavaScript
avatar dgrammatiko dgrammatiko - change - 7 Mar 2026
Labels Added: Language Change
avatar joomla-cms-bot joomla-cms-bot - change - 8 Mar 2026
Category Repository Administration com_banners com_categories com_contact com_content com_fields com_languages com_menus com_modules com_newsfeeds com_plugins com_tags com_users com_workflow NPM Change JavaScript Language & Strings ⇒ Administration com_banners com_categories com_contact com_content com_fields com_languages com_menus com_modules com_newsfeeds com_plugins com_tags com_users com_workflow Language & Strings Repository NPM Change JavaScript Libraries
avatar dgrammatiko dgrammatiko - change - 9 Mar 2026
The description was changed
avatar dgrammatiko dgrammatiko - edited - 9 Mar 2026
avatar Fedik
Fedik - comment - 9 Mar 2026

Thanks for working on it.

I have a few suggestion to make it more fun 😉

  1. Put translation in to dedicated WebAsset as we did it for Form validation

    public function onAttachCallback(Document $doc)
    {
    // Add validate.js language strings
    Text::script('JLIB_FORM_CONTAINS_INVALID_FIELDS');
    Text::script('JLIB_FORM_FIELD_REQUIRED_VALUE');
    Text::script('JLIB_FORM_FIELD_REQUIRED_CHECK');
    Text::script('JLIB_FORM_FIELD_INVALID_VALUE');
    }

  2. Make it work for multiple elements on the page, drop the containerSelector and pass the URL as data- attribute (can also pass other options as data-) kind of:

<div 
  class="js-my-cool-sortable-table" 
  data-sorting-url="blabla" 
  data-sorting-dir="ASC" 
  data-sorting-row=".js-row-selector"
>
    <div class="js-row-selector">...</div>
    <div class="js-row-selector">...</div>
 </div>
setUpSortableTable(container, setupOptions){
  const options = {..defaultOptions, ...setupOptions};
  ...
  ...
}
document.querySelectorAll('.js-my-cool-sortable-table').forEach((container) => {
  setUpSortableTable(container, container.dataset);
});

It of course could be WC, but as regular container it will be more clear and reusable.

setUpSortableTable() could be publicly available so people can use it on its own. If you like.

Thanks 😉

avatar dgrammatiko
dgrammatiko - comment - 9 Mar 2026

@Fedik Better? I still haven't modularize it (waiting to see the other 2-3 parts that have drag and drop)

avatar gioacchino54 gioacchino54 - test_item - 9 Mar 2026 - Tested successfully
avatar gioacchino54
gioacchino54 - comment - 9 Mar 2026

I have tested this item ✅ successfully on 42f52e7

I clicked on the first checkbox of an article and followed the instructions, and the sorting is performed correctly.


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/47328.

avatar dgrammatiko
dgrammatiko - comment - 9 Mar 2026

@brianteeman yes

BTW I would appreciate an accessibility test and a check on the announcements. Thanks

avatar Fedik
Fedik - comment - 9 Mar 2026

Better?

Looks good, thanks!

I still haven't modularize it (waiting to see the other 2-3 parts that have drag and drop)

Not important for now, can stay as you did.
It can be extended anytime later in another PR.

avatar dgrammatiko dgrammatiko - change - 9 Mar 2026
The description was changed
avatar dgrammatiko dgrammatiko - edited - 9 Mar 2026
avatar brianteeman
brianteeman - comment - 9 Mar 2026

@brianteeman yes

BTW I would appreciate an accessibility test and a check on the announcements. Thanks

I will check tomorrow. Not looked at it too closely yet but it will need a live region for the announcement

avatar brianteeman
brianteeman - comment - 9 Mar 2026

Looks like you are missing some strings from the announcements https://dndkit.com/extend/plugins/accessibility#default-announcements and from the screen reader instructions https://dndkit.com/extend/plugins/accessibility#default-screen-reader-instructions

avatar github-actions[bot]
github-actions[bot] - comment - 10 Mar 2026

This pull request has conflicts, please resolve those before we can evaluate the pull request.

avatar github-actions[bot]
github-actions[bot] - comment - 10 Mar 2026

This pull request has conflicts, please resolve those before we can evaluate the pull request.

avatar brianteeman
brianteeman - comment - 10 Mar 2026

icon size looks a bit big and not aligned with other icons

image
avatar brianteeman
brianteeman - comment - 10 Mar 2026

dnd works well with both mouse and keyboard

BUT when narrator is enabled it doesnt appear to work at all with the keyboard - but neither does their own demo clauderic/dnd-kit#147

you have to turn scan mode to off in narrator for it to work. i dont know if this is something obvious to screen reader users or not.

avatar brianteeman
brianteeman - comment - 10 Mar 2026

Can someone link this PR to the issue 29936

avatar dgrammatiko dgrammatiko - change - 10 Mar 2026
The description was changed
avatar dgrammatiko dgrammatiko - edited - 10 Mar 2026
avatar dgrammatiko dgrammatiko - change - 10 Mar 2026
Labels Added: Conflicting Files
avatar dgrammatiko
dgrammatiko - comment - 10 Mar 2026

icon size looks a bit big and not aligned with other icons

This shouldn't be committed but the icon needs to change to 3 lines from 3 dots and the clickable area should be way bigger than only the icon size Reverted

BUT when narrator is enabled it doesnt appear to work at all with the keyboard - but neither does their own demo clauderic/dnd-kit#147

Not much that we could do here but in the issue it's mentioned that after pressing caps lock the issue is resolved

Looks like you are missing some strings from the announcements

You're right but event the ones that I added I guess are wrong (just added the defaults on their docs). I guess someone should come up with what should be announced in each step of the workflow (I think it should be something like: Item with title: Fancy title was picked up, instead of the one I just added Picked up draggable item row-0

avatar dgrammatiko dgrammatiko - change - 10 Mar 2026
Labels Removed: Conflicting Files
avatar brianteeman
brianteeman - comment - 10 Mar 2026

For a start I would use the exact same strings that they use and I link to. We can customise it later but for now we should at least ensure we have ALL the required strings

avatar dgrammatiko dgrammatiko - change - 10 Mar 2026
Labels Added: a11y
avatar dgrammatiko
dgrammatiko - comment - 10 Mar 2026

For a start I would use the exact same strings that they use and I link to

added the original strings

avatar chmst
chmst - comment - 10 Mar 2026

Tested with mouse and keyboard. Ordering works like a charm.
With keyboard I am not sure about the skips - but could be it is like this since ever.

I open the page, skip-to form.
Focus is on the ordering icon, not on the check-all-toggle.
Then I tab forward, ok.
When I tab backwards, the tab ignores the order-button and goes to the check-all-toggle
Tabbing forward the ignores the order-button again.

grafik

Then I am unable to tab to the order-button with tabbing.

avatar dgrammatiko
dgrammatiko - comment - 10 Mar 2026

@chmst interesting but that’s not a part that this pr covers. I’m only doing the table body reordering, so maybe open another issue for the table head?
Thanks

avatar Fedik
Fedik - comment - 14 Mar 2026

I guess you're ok with the introduction of the new function but if still under discussion the reasons are

I am actually did not really paid attention for that 😄
I think we can use existing method with little modification to make it b/c.

Need to check.

avatar dgrammatiko
dgrammatiko - comment - 14 Mar 2026

I think we can use existing method with little modification to make it b/c.

it always returns "1" plus it expects the url parameters ie form submit…

avatar github-actions[bot]
github-actions[bot] - comment - 17 Mar 2026

This pull request has conflicts, please resolve those before we can evaluate the pull request.

avatar gioacchino54
gioacchino54 - comment - 17 Mar 2026

Hello everyone,

I ran a test with a screen reader and can confirm the following.

Given that I do not know the commands for jumping between the various sections, pressing the tab key takes you through all the navigation links.

When you reach the headers of the articles table, pressing Enter above the sort icon activates the rows so that they can be moved. Furthermore, pressing Enter on the sort icon causes you to lose focus, and you have to go through the cycle again with the Tab key to reposition yourself on the table. However, when you are above the three dots, you cannot drag the row to move the item, rendering the function unusable.

See the video at this link: https://www.loom.com/share/cd4fab7d69ed47a588698710591c1b85

It works in Firefox

https://www.loom.com/share/b20257272179484fa1d2de4a8862c902

avatar dgrammatiko
dgrammatiko - comment - 17 Mar 2026

Furthermore, pressing Enter on the sort icon causes you to lose focus, and you have to go through the cycle again with the Tab key to reposition yourself on the table

this is expected as pressing enter will reload the page, so the focus is lost. I’m not resigning the page here just implementing the drag and drop with a popular js framework/library

However, when you are above the three dots, you cannot drag the row to move the item, rendering the function unusable.

when you have the 3dots high listed y out need to press enter or space once to enter the dragging mode. Check the instructions in the description above

avatar mbeganyi-a11y
mbeganyi-a11y - comment - 19 Sep 2026

Hi all. Just wondering what the status is for this particular PR. If there's anything I can do to help it along, happy to do so. Thank you.

avatar dgrammatiko
dgrammatiko - comment - 21 Sep 2026

I’m gonna solve the merge conflicts so it can be tested again

716671a 21 Sep 2026 avatar dgrammatiko fixes
0e43187 21 Sep 2026 avatar dgrammatiko CS
7756941 21 Sep 2026 avatar dgrammatiko CS
6e8d23d 21 Sep 2026 avatar dgrammatiko oops
835ad62 21 Sep 2026 avatar dgrammatiko CS
avatar angieradtke
angieradtke - comment - 25 Sep 2026

First of all, a huge improvement compared to before, but it’s really quite complex. This are only fast impressions,
Here is a brief summary of what I noticed. I hope I have understood everything correctly:

1. Announcements use row-0 instead of the article title
The announcements are basically dnd-kit's way of keeping screen reader users in the loop while something is being dragged around. During a drag, dnd-kit adds a visually hidden live region

<div role="status" aria-live="polite" aria-atomic="true">

to the end of the and keeps updating it on drag start, drag over, and drag end.

Whatever gets written into that region is picked up by the screen reader. So for keyboard and screen reader users, this is essentially the only way to know what's being dragged and where it currently is
The announcements currently use the internal sortable ID for {{source}} and {{target}}.
The Joomla elements do not have an id, which is why the screen reader announces:

“Picked up draggable item row-0”

Solution: Read the title from the title cell instead, maybe in that way:

// dnd.es6.js – line 76


getLabel(element) {
  const cell =
    element?.querySelector('th[scope="row"] a') ||
    element?.querySelector('th[scope="row"]');

  const label = cell
    ? cell.textContent.replace(/\s+/g, ' ').trim()
    : '';

  return label || element?.dataset.dndDraggableId || '';
}

2. No position information is announced

An announcement such as:

“… was moved over droppable target row-1”

does not tell the user where the item is now positioned.

Solution: Announce the current position and the total number of items within the group. This is somewhat more complicated because the position needs to be calculated dynamically based on the current group and ordering.

3. dragover is announced twice

dnd-kit fires a second dragover after each step where the dragged element is effectively positioned over itself.

This results in announcements such as:

“row-0 was moved over droppable target row-0”

in the PR.

Possible Solution:

if (target.id === source.id) {
  return undefined;
}

4. JGLOBAL_DRAGANDDROP_DRAGEND_CANCELED is not loaded

The language key exists in the INI file, but it is missing from DragAndDropAssetItem::onAttachCallback().

As a result, when the operation is cancelled with Escape, the language key is not available to the JavaScript announcement.

Solution:

Text::script('JGLOBAL_DRAGANDDROP_DRAGEND_CANCELED');

5. Cancellation is announced as “dropped”

In dragend, !target is currently checked before canceled.

A cancelled drag operation often has no target, so the wrong announcement is triggered.

Solution: Reverse the order of the checks:

if (canceled) {
  return this.announce(
    'JGLOBAL_DRAGANDDROP_DRAGEND_CANCELED',
    source.element,
    this.dragElementIndex
  );
}


if (!target) {
  return this.announce(
    'JGLOBAL_DRAGANDDROP_DRAGEND_DROPPED_NO_ELEMENT',
    source.element
  );
}

6. Keyboard instruction is hard-coded in English

aria-describedby currently points to the default dnd-kit instructions:

“To pick up a draggable item, press the space bar …”

These instructions are not translatable through the Joomla language system.

Solution: Configure the screen-reader instructions explicitly:

Accessibility.configure({
  screenReaderInstructions: {
    draggable: Joomla.Text._(
      'JGLOBAL_DRAGANDDROP_INSTRUCTIONS'
    ),
  },
  // …
});

Add the corresponding language string:

JGLOBAL_DRAGANDDROP_INSTRUCTIONS="To move this item, press Space or Enter. Use the Up and Down arrow keys to change its position. Press Space or Enter again to drop it, or press Escape to cancel."

And load it in PHP:

Text::script('JGLOBAL_DRAGANDDROP_INSTRUCTIONS');

7. The drag handle has no accessible name

dnd-kit turns span.sortable-handler into a role="button".

The element itself only contains an icon with aria-hidden. As a result, the screen reader announces something similar to:

“draggable, button”

without providing a meaningful accessible name, and with an English role description.
This does not meet the requirements of WCAG 4.1.2 (Name, Role, Value).

Solution: Set the accessible name when registering the drag handle. dnd-kit does not overwrite existing attributes.

handle.setAttribute(
  'aria-label',
  Joomla.Text
    ._('JGLOBAL_DRAGANDDROP_HANDLE_LABEL')
    .replace('{{title}}', this.getLabel(element))
);

handle.setAttribute(
  'aria-roledescription',
  Joomla.Text._(
    'JGLOBAL_DRAGANDDROP_ROLEDESCRIPTION'
  )
);

Add the corresponding language strings:


JGLOBAL_DRAGANDDROP_HANDLE_LABEL="Reorder {{title}}"
JGLOBAL_DRAGANDDROP_ROLEDESCRIPTION="sortable item"

Overall, the main problem is that the current implementation still displays several internal dnd-kit/sortable identifiers and default English accessibility strings to screen reader users. Replacing these elements with labels that can be translated in Joomla, meaningful element titles, position indicators, and properly handled cancellation states should make the drag-and-drop interaction significantly clearer and more accessible.

That can definitely be done. However, the changes are in the script, and I’m not sure if we have to stick with the default.

I’m also not sure if I’ve found everything or if I’ve misinterpreted something. Testing this is quite complex.

avatar dgrammatiko dgrammatiko - change - 27 Sep 2026
Labels Added: Feature Conflicting Files
058940a 27 Sep 2026 avatar dgrammatiko CS
avatar dgrammatiko dgrammatiko - change - 27 Sep 2026
Labels Removed: Conflicting Files
avatar mbeganyi-a11y
mbeganyi-a11y - comment - 1 Oct 2026

@dgrammatiko You want me to give this a test, too? Happy to help out here.

avatar dgrammatiko
dgrammatiko - comment - 1 Oct 2026

@mbeganyi-a11y sure go ahead. I’ll meet Angie in person the coming days so we will test it as well

Add a Comment

Login with GitHub to post a comment