diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less index f01e69a37..9d97d82d4 100644 --- a/customize.dist/src/less2/include/alertify.less +++ b/customize.dist/src/less2/include/alertify.less @@ -198,6 +198,12 @@ text-decoration: none; } } + .cp-usergrid-user, textarea, a, .fa-times { + outline: none; + &:focus { + outline: @cryptpad_color_brand solid 2px; + } + } } .cp-alertify-type-container { overflow: visible !important; @@ -237,6 +243,10 @@ } } } + outline: none; + &:focus { + outline: @cryptpad_color_brand solid 2px; + } } span.alertify-tabs-active { background-color: @cp_alertify-fg !important; @@ -263,6 +273,10 @@ input { .tools_placeholder-color(); + outline: none; + &:focus-visible { + outline: @cryptpad_color_brand solid 2px; + } } span.cp-password-container { diff --git a/customize.dist/src/less2/include/checkmark.less b/customize.dist/src/less2/include/checkmark.less index 723f4297a..18e2c4ac9 100644 --- a/customize.dist/src/less2/include/checkmark.less +++ b/customize.dist/src/less2/include/checkmark.less @@ -128,9 +128,9 @@ position: absolute; box-sizing: border-box; } + outline: none; &:focus { - box-shadow: 0px 0px 5px @cp_checkmark-back1; - outline: none; + outline: @cryptpad_color_brand solid 2px; } } @@ -216,9 +216,9 @@ height: @checkmark-dim1; height: var(--checkmark-dim1); } + outline: none; &:focus { - box-shadow: 0px 0px 5px @cp_checkmark-back1; - outline: none; + outline: @cryptpad_color_brand solid 2px; } } diff --git a/customize.dist/src/less2/include/forms.less b/customize.dist/src/less2/include/forms.less index 2f5777771..3c018e365 100644 --- a/customize.dist/src/less2/include/forms.less +++ b/customize.dist/src/less2/include/forms.less @@ -122,7 +122,6 @@ button.btn { background-color: @cp_buttons-cancel; box-sizing: border-box; - outline: 0; align-items: center; padding: 0 6px; line-height: 36px; @@ -232,11 +231,9 @@ } - + outline: none; &:focus { - //border: 1px dotted @alertify-base; - box-shadow: 0px 0px 5px @cp_buttons-primary !important; - outline: none; + outline: @cryptpad_color_brand solid 2px; } &::-moz-focus-inner { border: 0; diff --git a/customize.dist/src/less2/include/toolbar.less b/customize.dist/src/less2/include/toolbar.less index 76333017b..1b43df84e 100644 --- a/customize.dist/src/less2/include/toolbar.less +++ b/customize.dist/src/less2/include/toolbar.less @@ -780,7 +780,7 @@ padding: 10px; color: @toolbar-bg-color; color: var(--toolbar-bg-color); - border-radius: 5px; + border-radius: @variables_radius; span { font-size: 45px; diff --git a/customize.dist/src/less2/include/usergrid.less b/customize.dist/src/less2/include/usergrid.less index 475f9cde1..bfddc84a3 100644 --- a/customize.dist/src/less2/include/usergrid.less +++ b/customize.dist/src/less2/include/usergrid.less @@ -115,7 +115,8 @@ } } .fa-times { - padding-left: 5px; + border-radius: @variables_radius; + margin-left: 5px; cursor: pointer; height: 100%; line-height: 25px; diff --git a/www/common/common-interface.js b/www/common/common-interface.js index 50a4c3991..26584da30 100644 --- a/www/common/common-interface.js +++ b/www/common/common-interface.js @@ -240,11 +240,15 @@ define([ if (!(tab.content || tab.disabled) || !tab.title) { return; } var content = h('div.alertify-tabs-content', tab.content); var title = h('span.alertify-tabs-title'+ (tab.disabled ? '.disabled' : ''), h('span.tab-title-text',{id: 'cp-tab-' + tab.title.toLowerCase(), 'aria-hidden':"true"}, tab.title)); + $(title).attr('tabindex', '0'); if (tab.icon) { var icon = h('i', {class: tab.icon, 'aria-labelledby': 'cp-tab-' + tab.title.toLowerCase()}); $(title).prepend(' ').prepend(icon); } - $(title).click(function () { + + Util.onClickEnter($(title), function (event) { + event.preventDefault(); + event.stopPropagation(); if (tab.disabled) { return; } var old = tabs[active]; if (old.onHide) { old.onHide(); } @@ -330,7 +334,6 @@ define([ if (isEdit) { $button.find('span').text(Messages.tag_edit); } else { $button.find('span').text(Messages.add); } $container.append($form); - $input.focus(); isEdit = false; called = false; }); @@ -486,7 +489,7 @@ define([ var navs = []; buttons.forEach(function (b) { if (!b.name || !b.onClick) { return; } - var button = h('button', { tabindex: '1', 'class': b.className || '' }, [ + var button = h('button', { 'class': b.className || '' }, [ b.iconClass ? h('i' + b.iconClass) : undefined, b.name ]); @@ -509,7 +512,8 @@ define([ divClasses: 'left' }, todo); } else { - $(button).click(function () { + Util.onClickEnter($(button), function (e) { + e.stopPropagation(); todo(); }); } @@ -548,6 +552,34 @@ define([ if (opt.forefront) { $(frame).addClass('forefront'); } return frame; }; + + let addTabListener = frame => { + // find focusable elements + let modalElements = $(frame).find('a, button, input, [tabindex]:not([tabindex="-1"]), textarea').filter(':visible'); + // intialize with focus on first element + modalElements[0].focus(); + + $(frame).on('keydown', function (e) { + modalElements = $(frame).find('a, button, input, [tabindex]:not([tabindex="-1"]), textarea').filter(':visible'); // for modals with dynamic content + + if (e.which === 9) { // Tab + if (e.shiftKey) { + // On the first element, shift+tab goes to last + if (document.activeElement === modalElements[0]) { + e.preventDefault(); + modalElements[modalElements.length - 1].focus(); + } + } else { + // On the last element, tab goes to first + if (document.activeElement === modalElements[modalElements.length - 1]) { + e.preventDefault(); + modalElements[0].focus(); + } + } + } + }); + + }; UI.openCustomModal = function (content, opt) { var frame = dialog.frame([ content @@ -564,6 +596,9 @@ define([ setTimeout(function () { Notifier.notify(); }); + + addTabListener(frame); + return frame; }; @@ -742,13 +777,28 @@ define([ var $ok = $(ok).click(function (ev) { close(true, ev); }); var $cancel = $(cancel).click(function (ev) { close(false, ev); }); + document.body.appendChild(frame); + + addTabListener(frame); + + frame.addEventListener('keydown', function(e) { + if (e.keyCode === 13) { + if (document.activeElement === $ok[0]) { + $ok.click(); + } else if (document.activeElement === $cancel[0]) { + $cancel.click(); + } + } else if (e.keyCode === 27) { + $cancel.click(); + } + }); + listener = listenForKeys(function () { $ok.click(); }, function () { $cancel.click(); }, frame); - document.body.appendChild(frame); setTimeout(function () { Notifier.notify(); $(frame).find('.ok').focus(); @@ -815,15 +865,19 @@ define([ }; var newCls2 = config.new ? 'new' : ''; - $(originalBtn).addClass('cp-button-confirm-placeholder').addClass(newCls2).click(function (e) { - e.stopPropagation(); - // If we have a validation function, continue only if it's true - if (config.validate && !config.validate()) { return; } - i = 1; - to = setTimeout(todo, INTERVAL); - $(originalBtn).hide().after(content); + $(originalBtn).addClass('cp-button-confirm-placeholder').addClass(newCls2).on('click keydown', function (e) { + if (e.type === 'click' || (e.type === 'keydown' && e.key === 'Enter')) { + e.stopPropagation(); + // If we have a validation function, continue only if it's true + if (config.validate && !config.validate()) { return; } + i = 1; + to = setTimeout(todo, INTERVAL); + $(originalBtn).hide().after(content); + $(button).focus(); + } }); + return { reset: function () { done(false); @@ -1217,7 +1271,7 @@ define([ $mark.keydown(function (e) { if ($input.is(':disabled')) { return; } - if (e.which === 32) { + if (e.which === 32 || e.which === 13){ e.stopPropagation(); e.preventDefault(); $input.prop('checked', !$input.is(':checked')); @@ -1270,7 +1324,7 @@ define([ $(mark).keydown(function (e) { if ($input.is(':disabled')) { return; } - if (e.which === 32) { + if (e.which === 13 || e.which === 32) { e.stopPropagation(); e.preventDefault(); if ($input.is(':checked')) { return; } diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index c25f956fe..8fc65140c 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -173,8 +173,12 @@ define([ var removeBtn, el; if (config.remove) { removeBtn = h('span.fa.fa-times'); - $(removeBtn).click(function () { - config.remove(el); + $(removeBtn).attr('tabindex', '0'); + $(removeBtn).on('click keydown', function(event) { + if (event.type === 'click' || (event.type === 'keydown' && event.key === 'Enter')) { + event.preventDefault(); + config.remove(el); + } }); } @@ -184,6 +188,7 @@ define([ 'data-curve': data.curvePublic || '', 'data-name': name.toLowerCase(), 'data-order': i, + 'tabindex': '0', style: 'order:'+i+';' },[ avatar, @@ -231,6 +236,13 @@ define([ } onSelect(); }); + $div.on('keydown', '.cp-usergrid-user', function (e) { + if (e.which === 13) { + e.preventDefault(); + e.stopPropagation(); + $(this).trigger('click'); + } + }); } return { diff --git a/www/common/inner/access.js b/www/common/inner/access.js index de171f116..9159aac93 100644 --- a/www/common/inner/access.js +++ b/www/common/inner/access.js @@ -367,6 +367,13 @@ define([ UI.log(Messages.saved); }); }); + $(addBtn).on('keydown', function () { + if (event.keyCode === 13) { + event.preventDefault(); + event.stopPropagation(); + $(addBtn).click(); + } + }); var called = false; redrawAll = function (reload) { @@ -459,6 +466,9 @@ define([ var setLock = function (locked) { $(link).find('.cp-overlay').toggle(locked); + $(link).find('.cp-usergrid-user').attr('tabindex', locked ? -1 : 0); + $(link).find('.cp-usergrid-filter input').prop('disabled', locked); + $(link).find('.cp-access-add').prop('disabled', locked); }; // Remove owner column @@ -714,6 +724,13 @@ define([ UI.log(Messages.saved); }); }); + $(addBtn).on('keydown', function () { + if (event.keyCode === 13) { + event.preventDefault(); + event.stopPropagation(); + $(addBtn).click(); + } + }); var called = false; redrawAll = function (reload) { @@ -1025,6 +1042,13 @@ define([ }); }); }); + $(passwordOk).on('keydown', function (e) { + if (e.keyCode === 13) { + e.preventDefault(); + e.stopPropagation(); + $(passwordOk).click(); + } + }); $d.append(changePass); } if (owned) { diff --git a/www/common/sframe-common-codemirror.js b/www/common/sframe-common-codemirror.js index 2e84c2d11..aa1bde788 100644 --- a/www/common/sframe-common-codemirror.js +++ b/www/common/sframe-common-codemirror.js @@ -178,8 +178,7 @@ define([ }, //remove focus from editor "Esc": function () { - document.activeElement.blur(); - document.querySelector('.cp-toolbar-link-logo').focus(); + editor.display.input.blur(); }, "Shift-Tab": function () { editor.execCommand("indentLess"); diff --git a/www/kanban/app-kanban.less b/www/kanban/app-kanban.less index 7ef230158..f871964da 100644 --- a/www/kanban/app-kanban.less +++ b/www/kanban/app-kanban.less @@ -152,9 +152,17 @@ line-height: 30px; color: @cp_kanban-fg; border: 1px solid fade(@cp_kanban-fg, 40%); - &.fa-check { // tick on selected color + outline: none; + // tick on selected color + &.cp-kanban-palette-card.fa-check { color: @cryptpad_text_col; } + &.cp-kanban-palette-board.fa-check { + color: @cryptpad_text_col_inv; + } + &:focus{ + outline: @cryptpad_color_brand solid 2px; + } } } #cp-kanban-edit-tags { @@ -187,6 +195,11 @@ border: 0; background: transparent; align-self: flex-start; + outline-style: none; + border-radius: @variables_radius; + &:focus { + outline: @cryptpad_color_brand solid 2px; + } @media (hover: none) { margin-right: 20px; } diff --git a/www/kanban/inner.js b/www/kanban/inner.js index dbb7a91f0..6b2519c95 100644 --- a/www/kanban/inner.js +++ b/www/kanban/inner.js @@ -378,8 +378,15 @@ define([ }); }; palette.forEach(function (color) { - var $color = $(h('span.cp-kanban-palette.fa')); + var $color = $(h('button.cp-kanban-palette.fa')); $color.addClass('cp-kanban-palette-'+(color || 'nocolor')); + $color.keydown(function (e) { + if (e.which === 13) { + e.stopPropagation(); + e.preventDefault(); + $color.click(); + } + }); $color.click(function () { if (offline) { return; } if (color === selectedColor) { return; }