diff --git a/keepassxc-browser/content/autocomplete.js b/keepassxc-browser/content/autocomplete.js index b14ff13..e7c26ef 100644 --- a/keepassxc-browser/content/autocomplete.js +++ b/keepassxc-browser/content/autocomplete.js @@ -100,7 +100,9 @@ class Autocomplete { styleSheet.addEventListener('load', () => (this.wrapper.style.display = 'block')); this.container = kpxcUI.createElement('div', 'kpxcAutocomplete-container', { id: 'kpxcAutocomplete-container', + popover: 'manual', }); + this.container.style.margin = 0; // Apply compact mode class if (kpxc.settings.useCompactMode) { @@ -128,6 +130,7 @@ class Autocomplete { this.updateList(); this.container.classList.add('kpxcAutocomplete-container--visible'); + this.container.showPopover({ source: inputField }); this.updatePosition(); } @@ -235,6 +238,7 @@ class Autocomplete { } this.container.classList.remove('kpxcAutocomplete-container--visible'); + this.container.hidePopover(); } getAllItems() { @@ -338,7 +342,7 @@ class Autocomplete { // Get body zoom radio const zoom = kpxcUI.bodyStyle.zoom || 1; - + // Calculate Y offset if menu does not fit to the bottom of the screen -> show it at the top of the input field const menuRect = this.container.getBoundingClientRect(); const totalHeight = menuRect.height + rect.height; diff --git a/keepassxc-browser/content/fields.js b/keepassxc-browser/content/fields.js index 8920a1a..69dbafd 100644 --- a/keepassxc-browser/content/fields.js +++ b/keepassxc-browser/content/fields.js @@ -433,7 +433,7 @@ kpxcFields.isSearchField = function(target) { // :popover-open selector is supported only with Firefox >= 125 and Chrome >= 114 kpxcFields.discoverOverlays = function() { - try { + try { kpxcFields.overlays = document.querySelectorAll(':popover-open, [popover]'); } catch (e) { // Ignore SyntaxError (e.g., unsupported selector) diff --git a/keepassxc-browser/content/pwgen.js b/keepassxc-browser/content/pwgen.js index c9a3bf5..6acf32a 100644 --- a/keepassxc-browser/content/pwgen.js +++ b/keepassxc-browser/content/pwgen.js @@ -50,18 +50,17 @@ PasswordIcon.prototype.initField = function(field) { PasswordIcon.prototype.createIcon = function(field) { const className = (isFirefox() ? 'key-moz' : 'key'); - const size = (field.offsetHeight > 28) ? 24 : 16; - const offset = kpxcUI.calculateIconOffset(field, size); + const size = this.calculateIconSize(field); const icon = kpxcUI.createElement('div', 'kpxc kpxc-pwgen-icon ' + className, { 'title': tr('passwordGeneratorGenerateText'), 'size': size, - 'offset': offset, - 'kpxc-pwgen-field-id': field.getAttribute('data-kpxc-id') // Needed? + 'kpxc-pwgen-field-id': field.getAttribute('data-kpxc-id'), + 'popover': 'manual' }); - icon.style.zIndex = '10000000'; + icon.style.margin = 0; icon.style.width = Pixels(size); icon.style.height = Pixels(size); @@ -75,7 +74,7 @@ PasswordIcon.prototype.createIcon = function(field) { } if (e.shiftKey) { - icon.style.display = 'none'; + icon.hidePopover(); return; } @@ -89,6 +88,7 @@ PasswordIcon.prototype.createIcon = function(field) { kpxcUI.setIconPosition(icon, field, this.rtl); this.icon = icon; this.createWrapper('css/pwgen.css'); + icon.showPopover(); }; diff --git a/keepassxc-browser/content/totp-field.js b/keepassxc-browser/content/totp-field.js index f80cd06..8f1763a 100644 --- a/keepassxc-browser/content/totp-field.js +++ b/keepassxc-browser/content/totp-field.js @@ -140,18 +140,15 @@ TOTPFieldIcon.prototype.initField = async function(field, segmented) { TOTPFieldIcon.prototype.createIcon = function(field, segmented = false) { const className = (isFirefox() ? 'moz' : 'default'); - - // Size the icon dynamically, but not greater than 24 or smaller than 14 - const size = Math.max(Math.min(24, field.offsetHeight - 4), 14); - const offset = kpxcUI.calculateIconOffset(field, size); + const size = this.calculateIconSize(field); const icon = kpxcUI.createElement('div', 'kpxc kpxc-totp-icon ' + className, { 'title': tr('totpFieldText'), 'size': size, - 'offset': offset + 'popover': 'manual' }); - icon.style.zIndex = '10000000'; + icon.style.margin = 0; icon.style.width = Pixels(size); icon.style.height = Pixels(size); @@ -167,7 +164,7 @@ TOTPFieldIcon.prototype.createIcon = function(field, segmented = false) { } if (e.shiftKey) { - icon.style.display = 'none'; + icon.hidePopover(); return; } @@ -182,4 +179,5 @@ TOTPFieldIcon.prototype.createIcon = function(field, segmented = false) { kpxcUI.setIconPosition(icon, field, this.rtl, segmented); this.icon = icon; this.createWrapper('css/totp.css'); + icon.showPopover(); }; diff --git a/keepassxc-browser/content/ui.js b/keepassxc-browser/content/ui.js index 137e3bc..165e78c 100644 --- a/keepassxc-browser/content/ui.js +++ b/keepassxc-browser/content/ui.js @@ -7,6 +7,9 @@ const MIN_INPUT_FIELD_OFFSET_WIDTH = 60; const MIN_OPACITY = 0.7; const MAX_OPACITY = 1; +const MIN_ICON_SIZE = 14; +const MAX_ICON_SIZE = 24; + const BLUE_BUTTON = 'kpxc-button kpxc-blue-button'; const GREEN_BUTTON = 'kpxc-button kpxc-green-button'; const ORANGE_BUTTON = 'kpxc-button kpxc-orange-button'; @@ -52,6 +55,11 @@ class Icon { } } + // Size the icon dynamically, but not greater than 24 or smaller than 14 + calculateIconSize(field) { + return Math.max(Math.min(MAX_ICON_SIZE, field.offsetHeight - 4), MIN_ICON_SIZE); + } + // Creates a wrapper div that has the icon in Shadow DOM createWrapper(styleSheetFilename) { const styleSheet = createStylesheet(styleSheetFilename); diff --git a/keepassxc-browser/content/username-field.js b/keepassxc-browser/content/username-field.js index 6f3afb1..8f1c531 100644 --- a/keepassxc-browser/content/username-field.js +++ b/keepassxc-browser/content/username-field.js @@ -68,9 +68,7 @@ UsernameFieldIcon.prototype.initField = function(field) { UsernameFieldIcon.prototype.createIcon = function(field) { const className = getIconClassName(this.databaseState); - - // Size the icon dynamically, but not greater than 24 or smaller than 14 - const size = Math.max(Math.min(24, field.offsetHeight - 4), 14); + const size = this.calculateIconSize(field); // Don't create the icon if the input field is too small if (field.offsetWidth < (size * 1.5) || field.offsetHeight < size) { @@ -78,16 +76,14 @@ UsernameFieldIcon.prototype.createIcon = function(field) { return; } - const offset = kpxcUI.calculateIconOffset(field, size); - const icon = kpxcUI.createElement('div', 'kpxc kpxc-username-icon ' + className, { 'title': getIconText(this.databaseState), 'size': size, - 'offset': offset, - 'kpxc-pwgen-field-id': field.getAttribute('data-kpxc-id') + 'kpxc-pwgen-field-id': field.getAttribute('data-kpxc-id'), + 'popover': 'manual' }); - icon.style.zIndex = '10000000'; + icon.style.margin = 0; icon.style.width = Pixels(size); icon.style.height = Pixels(size); @@ -97,7 +93,7 @@ UsernameFieldIcon.prototype.createIcon = function(field) { } if (e.shiftKey) { - icon.style.display = 'none'; + icon.hidePopover(); return; } @@ -111,6 +107,7 @@ UsernameFieldIcon.prototype.createIcon = function(field) { kpxcUI.setIconPosition(icon, field, this.rtl); this.icon = icon; this.createWrapper('css/username.css'); + icon.showPopover(); }; const iconClicked = async function(field, icon) { diff --git a/keepassxc-browser/css/pwgen.css b/keepassxc-browser/css/pwgen.css index 64b574d..4368d25 100644 --- a/keepassxc-browser/css/pwgen.css +++ b/keepassxc-browser/css/pwgen.css @@ -1,5 +1,7 @@ .kpxc-pwgen-icon { + border: 0; cursor: pointer; + padding: 0 !important; position: absolute; } diff --git a/keepassxc-browser/css/totp.css b/keepassxc-browser/css/totp.css index 8281132..a34ed7c 100644 --- a/keepassxc-browser/css/totp.css +++ b/keepassxc-browser/css/totp.css @@ -1,6 +1,8 @@ .kpxc-totp-icon { - position: absolute; + border: 0; cursor: pointer; + padding: 0 !important; + position: absolute; } .kpxc-totp-icon.default { diff --git a/keepassxc-browser/css/username.css b/keepassxc-browser/css/username.css index 6b2e32a..42d438b 100644 --- a/keepassxc-browser/css/username.css +++ b/keepassxc-browser/css/username.css @@ -1,6 +1,8 @@ .kpxc-username-icon { - position: absolute; + border: 0; cursor: pointer; + padding: 0 !important; + position: absolute; } .kpxc-username-icon.disconnected {