Dropdown accessibility: fix small screen issues & keyboard

This commit is contained in:
yflory 2024-03-08 12:31:53 +01:00
parent 4ba052d090
commit c6bcfc1321
3 changed files with 48 additions and 30 deletions

View File

@ -48,11 +48,13 @@
position: relative;
display: inline-block;
&.cp-dropdown-recursive {
position: unset;
.cp-dropdown-content {
top: 0;
left: 100%;
// If a menu is displayed "left", pour the submenus on the left too
.cp-dropdown-left {
.cp-dropdown-submenu {
.cp-dropdown-content {
left: unset;
right: 100%;
}
}
}
@ -69,6 +71,16 @@
}
}
.cp-dropdown-left {
.cp-dropdown-content {
right: 0;
margin-right: 5px;
&.cp-dropdown-submenu {
left: unset;
right: 250px;
}
}
}
.cp-dropdown-content {
list-style-type: none;
display: none;
@ -84,13 +96,8 @@
font: @dropdown_font;
line-height: 1em;
&.cp-dropdown-has-submenu {
overflow: visible;
}
&.cp-dropdown-left {
right: 0;
margin-right: 5px;
&.cp-dropdown-submenu {
left: 250px;
}
&:hover {

View File

@ -1563,6 +1563,7 @@ define([
$container = $('<span>', containerConfig);
}
// Button
let icon = config.iconCls ? h('i', {class:config.iconCls}) : undefined;
var $button = $(h('button', {
@ -1585,13 +1586,17 @@ define([
// Menu
var $innerblock = $('<ul>', {'class': 'cp-dropdown-content', 'role': 'menu'});
if (config.left) { $innerblock.addClass('cp-dropdown-left'); }
var $outerblock = $(h('div.cp-dropdown-menu-container', $innerblock[0]));
let $parentMenu = config.isSubmenuOf;
$container.$menu = $innerblock;
if (config.left) { $outerblock.addClass('cp-dropdown-left'); }
if (config.isSubmenuOf && config.isSubmenuOf.length) {
$innerblock.addClass('cp-dropdown-submenu');
}
var hide = function () {
window.setTimeout(function () {
$innerblock.hide();
$innerblock.parents('.cp-dropdown-content').removeClass('cp-dropdown-has-submenu')
.hide();
}, 0);
};
@ -1623,7 +1628,8 @@ define([
$entry.appendTo($innerblock);
};
$container.append($button).append($innerblock);
$container.append($button).append($outerblock);
if ($parentMenu) { $parentMenu.after($innerblock); }
var value = config.initialValue || '';
@ -1655,16 +1661,14 @@ define([
if ((topPos + h) > wh) {
$innerblock.css('bottom', button.height+'px');
}
} else if ($innerblock.parents('.cp-dropdown-content').length) {
let $p = $innerblock.parents('.cp-dropdown-content');
let max = $p.css('max-height');
} else if ($parentMenu) {
let max = $parentMenu.css('max-height');
$innerblock.css('max-height', max);
} else {
$innerblock.css('max-height', Math.floor(wh - topPos - 1)+'px');
}
$innerblock.show();
$innerblock.parents('.cp-dropdown-content').addClass('cp-dropdown-has-submenu')
.show(); // keep parent open when recursive
if ($parentMenu) { $parentMenu.show(); } // keep parent open when recursive
$innerblock.find('.cp-dropdown-element-active').removeClass('cp-dropdown-element-active');
setTimeout(() => {
if (config.isSelect && value) {
@ -1709,7 +1713,7 @@ define([
if (config.isSelect) {
$container.onChange = Util.mkEvent();
$container.on('click', 'li', function () {
$innerblock.on('click', 'li', function () {
var $val = $(this).find('a');
value = $val.data('value');
var textValue = $val.text() || value;
@ -1772,7 +1776,10 @@ define([
var next = (idx + 1) % $all.length;
return $($all.get(next));
};
$container.keydown(function (e) {
let $listener = $container;
if ($parentMenu) { $listener = $innerblock; }
$listener.keydown(function (e) {
e.stopPropagation(); // don't propagate event to window if the dropdown is focused
var visible = $innerblock.is(':visible');
@ -1781,6 +1788,7 @@ define([
$container.click();
visible = true;
}
if (!visible) { return; }
if (e.which === 38) { // Up
e.preventDefault();
@ -1824,18 +1832,21 @@ define([
e.preventDefault();
$value.mouseleave();
hide();
$button.focus();
if ($parentMenu) { $button.closest('li').focus(); }
else { $button.focus(); }
}
if (e.which === 9) { // Tab
hide();
if (e.shiftKey) {
$button.focus();
if ($parentMenu) { $button.closest('li').focus(); }
else { $button.focus(); }
} else {
if ($parentMenu) { $parentMenu.hide(); }
$innerblock.find('[role="menuitem"]').last().focus();
}
}
});
$container.keypress(function (e) {
$listener.keypress(function (e) {
e.stopPropagation(); // Don't propagate to window
window.clearTimeout(to);
var c = String.fromCharCode(e.which);

View File

@ -367,16 +367,16 @@ define([
text: Messages.languageButton, // Button initial text
options: options, // Entries displayed in the menu
isSelect: true,
isSubmenuOf: $drawer,
feedback: 'CODE_LANGUAGE',
common: Common
};
var $block = exp.$language = UIElements.createDropdown(dropdownConfig);
$block.find('button').attr('title', Messages.languageButtonTitle).hide();
$block.prepend(h('span.cp-language-text', Messages.languageButton));
$block.addClass('cp-dropdown-recursive');
var isHovering = false;
var $aLanguages = $block.find('li');
var $aLanguages = $block.$menu.find('li');
$aLanguages.mouseenter(function () {
isHovering = true;
setMode($(this).find('a').attr('data-value'));
@ -432,6 +432,7 @@ define([
text: Messages.code_editorTheme, // Button initial text
options: options, // Entries displayed in the menu
isSelect: true,
isSubmenuOf: $drawer,
initialValue: lastTheme,
feedback: 'CODE_THEME',
common: Common
@ -447,12 +448,11 @@ define([
});*/
$block.find('button').hide();
$block.prepend(h('span.cp-theme-text', Messages.languageButton));
$block.addClass('cp-dropdown-recursive');
setTheme(lastTheme, $block);
var isHovering = false;
var $aThemes = $block.find('li');
var $aThemes = $block.$menu.find('li');
$aThemes.mouseenter(function () {
isHovering = true;
var theme = $(this).find('a').attr('data-value');