From bd6505f72b61a0f26b22ef21246e5497a7541f72 Mon Sep 17 00:00:00 2001 From: Marcus Date: Sat, 6 Jul 2024 16:28:05 -0700 Subject: [PATCH 1/4] implement `appendWithoutOverflow` --- src/features/quick_reblog.css | 60 ++++++++++------------------------- src/features/quick_reblog.js | 7 ++-- src/features/quick_tags.css | 33 +++++++------------ src/features/quick_tags.js | 14 ++------ src/utils/interface.js | 32 +++++++++++++++++++ 5 files changed, 66 insertions(+), 80 deletions(-) diff --git a/src/features/quick_reblog.css b/src/features/quick_reblog.css index 5e0c9df0b..5b0713c41 100644 --- a/src/features/quick_reblog.css +++ b/src/features/quick_reblog.css @@ -1,3 +1,9 @@ +/* debug */ +[data-temp-highlight] { + outline: 4px dashed red; + outline-offset: -2px; +} + #quick-reblog { position: absolute; z-index: 97; @@ -20,56 +26,22 @@ display: none !important; } -@media (max-width: 650px) { - #quick-reblog { - top: 50%; - right: 100%; - transform: translateY(-50%); - } +#quick-reblog { + --icon-spacing: 12px; } - -@media (min-width: 650px) { +@media (max-width: 990px) { #quick-reblog { - transform: translateX(50%); - } - - #quick-reblog.above { - bottom: 100%; - right: 50%; - } - - #quick-reblog.below { - top: 100%; - right: 50%; - } -} - -@media (min-width: 990px) { - #quick-reblog.above { - transform: translate(50%, -12px) - } - - #quick-reblog.below { - transform: translate(50%, 12px); + --icon-spacing: 0px; } } -@media (max-width: 990px) { - [role="dialog"] #quick-reblog { - top: 50%; - bottom: unset; - right: 100%; - transform: translateY(-50%); - } +#quick-reblog.below { + inset: 100% 50% auto auto; + transform: translate(calc(50% + var(--horizontal-offset, 0%)), var(--icon-spacing)); } - -@media (min-width: 990px) and (max-width: 1145px) { - [role="dialog"] #quick-reblog { - top: 50%; - bottom: unset; - right: 100%; - transform: translate(-20px, -50%); - } +#quick-reblog.above { + inset: auto 50% 100% auto; + transform: translate(calc(50% + var(--horizontal-offset, 0%)), calc(0px - var(--icon-spacing))); } div:first-child + span + #quick-reblog, diff --git a/src/features/quick_reblog.js b/src/features/quick_reblog.js index e52fc9082..af86a5446 100644 --- a/src/features/quick_reblog.js +++ b/src/features/quick_reblog.js @@ -1,7 +1,7 @@ import { sha256 } from '../utils/crypto.js'; import { timelineObject } from '../utils/react_props.js'; import { apiFetch } from '../utils/tumblr_helpers.js'; -import { postSelector, filterPostElements, postType } from '../utils/interface.js'; +import { postSelector, filterPostElements, postType, appendWithoutOverflow } from '../utils/interface.js'; import { userBlogs } from '../utils/user.js'; import { getPreferences } from '../utils/preferences.js'; import { onNewPosts } from '../utils/mutations.js'; @@ -9,6 +9,7 @@ import { notify } from '../utils/notifications.js'; import { translate } from '../utils/language_data.js'; import { dom } from '../utils/dom.js'; import { showErrorModal } from '../utils/modals.js'; +import { keyToCss } from '../utils/css_map.js'; const popupElement = dom('div', { id: 'quick-reblog' }); const blogSelector = dom('select'); @@ -131,7 +132,7 @@ tagsInput.addEventListener('input', checkLength); const showPopupOnHover = ({ currentTarget }) => { clearTimeout(timeoutID); - currentTarget.closest('div').appendChild(popupElement); + appendWithoutOverflow(popupElement, currentTarget.closest(keyToCss('controlIcon')), popupPosition); popupElement.parentNode.addEventListener('mouseleave', removePopupOnLeave); const thisPost = currentTarget.closest(postSelector); @@ -326,8 +327,6 @@ export const main = async function () { alreadyRebloggedLimit } = await getPreferences('quick_reblog')); - popupElement.className = popupPosition; - blogSelector.replaceChildren( ...userBlogs.map(({ name, uuid }) => dom('option', { value: uuid }, null, [name])) ); diff --git a/src/features/quick_tags.css b/src/features/quick_tags.css index 6ce55c4ab..cf1deb990 100644 --- a/src/features/quick_tags.css +++ b/src/features/quick_tags.css @@ -1,3 +1,9 @@ +/* debug */ +[data-temp-highlight] { + outline: 4px dashed red; + outline-offset: -2px; +} + #quick-tags, #quick-tags-post-option { position: absolute; @@ -42,28 +48,13 @@ } } -@media (min-width: 650px) { - #quick-tags.below { - inset: 100% 50% auto auto; - transform: translate(50%, var(--icon-spacing)); - } - #quick-tags.above { - inset: auto 50% 100% auto; - transform: translate(50%, calc(0px - var(--icon-spacing))); - } +#quick-tags.below { + inset: 100% 50% auto auto; + transform: translate(calc(50% + var(--horizontal-offset, 0%)), var(--icon-spacing)); } - -@media (max-width: 650px) { - #quick-tags { - inset: 50% 100% auto auto; - transform: translate(calc(0px - var(--icon-spacing)), -50%); - } -} -@media (max-width: 1145px) { - [role="dialog"] #quick-tags { - inset: 50% 100% auto auto; - transform: translate(calc(0px - var(--icon-spacing)), -50%); - } +#quick-tags.above { + inset: auto 50% 100% auto; + transform: translate(calc(50% + var(--horizontal-offset, 0%)), calc(0px - var(--icon-spacing))); } #quick-tags:empty::before, diff --git a/src/features/quick_tags.js b/src/features/quick_tags.js index ec4f1f109..689c95ae1 100644 --- a/src/features/quick_tags.js +++ b/src/features/quick_tags.js @@ -1,7 +1,7 @@ import { cloneControlButton, createControlButtonTemplate } from '../utils/control_buttons.js'; import { keyToCss } from '../utils/css_map.js'; import { dom } from '../utils/dom.js'; -import { filterPostElements, getTimelineItemWrapper, postSelector } from '../utils/interface.js'; +import { appendWithoutOverflow, filterPostElements, getTimelineItemWrapper, postSelector } from '../utils/interface.js'; import { megaEdit } from '../utils/mega_editor.js'; import { modalCancelButton, modalCompleteButton, showErrorModal, showModal } from '../utils/modals.js'; import { onNewPosts, pageModifications } from '../utils/mutations.js'; @@ -115,14 +115,6 @@ export const onStorageChanged = async function (changes, areaName) { } }; -const appendWithoutViewportOverflow = (element, target) => { - element.className = 'below'; - target.appendChild(element); - if (element.getBoundingClientRect().bottom > document.documentElement.clientHeight) { - element.className = 'above'; - } -}; - const togglePopupDisplay = async function ({ target, currentTarget: controlButton }) { if (target === popupElement || popupElement.contains(target)) { return; } @@ -131,7 +123,7 @@ const togglePopupDisplay = async function ({ target, currentTarget: controlButto if (buttonContainer.contains(popupElement)) { buttonContainer.removeChild(popupElement); } else { - appendWithoutViewportOverflow(popupElement, buttonContainer); + appendWithoutOverflow(popupElement, buttonContainer); } }; @@ -141,7 +133,7 @@ const togglePostOptionPopupDisplay = async function ({ target, currentTarget }) if (currentTarget.contains(postOptionPopupElement)) { currentTarget.removeChild(postOptionPopupElement); } else { - appendWithoutViewportOverflow(postOptionPopupElement, currentTarget); + appendWithoutOverflow(postOptionPopupElement, currentTarget); } }; diff --git a/src/utils/interface.js b/src/utils/interface.js index 3eb252ca5..608094af5 100644 --- a/src/utils/interface.js +++ b/src/utils/interface.js @@ -115,3 +115,35 @@ export const postType = ({ trail = [], content = [], layout = [] }) => { else if (content.some(({ type }) => type === 'link')) return 'link'; else return 'text'; }; + +const closestWithOverflow = element => { + const parent = element.parentElement; + if (!parent) return element; + if (getComputedStyle(parent).overflowX !== 'visible') return parent; + return closestWithOverflow(parent); +}; + +export const appendWithoutOverflow = (element, target, defaultPosition = 'below') => { + element.className = defaultPosition; + element.style.removeProperty('--horizontal-offset'); + + target.appendChild(element); + + const preventOverflowTarget = closestWithOverflow(target); + + // debug + preventOverflowTarget.dataset.tempHighlight = ''; + setTimeout(() => { + delete preventOverflowTarget.dataset.tempHighlight; + }, 1000); + + const preventOverflowTargetRect = preventOverflowTarget.getBoundingClientRect(); + const elementRect = element.getBoundingClientRect(); + + if (elementRect.bottom > document.documentElement.clientHeight) { + element.className = 'above'; + } + if (elementRect.right > preventOverflowTargetRect.right - 15) { + element.style.setProperty('--horizontal-offset', `${preventOverflowTargetRect.right - 15 - elementRect.right}px`); + } +}; From 7256820a43dd69b3ce17469f89ba83b5f7a0d986 Mon Sep 17 00:00:00 2001 From: Marcus Date: Sat, 6 Jul 2024 16:49:02 -0700 Subject: [PATCH 2/4] remove debug code --- src/features/quick_reblog.css | 6 ------ src/features/quick_tags.css | 6 ------ src/utils/interface.js | 7 ------- 3 files changed, 19 deletions(-) diff --git a/src/features/quick_reblog.css b/src/features/quick_reblog.css index 5b0713c41..2db158ca8 100644 --- a/src/features/quick_reblog.css +++ b/src/features/quick_reblog.css @@ -1,9 +1,3 @@ -/* debug */ -[data-temp-highlight] { - outline: 4px dashed red; - outline-offset: -2px; -} - #quick-reblog { position: absolute; z-index: 97; diff --git a/src/features/quick_tags.css b/src/features/quick_tags.css index cf1deb990..73007cb21 100644 --- a/src/features/quick_tags.css +++ b/src/features/quick_tags.css @@ -1,9 +1,3 @@ -/* debug */ -[data-temp-highlight] { - outline: 4px dashed red; - outline-offset: -2px; -} - #quick-tags, #quick-tags-post-option { position: absolute; diff --git a/src/utils/interface.js b/src/utils/interface.js index 608094af5..936ffb53c 100644 --- a/src/utils/interface.js +++ b/src/utils/interface.js @@ -130,13 +130,6 @@ export const appendWithoutOverflow = (element, target, defaultPosition = 'below' target.appendChild(element); const preventOverflowTarget = closestWithOverflow(target); - - // debug - preventOverflowTarget.dataset.tempHighlight = ''; - setTimeout(() => { - delete preventOverflowTarget.dataset.tempHighlight; - }, 1000); - const preventOverflowTargetRect = preventOverflowTarget.getBoundingClientRect(); const elementRect = element.getBoundingClientRect(); From 1d987e67641428bcc13a03add2be9086056bbc80 Mon Sep 17 00:00:00 2001 From: Marcus Date: Sun, 7 Jul 2024 10:20:09 -0700 Subject: [PATCH 3/4] rename `closestWithOverflow` Co-Authored-By: April Sylph <28949509+AprilSylph@users.noreply.github.com> --- src/utils/interface.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/interface.js b/src/utils/interface.js index 936ffb53c..cf4486692 100644 --- a/src/utils/interface.js +++ b/src/utils/interface.js @@ -116,11 +116,11 @@ export const postType = ({ trail = [], content = [], layout = [] }) => { else return 'text'; }; -const closestWithOverflow = element => { +const getClosestWithOverflow = element => { const parent = element.parentElement; if (!parent) return element; if (getComputedStyle(parent).overflowX !== 'visible') return parent; - return closestWithOverflow(parent); + return getClosestWithOverflow(parent); }; export const appendWithoutOverflow = (element, target, defaultPosition = 'below') => { @@ -129,7 +129,7 @@ export const appendWithoutOverflow = (element, target, defaultPosition = 'below' target.appendChild(element); - const preventOverflowTarget = closestWithOverflow(target); + const preventOverflowTarget = getClosestWithOverflow(target); const preventOverflowTargetRect = preventOverflowTarget.getBoundingClientRect(); const elementRect = element.getBoundingClientRect(); From 31b20b13839dec80293ef99ecee1ae97aa68c1dd Mon Sep 17 00:00:00 2001 From: Marcus Date: Sun, 7 Jul 2024 10:21:29 -0700 Subject: [PATCH 4/4] adjust conditional styling Co-Authored-By: April Sylph <28949509+AprilSylph@users.noreply.github.com> --- src/utils/interface.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/utils/interface.js b/src/utils/interface.js index cf4486692..86b67680b 100644 --- a/src/utils/interface.js +++ b/src/utils/interface.js @@ -118,9 +118,13 @@ export const postType = ({ trail = [], content = [], layout = [] }) => { const getClosestWithOverflow = element => { const parent = element.parentElement; - if (!parent) return element; - if (getComputedStyle(parent).overflowX !== 'visible') return parent; - return getClosestWithOverflow(parent); + if (!parent) { + return element; + } else if (getComputedStyle(parent).overflowX !== 'visible') { + return parent; + } else { + return getClosestWithOverflow(parent); + } }; export const appendWithoutOverflow = (element, target, defaultPosition = 'below') => {