From d7a33fe4eb2571d9e53986f830fd2f4b9e777312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grabowski?= Date: Tue, 28 Jan 2025 14:20:53 +0100 Subject: [PATCH] fix scrollbar issues --- .../public/js/scripts/admin.input.text.js | 26 +++++++++++++++++++ src/bundle/Resources/public/scss/_inputs.scss | 17 +++++++++--- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/bundle/Resources/public/js/scripts/admin.input.text.js b/src/bundle/Resources/public/js/scripts/admin.input.text.js index e9480e96b4..6a5dc8ecd2 100644 --- a/src/bundle/Resources/public/js/scripts/admin.input.text.js +++ b/src/bundle/Resources/public/js/scripts/admin.input.text.js @@ -1,5 +1,6 @@ (function (global, doc) { const INPUT_PADDING = 12; + const TEXTAREA_SCROLLBAR_PADDING = 6; const togglePasswordVisibility = (event) => { const passwordTogglerBtn = event.currentTarget; const passwordShowIcon = passwordTogglerBtn.querySelector('.ibexa-input-text-wrapper__password-show'); @@ -40,6 +41,7 @@ inputClearBtns.forEach((clearBtn) => clearBtn.addEventListener('click', clearText, false)); passwordTogglerBtns.forEach((passwordTogglerBtn) => passwordTogglerBtn.addEventListener('click', togglePasswordVisibility, false)); recalculateStyling(); + attachListenersToMultilineInputs(); }; const recalculateInputStyling = (inputActionsContainer) => { const textWrapper = inputActionsContainer.closest('.ibexa-input-text-wrapper'); @@ -66,6 +68,30 @@ recalculateInputStyling(inputActionsContainer); }); }; + const attachListenersToMultilineInputs = () => { + const multilineInputWrappers = doc.querySelectorAll('.ibexa-input-text-wrapper.ibexa-input-text-wrapper--multiline'); + + multilineInputWrappers.forEach((multilineInputWrapper) => { + const textareaComponent = multilineInputWrapper.querySelector('.ibexa-input--textarea'); + + const textareaComponentObserver = new ResizeObserver(() => { + toggleScrollbarStyles(multilineInputWrapper); + }); + + textareaComponentObserver.observe(textareaComponent); + toggleScrollbarStyles(multilineInputWrapper); + }); + }; + const toggleScrollbarStyles = (multilineInputWrapper) => { + const textareaComponent = multilineInputWrapper.querySelector('textarea'); + const { scrollHeight, clientHeight, offsetWidth, clientWidth } = textareaComponent; + const { overflowY } = global.getComputedStyle(textareaComponent); + const hasScrollbar = overflowY !== 'hidden' && scrollHeight > clientHeight; + const scrollbarWidth = offsetWidth - clientWidth; + + multilineInputWrapper.classList.toggle('ibexa-input-text-wrapper--scrollbar-visible', hasScrollbar); + multilineInputWrapper.style.setProperty('--scrollbar-width', `${scrollbarWidth + TEXTAREA_SCROLLBAR_PADDING}px`); + }; doc.body.addEventListener('ibexa-inputs:added', attachListenersToAllInputs, false); doc.body.addEventListener('ibexa-inputs:recalculate-styling', recalculateStyling, false); diff --git a/src/bundle/Resources/public/scss/_inputs.scss b/src/bundle/Resources/public/scss/_inputs.scss index 45e3ecb12f..92b8e9cf26 100644 --- a/src/bundle/Resources/public/scss/_inputs.scss +++ b/src/bundle/Resources/public/scss/_inputs.scss @@ -111,6 +111,10 @@ box-shadow 0s; // Chrome does not render box-shadow properly with transition height: calculateRem(120px); padding: calculateRem(10px) calculateRem(16px); + + &.form-control { + min-height: calculateRem(48px); + } } &--checkbox, @@ -406,7 +410,7 @@ top: 50%; right: calculateRem(8px); transform: translate(0, -50%); - height: calculateRem(24px); + min-height: calculateRem(24px); padding: 0; fill: var(--ibexa-btn-icon-fill-color, #{$ibexa-color-dark}); z-index: 1; @@ -455,11 +459,18 @@ &--multiline { .ibexa-input-text-wrapper { &__actions { - right: calculateRem(24px); - top: calculateRem(16px); + top: calculateRem(8px); transform: none; } } + + &.ibexa-input-text-wrapper--scrollbar-visible { + .ibexa-input-text-wrapper { + &__actions { + right: var(--scrollbar-width, 0); + } + } + } } &:hover {