From 6c3b1bbf569d77c75f1768713296acdeb0b61f70 Mon Sep 17 00:00:00 2001 From: Joshua Fernandes Date: Wed, 29 Oct 2025 08:31:17 +0530 Subject: [PATCH 1/2] [3517035] WCAG - Focus lands in wrong place upon form submission when error present. --- .../assets/js/status-messages/status-messages.js | 16 ++++++++++++++++ .../assets/js/status-messages/status-messages.js | 16 ++++++++++++++++ .../templates/misc/status-messages.html.twig | 3 +++ 3 files changed, 35 insertions(+) create mode 100644 web/themes/contrib/civictheme/assets/js/status-messages/status-messages.js create mode 100644 web/themes/contrib/civictheme/civictheme_starter_kit/assets/js/status-messages/status-messages.js diff --git a/web/themes/contrib/civictheme/assets/js/status-messages/status-messages.js b/web/themes/contrib/civictheme/assets/js/status-messages/status-messages.js new file mode 100644 index 0000000000..1fcd3f47d4 --- /dev/null +++ b/web/themes/contrib/civictheme/assets/js/status-messages/status-messages.js @@ -0,0 +1,16 @@ +// CivicTheme status-messages.js +(function ($, Drupal) { + Drupal.behaviors.ctFocusErrorSummary = { + attach: function (context, settings) { + // Wait for DOM update after AJAX or normal load + setTimeout(function () { + // Find any element with id starting with 'error-summary-' + var $error = $('[id^="error-summary-"]', context).first(); + if ($error.length) { + $error.attr('tabindex', '-1'); // ensure focusable (in case) + $error.focus(); + } + }, 30); + } + }; +})(jQuery, Drupal); diff --git a/web/themes/contrib/civictheme/civictheme_starter_kit/assets/js/status-messages/status-messages.js b/web/themes/contrib/civictheme/civictheme_starter_kit/assets/js/status-messages/status-messages.js new file mode 100644 index 0000000000..1fcd3f47d4 --- /dev/null +++ b/web/themes/contrib/civictheme/civictheme_starter_kit/assets/js/status-messages/status-messages.js @@ -0,0 +1,16 @@ +// CivicTheme status-messages.js +(function ($, Drupal) { + Drupal.behaviors.ctFocusErrorSummary = { + attach: function (context, settings) { + // Wait for DOM update after AJAX or normal load + setTimeout(function () { + // Find any element with id starting with 'error-summary-' + var $error = $('[id^="error-summary-"]', context).first(); + if ($error.length) { + $error.attr('tabindex', '-1'); // ensure focusable (in case) + $error.focus(); + } + }, 30); + } + }; +})(jQuery, Drupal); diff --git a/web/themes/contrib/civictheme/templates/misc/status-messages.html.twig b/web/themes/contrib/civictheme/templates/misc/status-messages.html.twig index 47d2ea703f..5c5badc64f 100644 --- a/web/themes/contrib/civictheme/templates/misc/status-messages.html.twig +++ b/web/themes/contrib/civictheme/templates/misc/status-messages.html.twig @@ -6,11 +6,14 @@ #} {% for type, messages in message_list %} {% for message in messages %} + {% set id_suffix = type == 'error' ? loop.parent.loop.index ~ '-' ~ loop.index : '' %} + {% set id_attr = type == 'error' ? 'id="error-summary-' ~ id_suffix ~ '" tabindex="-1"' : '' %} {% include 'civictheme:message' with { title: status_headings[type] ? status_headings[type] : type|capitalize, content: message|render, type: (type == 'status' or type == 'info') ? 'information' : type, vertical_spacing: 'both', + attributes: id_attr } only %} {% endfor %} {% endfor %} From 46530fa3f189d6222dfe83ec4d0f0c989b39806c Mon Sep 17 00:00:00 2001 From: Joshua Fernandes Date: Wed, 29 Oct 2025 08:47:40 +0530 Subject: [PATCH 2/2] [3517035] Lint fixes. --- .../contrib/civictheme/templates/misc/status-messages.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/themes/contrib/civictheme/templates/misc/status-messages.html.twig b/web/themes/contrib/civictheme/templates/misc/status-messages.html.twig index 5c5badc64f..861d9f1eca 100644 --- a/web/themes/contrib/civictheme/templates/misc/status-messages.html.twig +++ b/web/themes/contrib/civictheme/templates/misc/status-messages.html.twig @@ -13,7 +13,7 @@ content: message|render, type: (type == 'status' or type == 'info') ? 'information' : type, vertical_spacing: 'both', - attributes: id_attr + attributes: id_attr, } only %} {% endfor %} {% endfor %}