# not be remembered between page loads
#%]
-<div class="module
+<section class="module
[%~ " edit-hide" IF hide_on_edit %]
[%~ " edit-show" IF hide_on_view && !hide_on_edit %]"
[% IF hide_on_view +%] style="display:none"[% END %]
[%~ ' data-non-stick="1"' IF no_collapse_persist %]
>
[% IF title %]
- <div class="module-header">
- <div class="module-latch">
- <div class="module-spinner">[% collapsed ? "▸" : "▾" %]</div>
- <div class="module-title">[% title FILTER html %]</div>
+ <header id="module-[% title.replace FILTER id %]-header" class="module-header">
+ <div class="module-latch"
+ data-label-expanded="Collapse [% title FILTER html %] section"
+ data-label-collapsed="Expand [% title FILTER html %] section">
+ <div class="module-spinner" role="button" tabindex="0"
+ aria-controls="module-[% title.replace FILTER id %]-content"
+ aria-expanded="[% collapsed ? "false" : "true" %]"
+ aria-labeledby="module-[% title.replace FILTER id %]-title"
+ aria-describedby="module-[% title.replace FILTER id %]-subtitle"></div>
+ <h2 class="module-title" id="module-[% title.replace FILTER id %]-title">[% title FILTER html %]</h2>
[% IF subtitle != "" && subtitle.size %]
- <div class="module-subtitle">
+ <h3 class="module-subtitle" id="module-[% title.replace FILTER id %]-subtitle">
([% FOREACH st IN subtitle.list %]
[% IF st.unfiltered.defined %]
[% st.unfiltered FILTER none %]
[% END %]
[% ", " UNLESS loop.last %]
[% END %])
- </div>
+ </h3>
[% END %]
</div>
- </div>
+ </header>
[% END %]
- <div class="module-content" [% ' style="display:none"' IF collapsed %] >
+ <div class="module-content"
+ [%~ IF title %] id="module-[% title.replace FILTER id %]-content"[% END %]
+ [%~ ' style="display:none"' IF collapsed %]
+ >
[% content FILTER none %]
</div>
-</div>
+</section>
.module-header {
background: #eee;
- padding: 2px 5px;
- cursor: pointer;
-webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);
-moz-box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);
box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);
}
.module-latch {
- display: table-cell;
- padding-left: 5px;
- padding-right: 5px;
+ padding: 2px 10px;
+ cursor: pointer;
}
.module-spinner {
width: 10px;
}
+.module-spinner::before {
+ content: "\25BE";
+}
+
+.module-spinner[aria-expanded="false"]::before {
+ content: "\25B8";
+}
+
.module-title {
font-weight: bold;
}
.module-title, .module-subtitle {
+ font-size: 13px;
display: table-cell;
padding-left: 5px;
}
if (!module.attr('id'))
return;
var latch = module.find('.module-latch');
- var spinner = $(latch.children('.module-spinner')[0]);
+ var spinner = module.find('.module-spinner');
var content = $(module.children('.module-content')[0]);
var duration = fast ? 0 : 200;
function slide_done() {
var is_visible = content.is(':visible');
- spinner.html(is_visible ? '▾' : '▸');
+ spinner.attr({
+ 'aria-expanded': is_visible,
+ 'aria-label': is_visible ? latch.data('label-expanded') : latch.data('label-collapsed'),
+ });
if (BUGZILLA.user.settings.remember_collapsed)
localStorage.setItem(module.attr('id') + '.visibility', is_visible ? 'show' : 'hide');
}
}
// expand/colapse module
- $('.module-header')
+ $('.module-latch')
.click(function(event) {
event.preventDefault();
slide_module($(this).parents('.module'));
+ })
+ .keydown(function(event) {
+ // expand/colapse module with the enter or space key
+ if (event.keyCode === 13 || event.keyCode === 32) {
+ event.preventDefault();
+ slide_module($(this).parents('.module'));
+ }
});
// toggle obsolete attachments