Unverified Commit b7ab11cc authored by Lauri Timmanee's avatar Lauri Timmanee
Browse files

Issue #3231321 by bnjmnm, nod_, lauriii: Improve keyboard accessibility in a particular edge case

parent e1c6ba37
Loading
Loading
Loading
Loading
+32 −16
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
 * Provides admin UI for the CKEditor 5.
 */

((Drupal, drupalSettings, $, JSON, once, Sortable) => {
((Drupal, drupalSettings, $, JSON, once, Sortable, { tabbable }) => {
  const toolbarHelp = [
    {
      message: Drupal.t(
@@ -584,10 +584,7 @@
      // that can catch blur-causing events before the blur happens. If the
      // tooltip is hidden before the blur event, the outline will disappear
      // correctly.
      once(
        'safari-focus-fix',
        document.querySelectorAll('.ckeditor5-toolbar-item'),
      ).forEach((item) => {
      once('safari-focus-fix', '.ckeditor5-toolbar-item').forEach((item) => {
        item.addEventListener('keydown', (e) => {
          const keyCodeDirections = {
            9: 'tab',
@@ -679,9 +676,7 @@
      // information can be retrieved after AJAX rebuilds.
      once(
        'ui-state-storage',
        document.querySelector(
        '#filter-format-edit-form, #filter-format-add-form',
        ),
      ).forEach((form) => {
        form.setAttribute('data-drupal-ui-state', JSON.stringify({}));
      });
@@ -699,7 +694,32 @@
        const activeTab = getUiStateStorage(`${id}-active-tab`);
        if (activeTab) {
          setTimeout(() => {
            document.querySelector(activeTab).click();
            const activeTabLink = document.querySelector(activeTab);
            activeTabLink.click();

            // Only change focus on the plugin-settings-wrapper element.
            if (id !== 'plugin-settings-wrapper') {
              return;
            }
            // If the current focused element is not the body, then the user
            // navigated away from the vertical tab area and is somewhere else
            // within the form. Do not change the current focus.
            if (document.activeElement !== document.body) {
              return;
            }
            // If the active element is the body then we can assume that the
            // focus was on an element that was replaced by an ajax command.
            // If that is the case restore the focus to the active tab that
            // was just rebuilt.
            const targetTabPane = document.querySelector(
              activeTabLink.getAttribute('href'),
            );
            if (targetTabPane) {
              const tabbableElements = tabbable(targetTabPane);
              if (tabbableElements.length) {
                tabbableElements[0].focus();
              }
            }
          });
        }

@@ -718,12 +738,8 @@
      };

      once(
        'plugin-settings',
        document.querySelector('#plugin-settings-wrapper'),
      ).forEach(maintainActiveVerticalTab);
      once(
        'filter-settings',
        document.querySelector('#filter-settings-wrapper'),
        'maintainActiveVerticalTab',
        '#plugin-settings-wrapper, #filter-settings-wrapper',
      ).forEach(maintainActiveVerticalTab);

      // Add listeners to maintain focus after AJAX rebuilds.
@@ -1022,4 +1038,4 @@
      });
    },
  };
})(Drupal, drupalSettings, jQuery, JSON, once, Sortable);
})(Drupal, drupalSettings, jQuery, JSON, once, Sortable, tabbable);
+27 −7
Original line number Diff line number Diff line
@@ -5,7 +5,9 @@
* @preserve
**/

((Drupal, drupalSettings, $, JSON, once, Sortable) => {
((Drupal, drupalSettings, $, JSON, once, Sortable, {
  tabbable
}) => {
  const toolbarHelp = [{
    message: Drupal.t("The toolbar buttons that don't fit the user's browser window width will be grouped in a dropdown. If multiple toolbar rows are preferred, those can be configured by adding an explicit wrapping breakpoint wherever you want to start a new row.", null, {
      context: 'CKEditor 5 toolbar help text, default, no explicit wrapping breakpoint'
@@ -303,7 +305,7 @@
        });
        render(container, selected, available, dividers);
      });
      once('safari-focus-fix', document.querySelectorAll('.ckeditor5-toolbar-item')).forEach(item => {
      once('safari-focus-fix', '.ckeditor5-toolbar-item').forEach(item => {
        item.addEventListener('keydown', e => {
          const keyCodeDirections = {
            9: 'tab',
@@ -350,7 +352,7 @@
        return form.hasAttribute('data-drupal-ui-state') ? JSON.parse(form.getAttribute('data-drupal-ui-state'))[property] : null;
      };

      once('ui-state-storage', document.querySelector('#filter-format-edit-form, #filter-format-add-form')).forEach(form => {
      once('ui-state-storage', '#filter-format-edit-form, #filter-format-add-form').forEach(form => {
        form.setAttribute('data-drupal-ui-state', JSON.stringify({}));
      });

@@ -360,7 +362,26 @@

        if (activeTab) {
          setTimeout(() => {
            document.querySelector(activeTab).click();
            const activeTabLink = document.querySelector(activeTab);
            activeTabLink.click();

            if (id !== 'plugin-settings-wrapper') {
              return;
            }

            if (document.activeElement !== document.body) {
              return;
            }

            const targetTabPane = document.querySelector(activeTabLink.getAttribute('href'));

            if (targetTabPane) {
              const tabbableElements = tabbable(targetTabPane);

              if (tabbableElements.length) {
                tabbableElements[0].focus();
              }
            }
          });
        }

@@ -374,8 +395,7 @@
        });
      };

      once('plugin-settings', document.querySelector('#plugin-settings-wrapper')).forEach(maintainActiveVerticalTab);
      once('filter-settings', document.querySelector('#filter-settings-wrapper')).forEach(maintainActiveVerticalTab);
      once('maintainActiveVerticalTab', '#plugin-settings-wrapper, #filter-settings-wrapper').forEach(maintainActiveVerticalTab);
      const selectedButtons = document.querySelector('#ckeditor5-toolbar-buttons-selected');
      once('textarea-listener', selectedButtons).forEach(textarea => {
        textarea.addEventListener('change', e => {
@@ -552,4 +572,4 @@
    }

  };
})(Drupal, drupalSettings, jQuery, JSON, once, Sortable);
 No newline at end of file
})(Drupal, drupalSettings, jQuery, JSON, once, Sortable, tabbable);
 No newline at end of file