diff --git a/auth/tests/behat/login.feature b/auth/tests/behat/login.feature index 6fd357dede0..b5eacf1c2c7 100644 --- a/auth/tests/behat/login.feature +++ b/auth/tests/behat/login.feature @@ -55,12 +55,13 @@ Feature: Authentication And the page should meet accessibility standards with "wcag131, wcag141, wcag412" extra tests @javascript @accessibility - Scenario: The login page must have sufficient colour contrast + Scenario: The login page must meet accessibility standards Given the following config values are set as admin: | custommenuitems | -This is a custom item\|/customurl/ | When I am on site homepage - Then the page should meet "wcag143" accessibility standards - And the page should meet accessibility standards with "wcag143" extra tests + Then the page should meet accessibility standards with "best-practice" extra tests + And I follow "Log in" + And the page should meet accessibility standards with "best-practice" extra tests Scenario: Alternate login URL can be bypassed Given the following config values are set as admin: diff --git a/auth/tests/behat/loginform.feature b/auth/tests/behat/loginform.feature index cc4c01338e7..7942678268d 100644 --- a/auth/tests/behat/loginform.feature +++ b/auth/tests/behat/loginform.feature @@ -46,12 +46,14 @@ Feature: Test if the login form provides the correct feedback And I follow "Log in" Then I should see "Lorem ipsum dolor sit amet" + @javascript @accessibility Scenario: Show the maintenance mode message Given the following config values are set as admin: - | maintenance_enabled | Disabled | - | maintenance_message | Back online tomorrow | + | maintenance_enabled | 1 | + | maintenance_message | Back online tomorrow | And I follow "Log in" Then I should see "Back online tomorrow" + And the page should meet accessibility standards with "best-practice" extra tests Scenario: User self registration Given the following config values are set as admin: diff --git a/blocks/moodleblock.class.php b/blocks/moodleblock.class.php index 44fcf568d03..1696b4730bd 100644 --- a/blocks/moodleblock.class.php +++ b/blocks/moodleblock.class.php @@ -446,8 +446,11 @@ class block_base { $attributes = array( 'id' => 'inst' . $this->instance->id, 'class' => 'block_' . $this->name() . ' block', - 'role' => $this->get_aria_role() ); + $ariarole = $this->get_aria_role(); + if ($ariarole) { + $attributes['role'] = $ariarole; + } if ($this->hide_header()) { $attributes['class'] .= ' no-header'; } @@ -739,20 +742,19 @@ EOD; * a landmark child. * * Options are as follows: + * - application * - landmark - * - application - * - banner - * - complementary - * - contentinfo * - form - * - main * - navigation * - search * + * Please do not use top-level landmark roles such as 'banner', 'complementary', 'contentinfo', or 'main'. Read more at + * {@link https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/ ARIA Authoring Practices Guide - Landmark Regions} + * * @return string */ public function get_aria_role() { - return 'complementary'; + return 'region'; } /** diff --git a/lang/en/moodle.php b/lang/en/moodle.php index 6fcf8bfa434..9da9e5bebc5 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -221,6 +221,8 @@ $string['block'] = 'Block'; $string['blockconfiga'] = 'Configuring a {$a} block'; $string['blockconfigbad'] = 'This block has not been implemented correctly and thus cannot provide a configuration interface.'; $string['blocks'] = 'Blocks'; +$string['blocks_main'] = 'Main content blocks'; +$string['blocks_supplementary'] = 'Supplementary blocks'; $string['blocksaddedit'] = 'Add/Edit blocks'; $string['blockseditoff'] = 'Blocks editing off'; $string['blocksediton'] = 'Blocks editing on'; diff --git a/lib/classes/output/core_renderer.php b/lib/classes/output/core_renderer.php index 1409906f4c7..ebdb6404f7c 100644 --- a/lib/classes/output/core_renderer.php +++ b/lib/classes/output/core_renderer.php @@ -1503,7 +1503,7 @@ class core_renderer extends renderer_base { $context->skiptitle = strip_tags($bc->title); $context->showskiplink = !empty($context->skiptitle); $context->arialabel = $bc->arialabel; - $context->ariarole = !empty($bc->attributes['role']) ? $bc->attributes['role'] : 'complementary'; + $context->ariarole = !empty($bc->attributes['role']) ? $bc->attributes['role'] : ''; $context->class = $bc->attributes['class']; $context->type = $bc->attributes['data-block']; $context->title = $bc->title; @@ -3786,6 +3786,7 @@ EOD; */ public function blocks($region, $classes = [], $tag = 'aside', $fakeblocksonly = false) { $displayregion = $this->page->apply_theme_region_manipulations($region); + $headingid = $displayregion . '-block-region-heading'; $classes = (array)$classes; $classes[] = 'block-region'; $attributes = [ @@ -3793,12 +3794,23 @@ EOD; 'class' => join(' ', $classes), 'data-blockregion' => $displayregion, 'data-droptarget' => '1', + 'aria-labelledby' => $headingid, ]; + // Generate an appropriate heading to uniquely identify the block region. + $blocksheading = match ($displayregion) { + 'side-post' => get_string('blocks_supplementary'), + 'content' => get_string('blocks_main'), + default => get_string('blocks'), + }; + $content = html_writer::tag('h2', $blocksheading, ['class' => 'sr-only', 'id' => $headingid]); if ($this->page->blocks->region_has_content($displayregion, $this)) { - $content = html_writer::tag('h2', get_string('blocks'), ['class' => 'sr-only']) . - $this->blocks_for_region($displayregion, $fakeblocksonly); - } else { - $content = html_writer::tag('h2', get_string('blocks'), ['class' => 'sr-only']); + $content .= $this->blocks_for_region($displayregion, $fakeblocksonly); + } + // Given that