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 38f6033d0..5b49a6846 100644 --- a/customize.dist/src/less2/include/dropdown.less +++ b/customize.dist/src/less2/include/dropdown.less @@ -48,6 +48,16 @@ position: relative; display: inline-block; + // 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%; + } + } + } + .fa { font-family: FontAwesome; } @@ -61,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; @@ -76,9 +96,8 @@ font: @dropdown_font; line-height: 1em; - &.cp-dropdown-left { - right: 0; - margin-right: 5px; + &.cp-dropdown-submenu { + left: 250px; } &:hover { @@ -140,9 +159,13 @@ } li[role="menuitem"] { border-radius: @variables_radius; - &:hover, &:focus { + white-space: nowrap; + &:hover { background-color: @cp_dropdown-bg-hover !important; - color: @cp_dropdown-fg; + //color: @cp_dropdown-fg; + } + &:focus-visible { + outline-color: @cp_dropdown-fg; } } &> span { diff --git a/customize.dist/src/less2/include/toolbar.less b/customize.dist/src/less2/include/toolbar.less index 12c3736fc..ac16f77ff 100644 --- a/customize.dist/src/less2/include/toolbar.less +++ b/customize.dist/src/less2/include/toolbar.less @@ -366,7 +366,7 @@ .cp-toolbar { * { outline-style: none; - &:focus { + &:focus-visible { outline: @cryptpad_color_brand solid 2px; } } @@ -523,11 +523,6 @@ &::before { padding-top: 1px; } - // .cp-dropdown-button-title { - // transform: scale(0.5); - // bottom: -5px; - // right: -5px; - // } } } .cp-toolbar-user-dropdown { @@ -960,6 +955,11 @@ &:empty { height: 0; } + + & > div:empty { + display: none; + } + .cp-toolbar-users { pre { /* needed for ckeditor */ @@ -1053,7 +1053,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 +1127,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 375423e02..6fe038064 100644 --- a/www/code/inner.js +++ b/www/code/inner.js @@ -18,6 +18,7 @@ define([ '/common/TypingTests.js', '/customize/messages.js', 'cm/lib/codemirror', + '/common/common-ui-elements.js', 'css!cm/lib/codemirror.css', @@ -64,7 +65,8 @@ define([ Visible, TypingTest, Messages, - CMeditor) + CMeditor, + UIElements) { window.CodeMirror = CMeditor; @@ -82,19 +84,15 @@ define([ ]); var mkThemeButton = function (framework) { - var $theme = $(h('button.cp-toolbar-appmenu', [ - h('i.cptools.cptools-palette'), - h('span.cp-button-name', Messages.toolbar_theme) - ])); - var $content = $(h('div.cp-toolbar-drawer-content', { - tabindex: 1 - })).hide(); - - // set up all the necessary events - UI.createDrawer($theme, $content); - - framework._.toolbar.$theme = $content; - framework._.toolbar.$bottomL.append($theme); + const $drawer = UIElements.createDropdown({ + text: Messages.toolbar_theme, + options: [], + common: framework._.sfCommon, + iconCls: 'cptools cptools-palette' + }); + framework._.toolbar.$theme = $drawer.find('ul.cp-dropdown-content'); + framework._.toolbar.$bottomL.append($drawer); + $drawer.addClass('cp-toolbar-appmenu'); }; var mkCbaButton = function (framework, markers) { @@ -103,10 +101,12 @@ define([ name: 'authormarks', icon: 'fa-paint-brush', }).hide(); - framework._.toolbar.$theme.append($showAuthorColorsButton); - markers.setButton($showAuthorColorsButton); + var $showAuthorColors = UIElements.getEntryFromButton($showAuthorColorsButton).hide(); + $showAuthorColors.find('span').addClass('cp-toolbar-name cp-toolbar-drawer-element'); + framework._.toolbar.$theme.append($showAuthorColors); + markers.setButton($showAuthorColors); }; - var mkPrintButton = function (framework, $content, $print) { + var mkPrintButton = function (framework, $content) { var $printButton = framework._.sfCommon.createButton('print', true); $printButton.click(function () { $print.html($content.html()); @@ -114,7 +114,8 @@ define([ window.print(); framework.feedback('PRINT_CODE'); }); - framework._.toolbar.$drawer.append($printButton); + var $print = UIElements.getEntryFromButton($printButton); + framework._.toolbar.$drawer.append($print); }; var mkMarkdownTb = function (editor, framework) { var $codeMirrorContainer = $('#cp-app-code-container'); @@ -137,7 +138,8 @@ define([ var helpMenu = framework._.sfCommon.createHelpMenu(['text', 'code']); $codeMirrorContainer.prepend(helpMenu.menu); - framework._.toolbar.$drawer.append(helpMenu.button); + var $helpMenuButton = UIElements.getEntryFromButton(helpMenu.button); + framework._.toolbar.$drawer.append($helpMenuButton); }; var previews = {}; @@ -393,7 +395,8 @@ define([ setButton(!markers.getState()); UI.alert(content); }); - framework._.toolbar.$theme.append($cbaButton); + var $cba = UIElements.getEntryFromButton($cbaButton); + framework._.toolbar.$theme.prepend($cba); }; var mkFilePicker = function (framework, editor, evModeChange) { diff --git a/www/code/markers.js b/www/code/markers.js index 0d53b5dd8..b2a630cf3 100644 --- a/www/code/markers.js +++ b/www/code/markers.js @@ -25,7 +25,7 @@ define([ var debug = function () {}; - var MARK_OPACITY = 0.5; + var MARK_OPACITY = 0.2; var DEFAULT = { authors: {}, marks: [[-1, 0, 0, Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]] @@ -624,11 +624,9 @@ define([ if (Env.opacity) { Env.opacity = 0; $button.find('.cp-toolbar-drawer-element').text(Messages.cba_show); - $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"); } }; toggle(); diff --git a/www/common/common-interface.js b/www/common/common-interface.js index 8b30901b5..e8d55c59b 100644 --- a/www/common/common-interface.js +++ b/www/common/common-interface.js @@ -1466,44 +1466,6 @@ define([ }; }; - /* Given two jquery objects (a 'button' and a 'drawer') - add handlers to make it such that clicking the button - displays the drawer contents, and blurring the button - hides the drawer content. Used for toolbar buttons at the moment. - */ - UI.createDrawer = function ($button, $content) { - $button.click(function () { - var topPos = $button[0].getBoundingClientRect().bottom; - $content.toggle(); - $button.removeClass('cp-toolbar-button-active'); - if ($content.is(':visible')) { - $button.addClass('cp-toolbar-button-active'); - $content.focus(); - var wh = $(window).height(); - $content.css('max-height', Math.floor(wh - topPos - 1)+'px'); - } - }); - var onBlur = function (e) { - if (e.relatedTarget) { - var $relatedTarget = $(e.relatedTarget); - - if ($relatedTarget.is('.cp-toolbar-drawer-button')) { return; } - if ($relatedTarget.parents('.cp-toolbar-drawer-content').length) { - $relatedTarget.blur(onBlur); - return; - } - } - $button.removeClass('cp-toolbar-button-active'); - $content.hide(); - }; - $content.blur(onBlur).appendTo($button); - $('body').keydown(function (e) { - if (e.which === 27) { - $content.blur(); - } - }); - }; - /* QR code generation is synchronous once the library is loaded so this could be syncronous if we load the library separately. */ UI.createQRCode = function (data, _cb) { diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index e01a0835a..cccce667d 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -577,12 +577,38 @@ define([ }); }; + UIElements.getEntryFromButton = function ($button) { + if (!$button || !$button.length) { return; } + let $icon = $button.find('> i'); + + let attributes = {}; + let btnClass = $button.attr('class'); + let btnId = $button.attr('id'); + if (btnClass) { attributes['class'] = btnClass; } + if (btnId) { attributes['id'] = btnId; } + + return UIElements.createDropdownEntry({ + tag: 'a', + attributes: attributes, + content: [ + h('i',{ 'class': $icon.attr('class') }), + h('span', $button.text()) + ], + action: function () { + $button.click(); + return true; + } + }); + }; + + UIElements.createButton = function (common, type, rightside, data, callback) { var AppConfig = common.getAppConfig(); var button; var sframeChan = common.getSframeChannel(); var appType = (common.getMetadataMgr().getMetadata().type || 'pad').toUpperCase(); data = data || {}; + if (!callback && data.callback) { callback = data.callback; } switch (type) { case 'export': button = $('