diff --git a/edit.html b/edit.html
index b162045a..8907cd5b 100644
--- a/edit.html
+++ b/edit.html
@@ -271,13 +271,16 @@
-
diff --git a/edit/edit.css b/edit/edit.css
index 0553f5bf..0ad6eec7 100644
--- a/edit/edit.css
+++ b/edit/edit.css
@@ -260,23 +260,13 @@ input:invalid {
margin-top: .5rem;
}
-#actions > * {
- display: inline-flex;
- flex-wrap: wrap;
-}
-
-#mozilla-format-buttons {
+#actions .buttons {
display: flex;
flex-wrap: wrap;
align-items: center;
}
-#actions > div > a {
- height: min-content;
-}
-
-#actions button,
-#actions > div > a {
+#actions .buttons > * {
margin: 0 .2rem .5rem 0;
}
@@ -1065,11 +1055,7 @@ body.linter-disabled .hidden-unless-compact {
padding: .25rem 0 .5rem;
}
#actions {
- display: flex;
- flex-wrap: wrap;
white-space: nowrap;
- margin: 0;
- box-sizing: border-box;
}
#header input[type="checkbox"] {
vertical-align: middle;
diff --git a/edit/source-editor.js b/edit/source-editor.js
index b9ce6c66..fb118b1c 100644
--- a/edit/source-editor.js
+++ b/edit/source-editor.js
@@ -23,7 +23,7 @@ function SourceEditor() {
$('#header').on('wheel', headerOnScroll);
$('#sections').textContent = '';
$('#sections').appendChild($create('.single-editor'));
- $('[i18n-text="saveAsTemplate"]').onclick = saveTemplate;
+ $('#save-button').onauxclick = e => e.detail === 'tpl' && saveTemplate();
const cm = cmFactory.create($('.single-editor'));
const sectionFinder = MozSectionFinder(cm);
diff --git a/global.css b/global.css
index 95440557..0f094b85 100644
--- a/global.css
+++ b/global.css
@@ -6,6 +6,7 @@ html#stylus #header *:not(#\1transition-suppressor) {
}
:root {
--family: Arial, "Helvetica Neue", Helvetica, system-ui, sans-serif;
+ --bg: #fff;
}
body {
font: normal 12px var(--family);
@@ -33,6 +34,7 @@ button {
border: 1px solid hsl(0, 0%, 62%);
font: inherit;
font-size: 13px;
+ line-height: 1.2;
color: #000;
background-color: hsl(0, 0%, 100%);
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAeCAYAAADtlXTHAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QwGBBwIHvKt6QAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAL0lEQVQI12NoaGgQZ2JgYGBkYmBgYGZiYGBggrMY4VxsYsyoskQQCB2MWAxAMhkADVECDhlW9CoAAAAASUVORK5CYII=');
@@ -307,6 +309,39 @@ body.resizing-v > * {
}
/* header resizer - end */
+.split-btn {
+ position: relative;
+}
+.split-btn-pedal {
+ margin-left: -1px !important;
+ padding-left: .2em !important;
+ padding-right: .2em !important;
+}
+.split-btn-pedal::after {
+ content: '\25BC'; /* down triangle */
+ font-size: 90%;
+}
+.split-btn-pedal.active {
+ box-shadow: inset 0 0 100px rgba(0, 0, 0, .2);
+}
+.split-btn-menu {
+ background: #fff;
+ position: absolute;
+ box-shadow: 2px 3px 7px rgba(0, 0, 0, .5);
+ border: 1px solid hsl(180deg, 50%, 50%);
+ white-space: nowrap;
+ cursor: pointer;
+ padding: .25em 0;
+}
+.split-btn-menu > * {
+ padding: .5em 1em;
+ display: block;
+}
+.split-btn-menu > :hover {
+ background-color: hsla(180deg, 50%, 50%, .25);
+ color: #000;
+}
+
@supports (-moz-appearance: none) {
.moz-appearance-bug .svg-icon.checked,
.moz-appearance-bug .onoffswitch input,
diff --git a/js/dom-on-load.js b/js/dom-on-load.js
index 828d14c8..634ae5dd 100644
--- a/js/dom-on-load.js
+++ b/js/dom-on-load.js
@@ -1,4 +1,4 @@
-/* global $ $$ focusAccessibility getEventKeyName */// dom.js
+/* global $$ $ $create focusAccessibility getEventKeyName moveFocus */// dom.js
/* global debounce */// toolbox.js
/* global t */// localization.js
'use strict';
@@ -6,13 +6,14 @@
/** DOM housekeeping after a page finished loading */
(() => {
+ const SPLIT_BTN_MENU = '.split-btn-menu';
splitLongTooltips();
addTooltipsToEllipsized();
window.on('mousedown', suppressFocusRingOnClick, {passive: true});
window.on('keydown', keepFocusRingOnTabbing, {passive: true});
window.on('keypress', clickDummyLinkOnEnter);
window.on('wheel', changeFocusedInputOnWheel, {capture: true, passive: false});
- window.on('click', showTooltipNote);
+ window.on('click', e => splitMenu(e) || showTooltipNote(e));
window.on('resize', () => debounce(addTooltipsToEllipsized, 100));
// Removing transition-suppressor rule
const {sheet} = $('link[href$="global.css"]');
@@ -78,19 +79,44 @@
let el = document.activeElement;
if (el) {
el = el.closest('[data-focused-via-click]');
- if (el) delete el.dataset.focusedViaClick;
+ focusAccessibility.toggle(el, false);
}
});
}
}
+ function splitMenu(event) {
+ const prevMenu = $(SPLIT_BTN_MENU);
+ const prevPedal = (prevMenu || {}).previousElementSibling;
+ const pedal = event.target.closest('.split-btn-pedal');
+ const entry = prevMenu && event.target.closest(SPLIT_BTN_MENU + '>*');
+ if (prevMenu) prevMenu.remove();
+ if (prevPedal) prevPedal.classList.remove('active');
+ if (pedal && pedal !== prevPedal) {
+ const menu = $create(SPLIT_BTN_MENU,
+ Array.from(pedal.attributes, ({name, value}) =>
+ name.startsWith('menu-') &&
+ $create('a', {tabIndex: 0, __cmd: name.split('-').pop()}, value)
+ ));
+ menu.on('focusout', e => e.target === menu && splitMenu(e));
+ pedal.classList.toggle('active');
+ pedal.after(menu);
+ moveFocus(menu, 0);
+ focusAccessibility.toggle(menu.firstChild, focusAccessibility.get(pedal));
+ }
+ if (entry) {
+ prevPedal.previousElementSibling.dispatchEvent(new CustomEvent('auxclick', {
+ detail: entry.__cmd,
+ bubbles: true,
+ }));
+ }
+ }
+
function suppressFocusRingOnClick({target}) {
const el = focusAccessibility.closest(target);
if (el) {
focusAccessibility.lastFocusedViaClick = true;
- if (el.dataset.focusedViaClick === undefined) {
- el.dataset.focusedViaClick = '';
- }
+ focusAccessibility.toggle(el, true);
}
}
diff --git a/js/dom.js b/js/dom.js
index 5cb50aeb..a650a387 100644
--- a/js/dom.js
+++ b/js/dom.js
@@ -31,6 +31,8 @@ Object.assign(EventTarget.prototype, {
const focusAccessibility = {
// last event's focusedViaClick
lastFocusedViaClick: false,
+ get: el => el && el.dataset.focusedViaClick != null,
+ toggle: (el, state) => el && toggleDataset(el, 'focusedViaClick', state),
// to avoid a full layout recalc due to changes on body/root
// we modify the closest focusable element (like input or button or anything with tabindex=0)
closest(el) {