diff --git a/edit.html b/edit.html index 1c18e254..d64e112b 100644 --- a/edit.html +++ b/edit.html @@ -193,9 +193,7 @@ - - - + @@ -203,10 +201,14 @@
- +
-

+

+ + + +

@@ -249,9 +251,7 @@ - - - +
@@ -303,20 +303,17 @@
- - - + @@ -327,7 +324,9 @@
-

+

+ +

@@ -362,6 +361,5 @@ - diff --git a/edit/colorpicker-helper.js b/edit/colorpicker-helper.js index 03714092..547bd1c1 100644 --- a/edit/colorpicker-helper.js +++ b/edit/colorpicker-helper.js @@ -62,7 +62,8 @@ onDOMscriptReady('/colorview.js').then(() => { cm.state.colorpicker.openPopup(prefs.get('editor.colorpicker.color')); } - function configureColorpicker() { + function configureColorpicker(event) { + event.preventDefault(); const input = $create('input', { type: 'search', spellcheck: false, diff --git a/edit/edit.css b/edit/edit.css index 236c97a4..1d6c216f 100644 --- a/edit/edit.css +++ b/edit/edit.css @@ -76,19 +76,6 @@ label { min-height: 1.4rem; } -.svg-inline-wrapper { - outline: none; - text-decoration: none; -} - -.svg-inline-wrapper svg { - border-bottom: 1px dashed transparent; -} - -.svg-inline-wrapper:focus svg { - border-bottom-color: #AAA; -} - /* basic info */ #basic-info { margin-bottom: 1rem; @@ -106,21 +93,19 @@ label { #url:not([href^="http"]) { display: none; } -#save-button { - opacity: .5; - pointer-events: none; -} -.dirty #save-button { - opacity: 1; - pointer-events: all; -} .svg-icon { cursor: pointer; vertical-align: middle; transition: fill .5s; width: 16px; height: 16px; - margin-left: 0.2rem; +} +.svg-inline-wrapper { + margin-left: .2rem; + display: inline-block; +} +.aligned .svg-inline-wrapper { + margin-left: .25rem; } h2 .svg-icon, label .svg-icon { margin-top: -1px; @@ -619,6 +604,11 @@ html:not(.usercss) .usercss-only, display: none !important; /* hide during page init */ } +.usercss #name { + background-color: #eee; + color: #888; +} + #sections .single-editor { margin: 0; padding: 0; diff --git a/edit/edit.js b/edit/edit.js index e84c0fe4..3d4196da 100644 --- a/edit/edit.js +++ b/edit/edit.js @@ -273,8 +273,6 @@ function initHooks() { } } -// common for usercss and classic - function onChange(event) { const node = event.target; if ('savedValue' in node) { @@ -317,12 +315,6 @@ function setCleanItem(node, isClean) { function isCleanGlobal() { const clean = Object.keys(dirty).length === 0; setDirtyClass(document.body, !clean); - // let saveBtn = $('#save-button') - // if (clean){ - // //saveBtn.removeAttribute('disabled'); - // }else{ - // //saveBtn.setAttribute('disabled', true); - // } return clean; } @@ -406,6 +398,7 @@ function updateTitle() { const clean = isCleanGlobal(); const title = styleId === null ? t('addStyleTitle') : t('editStyleTitle', [name]); document.title = clean ? title : DIRTY_TITLE.replace('$', title); + $('#save-button').disabled = clean; } function updateLintReportIfEnabled(...args) { @@ -500,15 +493,18 @@ function fromMozillaFormat() { } } -function showSectionHelp() { +function showSectionHelp(event) { + event.preventDefault(); showHelp(t('styleSectionsTitle'), t('sectionHelp')); } -function showAppliesToHelp() { +function showAppliesToHelp(event) { + event.preventDefault(); showHelp(t('appliesLabel'), t('appliesHelp')); } -function showToMozillaHelp() { +function showToMozillaHelp(event) { + event.preventDefault(); showHelp(t('styleMozillaFormatHeading'), t('styleToMozillaFormatHelp')); } diff --git a/edit/lint.js b/edit/lint.js index f8792862..8f2170e6 100644 --- a/edit/lint.js +++ b/edit/lint.js @@ -149,7 +149,8 @@ var linterConfig = { }, // this is an event listener so it can't refer to self via 'this' - openOnClick() { + openOnClick(event) { + event.preventDefault(); setupLinterPopup(linterConfig.stringify()); }, diff --git a/global.css b/global.css index 264c222a..a13ffe91 100644 --- a/global.css +++ b/global.css @@ -1,13 +1,3 @@ -html:not([data-whatinput="keyboard"]) button, -html:not([data-whatinput="keyboard"]) input[type="checkbox"], -html:not([data-whatinput="keyboard"]) input[type="radio"], -html:not([data-whatinput="keyboard"]) #header summary, -html:not([data-whatinput="keyboard"]) .applies-to-extra-expander, -html:not([data-whatinput="keyboard"]) .regexp-report summary, -html:not([data-whatinput="keyboard"]) .regexp-report div { - outline: none; -} - button { -webkit-appearance: none; -moz-appearance: none; @@ -17,7 +7,8 @@ button { font: 400 13.3333px Arial; color: #000; background-color: hsl(0, 0%, 100%); - background: url(../images/button.png)repeat-x; + background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAeCAYAAADtlXTHAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QwGBBwIHvKt6QAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAL0lEQVQI12NoaGgQZ2JgYGBkYmBgYGZiYGBggrMY4VxsYsyoskQQCB2MWAxAMhkADVECDhlW9CoAAAAASUVORK5CYII='); + background-repeat: repeat-x; background-size: 100% 100%; transition: background-color .25s, border-color .25s; } @@ -30,7 +21,8 @@ button:not(:disabled):hover { button:active { background-color: hsl(0, 0%, 95%); border-color: hsl(0, 0%, 52%); - background: url(../images/button-active.png)repeat-x; + background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAeCAYAAADtlXTHAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QwJARIWJNZvuQAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAMElEQVQI12NoaGgIZmJgYPjLxMDA8I+JgYHhP5z1Dy7xH5X7jxQCzWQ0A9DEILYBABm5HtJk2jPHAAAAAElFTkSuQmCC'); + background-repeat: repeat-x; background-size: 100% 100%; } @@ -185,6 +177,11 @@ select[disabled] > option { display: none !important; } +[data-focused-via-click] :focus, +[data-focused-via-click]:focus { + outline: none; +} + @supports (-moz-appearance: none) { .moz-appearance-bug .svg-icon.checked, .moz-appearance-bug .onoffswitch input, diff --git a/images/button-active.png b/images/button-active.png deleted file mode 100644 index 32f40a68..00000000 Binary files a/images/button-active.png and /dev/null differ diff --git a/images/button.png b/images/button.png deleted file mode 100644 index 19d23892..00000000 Binary files a/images/button.png and /dev/null differ diff --git a/images/help.png b/images/help.png deleted file mode 100644 index 3ec0e7b9..00000000 Binary files a/images/help.png and /dev/null differ diff --git a/images/world_go.png b/images/world_go.png deleted file mode 100644 index 79239a2c..00000000 Binary files a/images/world_go.png and /dev/null differ diff --git a/install-usercss.html b/install-usercss.html index 2a6ad908..ea900b20 100644 --- a/install-usercss.html +++ b/install-usercss.html @@ -90,8 +90,7 @@
- - + diff --git a/js/dom.js b/js/dom.js index a2e54316..ee8cc022 100644 --- a/js/dom.js +++ b/js/dom.js @@ -57,6 +57,7 @@ $$.remove = (selector, base = document) => { onDOMready().then(() => { $.remove('#firefox-transitions-bug-suppressor'); initCollapsibles(); + focusAccessibility(); }); if (!chrome.app && chrome.windows) { @@ -314,3 +315,46 @@ function initCollapsibles({bindClickOn = 'h2'} = {}) { prefs.set(el.dataset.pref, el.open); } } + + +function focusAccessibility() { + // Makes the focus outline appear on keyboard tabbing, but not on mouse clicks. + // Since we don't want full layout recalc, we modify only the closest focusable element, + // which we try to find in DOM for this many parentElement jumps: + const focusables = focusAccessibility.ELEMENTS = + ['a', 'button', 'input', 'label', 'select', 'summary']; + const GIVE_UP_DEPTH = 4; + addEventListener('mousedown', suppressOutlineOnClick, {passive: true}); + addEventListener('keydown', keepOutlineOnTab, {passive: true}); + + function suppressOutlineOnClick({target}) { + for (let el = target, i = 0; el && i++ < GIVE_UP_DEPTH; el = el.parentElement) { + if (focusables.includes(el.localName)) { + if (el.dataset.focusedViaClick === undefined) { + el.dataset.focusedViaClick = ''; + } + return; + } + } + } + + function keepOutlineOnTab(event) { + if (event.which === 9) { + setTimeout(keepOutlineOnTab, 0, true); + return; + } else if (event !== true) { + return; + } + let el = document.activeElement; + if (!el || !focusables.includes(el.localName)) { + return; + } + if (el.dataset.focusedViaClick !== undefined) { + delete el.dataset.focusedViaClick; + } + el = el.closest('[data-focused-via-click]'); + if (el) { + delete el.dataset.focusedViaClick; + } + } +} diff --git a/manage.html b/manage.html index fc0bef30..cc8aef56 100644 --- a/manage.html +++ b/manage.html @@ -166,11 +166,13 @@

:

- - - - + + + + + +
@@ -341,7 +343,6 @@
- diff --git a/manage/config-dialog.css b/manage/config-dialog.css index 6a7eae56..46f5d4c3 100644 --- a/manage/config-dialog.css +++ b/manage/config-dialog.css @@ -93,20 +93,12 @@ margin-right: 4px; } -.config-reset-icon { - width: 16px; - display: inline-block; -} - -.config-body label:not(.nondefault) .config-reset-icon a { - display: none; +.config-body label:not(.nondefault) .config-reset-icon { + visibility: hidden; } .config-reset-icon .svg-icon { - /*position: absolute;*/ - pointer-events: none; cursor: pointer; - /*right: -7px;*/ fill: #aaa; width: 16px; height: 16px; diff --git a/manage/config-dialog.js b/manage/config-dialog.js index dd879b7d..503c5b39 100644 --- a/manage/config-dialog.js +++ b/manage/config-dialog.js @@ -30,13 +30,13 @@ function configDialog(style) { ], buttons: [{ textContent: t('confirmSave'), - dataset: {cmd: 'save', allowEnter: true}, + dataset: {cmd: 'save'}, disabled: true, onclick: save, }, { textContent: t('genericResetLabel'), title: t('optionsReset'), - dataset: {cmd: 'default', allowEnter: true}, + dataset: {cmd: 'default'}, onclick: useDefault, }, { textContent: t('confirmClose'), @@ -78,13 +78,7 @@ function configDialog(style) { updateButtons(); } - function onhide({button, enter}) { - if (enter) { - switch (button) { - case 0: save(); break; - case 1: useDefault(); break; - } - } + function onhide() { document.body.style.minWidth = ''; document.body.style.minHeight = ''; colorpicker.hide(); @@ -201,8 +195,8 @@ function configDialog(style) { } function buildConfigForm() { - let resetter = $create('span.config-reset-icon', [ - $create('a', {href:'#', dataset: {allowEnter: true}}, [ + let resetter = + $create('a.config-reset-icon', {href: '#'}, [ $create('SVG:svg.svg-icon', {viewBox: '0 0 20 20'}, [ $create('SVG:title', t('genericResetLabel')), $create('SVG:polygon', { @@ -210,8 +204,7 @@ function configDialog(style) { '5.5,16.2 10,11.7 14.5,16.2 16.2,14.5 11.7,10', }) ]) - ]) - ]); + ]); for (const va of vars) { let children; switch (va.type) { @@ -221,7 +214,6 @@ function configDialog(style) { va.input = $create('a.color-swatch', { va, href: '#', - dataset: {allowEnter: true}, onclick: showColorpicker }), ]), @@ -272,8 +264,8 @@ function configDialog(style) { } resetter = resetter.cloneNode(true); - $('a', resetter).va = va; - $('a', resetter).onclick = resetOnClick; + resetter.va = va; + resetter.onclick = resetOnClick; elements.push( $create(`label.config-${va.type}`, [ @@ -281,6 +273,8 @@ function configDialog(style) { ...children, resetter, ])); + + va.savedValue = va.value; } } @@ -319,22 +313,18 @@ function configDialog(style) { const el = va.input.closest('label'); el.classList.toggle('dirty', Boolean(va.dirty)); el.classList.toggle('nondefault', !isDefault(va)); + $('.config-reset-icon', el).disabled = isDefault(va); } function resetOnClick(event) { - if ( - event.type === 'click' || - (event.keyCode || event.which) === 13 - ) { - event.preventDefault(); - event.stopPropagation(); - this.va.value = null; - renderValues([this.va]); - onchange({target: this.va.input}); - } + event.preventDefault(); + this.va.value = null; + renderValues([this.va]); + onchange({target: this.va.input}); } - function showColorpicker() { + function showColorpicker(event) { + event.preventDefault(); window.removeEventListener('keydown', messageBox.listeners.key, true); const box = $('#message-box-contents'); colorpicker.show({ diff --git a/manage/filters.js b/manage/filters.js index 21ceaeb6..fb12d179 100644 --- a/manage/filters.js +++ b/manage/filters.js @@ -353,7 +353,9 @@ function showFiltersStats() { debounce(showFiltersStats, 100); return; } - $('#filters summary').classList.toggle('active', filtersSelector.hide !== ''); + const active = filtersSelector.hide !== ''; + $('#filters summary').classList.toggle('active', active); + $('#reset-filters').disabled = !active; const numTotal = BG.cachedStyles.list.length; const numHidden = installed.getElementsByClassName('entry hidden').length; const numShown = Math.min(numTotal - numHidden, installed.children.length); diff --git a/manage/manage.css b/manage/manage.css index 8fe28b3c..18209b7c 100644 --- a/manage/manage.css +++ b/manage/manage.css @@ -145,12 +145,11 @@ select { } .svg-icon.config { - width: 16px; - height: 16px; + transform: scale(.8); } .homepage { - margin-left: 0.1em; + margin-left: 0.25em; margin-right: 0.1em; } @@ -160,7 +159,6 @@ select { .homepage .svg-icon { margin-top: 0; - margin-left: .5ex; } .style-name { @@ -190,6 +188,7 @@ select { .actions > * { margin-bottom: .25rem; + display: inline-block; } .actions > *:not(:last-child) { @@ -450,11 +449,9 @@ select { color: hsla(180, 100%, 15%, 1); } -/* align delete button if no homepage link */ -.newUI a.homepage.disabled { - /* margin-left: 0.5ex + 20px svg width + margin-right: 8px */ - width: calc(0.5ex + 28px); - display: inline-block; +.newUI .homepage:not([href=""]) { + position: absolute; + margin-left: -28px; } .newUI .actions { @@ -464,30 +461,9 @@ select { } .newUI .actions > * { - margin: 0; -} - -.newUI .actions .svg-icon { - margin-right: 8px; -} - -.newUI .style-name-link:focus, -.newUI .actions a:focus, -.newUI a.expander { - outline: none; - text-decoration: none; -} - -.newUI .style-name-link, -.newUI .actions a svg, -.newUI a.expander { - border-bottom: 1px dashed transparent; -} - -.newUI .style-name-link:focus, -.newUI .actions a:focus svg, -.newUI a.expander:focus { - border-bottom: 1px dashed #AAA; + margin: 0 8px 0 0; + width: 20px; + height: 20px; } .newUI .updater-icons > * { @@ -509,7 +485,7 @@ select { .newUI .checking-update .check-update { opacity: 0; - display: inline; + display: inline-block; pointer-events: none; } @@ -517,7 +493,7 @@ select { .newUI .no-update:not(.update-problem):not(.update-done) .up-to-date, .newUI .no-update.update-problem .check-update, .newUI .update-done .updated { - display: inline; + display: inline-block; } .newUI .up-to-date svg, @@ -623,7 +599,7 @@ select { } .newUI .has-favicons .applies-to .expander { - padding-left: 20px; + margin-left: 20px; } .newUI .target:hover { @@ -682,8 +658,7 @@ select { margin-right: .5em; } -#newUIoptions [data-toggle-on-click], -#newUIoptions a[data-toggle-on-click] svg { +#newUIoptions [data-toggle-on-click] svg { transform: rotate(-90deg); cursor: pointer; right: -16px; @@ -691,8 +666,7 @@ select { pointer-events: auto; } -#newUIoptions [data-toggle-on-click][open], -#newUIoptions a[data-toggle-on-click][open] svg { +#newUIoptions [data-toggle-on-click][open] svg { transform: none; } @@ -720,7 +694,7 @@ input[id^="manage.newUI"] { /* Check update button for things that can */ .updatable .check-update { - display: inline; + display: inline-block; } /* Update check in progress */ @@ -730,7 +704,7 @@ input[id^="manage.newUI"] { /* Updates available */ .can-update .update { - display: inline; + display: inline-block; } .can-update[data-details$="locally edited"] button.update:after { @@ -827,6 +801,10 @@ input[id^="manage.newUI"] { #reset-filters { position: absolute; margin-top: 2px; + display: inline-block; +} + +#reset-filters svg { fill: hsla(180, 50%, 27%, .5); width: 24px; /* widen the click area a bit */ height: 20px; @@ -834,7 +812,7 @@ input[id^="manage.newUI"] { box-sizing: border-box; } -#reset-filters:hover { +#reset-filters:hover svg { fill: hsla(180, 50%, 27%, 1); } @@ -862,7 +840,7 @@ input[id^="manage.newUI"] { border-radius: 0.25rem; } -#search-wrapper #search-help { +#search-help { margin: 4px 0 0 8px; } diff --git a/manage/manage.js b/manage/manage.js index 669bc726..71c31798 100644 --- a/manage/manage.js +++ b/manage/manage.js @@ -191,9 +191,6 @@ function createStyleElement({style, name}) { if (style.url) { $('.homepage', entry).appendChild(parts.homepageIcon.cloneNode(true)); - } else { - $('.homepage', entry).removeAttribute('href'); - $('.homepage', entry).classList.add('disabled'); } if (style.updateUrl && newUI.enabled) { $('.actions', entry).appendChild(template.updaterIcons.cloneNode(true)); @@ -395,6 +392,7 @@ Object.assign(handleEvent, { }, config(event, {styleMeta}) { + event.preventDefault() configDialog(styleMeta); }, }); diff --git a/manage/updater-ui.js b/manage/updater-ui.js index b6089271..8e58e627 100644 --- a/manage/updater-ui.js +++ b/manage/updater-ui.js @@ -180,15 +180,17 @@ function showUpdateHistory(event) { messageBox({ title: t('updateCheckHistory'), contents: log, + blockScroll: true, buttons: [ t('confirmOK'), logText && {textContent: t('confirmDelete'), onclick: deleteHistory}, ], onshow: logText && (() => { scroller = $('#message-box-contents'); - scroller.setAttribute('tabindex', 0); - scroller.focus(); + scroller.tabIndex = 0; + setTimeout(() => scroller.focus()); scrollToBottom(); + $('#message-box-buttons button').insertAdjacentElement('afterend', // TODO: add a global class for our labels // TODO: add a