From 67cdadca1fb3138546cf4a725cfa91e51b8d1974 Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 7 Mar 2024 18:39:10 +0100 Subject: [PATCH] Dropdown accessibility: handle submenus and other fixes --- customize.dist/src/less2/include/drive.less | 7 + .../src/less2/include/dropdown.less | 12 ++ customize.dist/src/less2/include/toolbar.less | 39 ++-- www/code/inner.js | 22 +-- www/code/markers.js | 4 +- www/common/common-ui-elements.js | 178 ++++++------------ www/common/common-util.js | 2 +- www/common/sframe-app-framework.js | 10 +- www/common/sframe-common-codemirror.js | 33 ++-- www/common/toolbar.js | 20 +- www/slide/inner.js | 4 +- 11 files changed, 155 insertions(+), 176 deletions(-) diff --git a/customize.dist/src/less2/include/drive.less b/customize.dist/src/less2/include/drive.less index 5137f07e0..239f73287 100644 --- a/customize.dist/src/less2/include/drive.less +++ b/customize.dist/src/less2/include/drive.less @@ -1038,6 +1038,13 @@ align-items: center; } } + .cp-dropdown-container { + button { + .cp-icon { + margin-left: 5px; + } + } + } } .cp-app-drive-button { diff --git a/customize.dist/src/less2/include/dropdown.less b/customize.dist/src/less2/include/dropdown.less index 46a4e9bd6..18aa262e2 100644 --- a/customize.dist/src/less2/include/dropdown.less +++ b/customize.dist/src/less2/include/dropdown.less @@ -48,6 +48,14 @@ position: relative; display: inline-block; + &.cp-dropdown-recursive { + position: unset; + .cp-dropdown-content { + top: 0; + left: 100%; + } + } + .fa { font-family: FontAwesome; } @@ -76,6 +84,10 @@ font: @dropdown_font; line-height: 1em; + &.cp-dropdown-has-submenu { + overflow: visible; + } + &.cp-dropdown-left { right: 0; margin-right: 5px; diff --git a/customize.dist/src/less2/include/toolbar.less b/customize.dist/src/less2/include/toolbar.less index 12c3736fc..9f7c369f8 100644 --- a/customize.dist/src/less2/include/toolbar.less +++ b/customize.dist/src/less2/include/toolbar.less @@ -523,11 +523,6 @@ &::before { padding-top: 1px; } - // .cp-dropdown-button-title { - // transform: scale(0.5); - // bottom: -5px; - // right: -5px; - // } } } .cp-toolbar-user-dropdown { @@ -1053,7 +1048,7 @@ &.cp-toolbar-small { button { - .cp-toolbar-name, .cp-button-name { + .cp-toolbar-name, .cp-button-name, .cp-dropdown-button-title { display: none; } i, span { @@ -1127,27 +1122,29 @@ order: 8; } .cp-toolbar-file { - button { - &.fa-plus { order: 0; } - &.fa-history { order: 5; } - &.fa-hashtag { order: 10; } - &.fa-bookmark { order: 15; } - &.fa-upload { order: 20; } - &.fa-files-o { order: 25; } - &.fa-download { order: 30; } - &.fa-print { order: 35; } - &.fa-trash { order: 40; } - &.cp-toolbar-icon-pad-settings { order: 75; } - &.fa-info-circle { order: 100; } + li, button { + .fa-plus { order: 0; } + .fa-history { order: 5; } + .fa-hashtag { order: 10; } + .fa-bookmark { order: 15; } + .fa-upload { order: 20; } + .fa-files-o { order: 25; } + .fa-download { order: 30; } + .fa-print { order: 35; } + .fa-trash { order: 40; } + .cp-toolbar-icon-pad-settings { order: 75; } + .fa-info-circle { order: 100; } - &.cp-toolbar-icon-help { order: 150; } + .fa-question { order: 150; } + + span { order: 1000; } // text always after icon } } - .cp-toolbar-drawer-content:empty ~ .cp-toolbar-drawer-button { + .cp-toolbar-drawer-contentsss:empty ~ .cp-toolbar-drawer-button { display: none; } - .cp-toolbar-drawer-content { + .cp-toolbar-drawer-contentsss { box-shadow: 0px 1px 5px 0px @cp_shadow-color; border-radius: @variables_radius; overflow-y: auto; diff --git a/www/code/inner.js b/www/code/inner.js index 492fc82e0..a7d925932 100644 --- a/www/code/inner.js +++ b/www/code/inner.js @@ -89,11 +89,11 @@ define([ text: Messages.toolbar_theme, options: [], common: Common, - buttonCls: 'cptools cptools-palette' + iconCls: 'cptools cptools-palette' }); framework._.toolbar.$theme = $drawer.find('ul.cp-dropdown-content'); framework._.toolbar.$bottomL.append($drawer); - $drawer.find('span').addClass('cp-button-name'); + $drawer.addClass('cp-toolbar-appmenu'); }; var mkCbaButton = function (framework, markers) { @@ -105,15 +105,12 @@ define([ var $showAuthorColors = UIElements.createDropdownEntry({ tag: 'a', - attributes: {'class': $showAuthorColorsButton.attr('class')}, - content: [ - h('i', { 'class': $showAuthorColorsButton.children('i').attr('class') }), - h('span', $showAuthorColorsButton.text()) - ], + attributes: {'class': 'fa fa-paint-brush ' + $showAuthorColorsButton.attr('class')}, + content: h('span', $showAuthorColorsButton.text()), action: function () { $showAuthorColorsButton.click(); }, - }); + }).hide(); $showAuthorColors.find('span').addClass('cp-toolbar-name cp-toolbar-drawer-element'); framework._.toolbar.$theme.append($showAuthorColors); markers.setButton($showAuthorColors); @@ -425,16 +422,13 @@ define([ }); var $cba = UIElements.createDropdownEntry({ tag: 'a', - attributes: {'class': $cbaButton.attr('class')}, - content: [ - h('i', { 'class': $cbaButton.children('i').attr('class') }), - h('span', $cbaButton.text()) - ], + attributes: {'class': 'fa fa-paint-brush ' + $cbaButton.attr('class')}, + content: h('span', $cbaButton.text()), action: function () { $cbaButton.click(); }, }); - framework._.toolbar.$theme.append($cba); + framework._.toolbar.$theme.prepend($cba); // Put at the top }; var mkFilePicker = function (framework, editor, evModeChange) { diff --git a/www/code/markers.js b/www/code/markers.js index 0d53b5dd8..c96d22168 100644 --- a/www/code/markers.js +++ b/www/code/markers.js @@ -624,11 +624,11 @@ define([ if (Env.opacity) { Env.opacity = 0; $button.find('.cp-toolbar-drawer-element').text(Messages.cba_show); - $button.removeClass("cp-toolbar-button-active"); + //$button.removeClass("cp-toolbar-button-active"); } else { Env.opacity = MARK_OPACITY; $button.find('.cp-toolbar-drawer-element').text(Messages.cba_hide); - $button.addClass("cp-toolbar-button-active"); + //$button.addClass("cp-toolbar-button-active"); } }; toggle(); diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index b36a2f834..ab619490a 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -859,10 +859,9 @@ define([ ])).click(common.prepareFeedback(type)); break; case 'storeindrive': - button = $(h('button.cp-toolbar-storeindrive', { + button = $(h('button.cp-toolbar-storeindrive.fa.fa-hdd-o', { style: 'display:none;' }, [ - h('i.fa.fa-hdd-o'), h('span.cp-toolbar-name.cp-toolbar-drawer-element', Messages.toolbar_storeInDrive) ])).click(common.prepareFeedback(type)).click(function () { $(button).hide(); @@ -1454,7 +1453,12 @@ define([ }; UIElements.createDropdownEntry = function (config) { + var hide = function () {}; var allowedTags = ['a', 'li', 'p', 'hr', 'div']; + var isElement = function (o) { + return /HTML/.test(Object.prototype.toString.call(o)) && + typeof(o.tagName) === 'string'; + }; var isValidOption = function (o) { if (typeof o !== "object") { return false; } if (isElement(o)) { return true; } @@ -1462,15 +1466,8 @@ define([ return true; }; - var isElement = function (o) { - return /HTML/.test(Object.prototype.toString.call(o)) && - typeof(o.tagName) === 'string'; - }; var entry; - - if (!isValidOption(config)) { - return null; - } + if (!isValidOption(config)) { return; } if (isElement(config)) { entry = $(config); @@ -1512,18 +1509,14 @@ define([ entry.append($el); // Action can be triggered with a click or keyboard event - if (config.tag !== 'a' && config.tag !== 'li') { - return null; - } + if (config.tag === 'a' || config.tag === 'li') { + entry.on('mouseenter', (e) => { + e.stopPropagation(); + entry.focus(); + }); - entry.on('mouseenter', (e) => { - e.stopPropagation(); - entry.focus(); - }); - - entry.on('click keydown', function(e) { - if (config.isSelect) { return; } - if (e.type === 'click' || (e.type === 'keydown' && e.keyCode === 13) || (e.type === 'keydown' && e.keyCode === 32)) { + Util.onClickEnter(entry, function(e) { + if (config.isSelect) { return; } e.stopPropagation(); if (typeof(config.action) === "function") { var close = config.action(e); @@ -1532,10 +1525,17 @@ define([ // Click on with an href if (e.type === 'keydown'){ $el.get(0).click(); } } - } - }); + }, {space: true}); + } } + hide = function () { + window.setTimeout(function () { + entry.closest('ul.cp-dropdown-content').hide(); + entry.parents('.cp-dropdown-content').removeClass('cp-dropdown-has-submenu').hide(); + }, 0); + }; + return entry; }; @@ -1576,37 +1576,23 @@ define([ } // Button - var $button; - - if (config.buttonContent) { - $button = $(h('button', { - class: config.buttonCls || '', - 'aria-haspopup': 'menu', - 'aria-expanded': 'false', - 'title': config.buttonTitle || '', - 'aria-label': config.buttonTitle || '', - }, [ - h('span.cp-dropdown-button-title', config.buttonContent), - ])); - } else { - $button = $('