1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-09 07:25:19 +02:00

feat: preserve scroll and scroll on connect, better responsive mobile settings menu

This commit is contained in:
Luan Estradioto 2025-05-21 21:26:13 -03:00
parent 34b3e4ae20
commit 8f1b685f4e
3 changed files with 88 additions and 1 deletions

View file

@ -0,0 +1,44 @@
import { Controller } from "@hotwired/stimulus"
/*
https://dev.to/konnorrogers/maintain-scroll-position-in-turbo-without-data-turbo-permanent-2b1i
modified to add support for horizontal scrolling
only requirement is that the element has an id
*/
export default class extends Controller {
static scrollPositions = {}
connect() {
this.preserveScrollBound = this.preserveScroll.bind(this)
this.restoreScrollBound = this.restoreScroll.bind(this)
window.addEventListener("turbo:before-cache", this.preserveScrollBound)
window.addEventListener("turbo:before-render", this.restoreScrollBound)
window.addEventListener("turbo:render", this.restoreScrollBound)
}
disconnect() {
window.removeEventListener("turbo:before-cache", this.preserveScrollBound)
window.removeEventListener("turbo:before-render", this.restoreScrollBound)
window.removeEventListener("turbo:render", this.restoreScrollBound)
}
preserveScroll() {
if (!this.element.id) return
this.constructor.scrollPositions[this.element.id] = {
top: this.element.scrollTop,
left: this.element.scrollLeft
}
}
restoreScroll(event) {
if (!this.element.id) return
if (this.constructor.scrollPositions[this.element.id]) {
this.element.scrollTop = this.constructor.scrollPositions[this.element.id].top
this.element.scrollLeft = this.constructor.scrollPositions[this.element.id].left
}
}
}

View file

@ -0,0 +1,43 @@
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static values = {
selector: { type: String, default: "[aria-current=\"page\"]" },
delay: { type: Number, default: 500 }
}
connect() {
setTimeout(() => {
this.scrollToActiveItem()
}, this.delayValue)
}
scrollToActiveItem() {
const activeItem = this.element?.querySelector(this.selectorValue)
console.log(activeItem)
if (!activeItem) return
const scrollContainer = this.element
const containerRect = scrollContainer.getBoundingClientRect()
const activeItemRect = activeItem.getBoundingClientRect()
const scrollPositionX = (activeItemRect.left + scrollContainer.scrollLeft) -
(containerRect.width / 2) +
(activeItemRect.width / 2)
const scrollPositionY = (activeItemRect.top + scrollContainer.scrollTop) -
(containerRect.height / 2) +
(activeItemRect.height / 2)
console.log(scrollPositionX, scrollPositionY)
// Smooth scroll to position
scrollContainer.scrollTo({
top: Math.max(0, scrollPositionY),
left: Math.max(0, scrollPositionX),
behavior: 'smooth'
})
}
}

View file

@ -67,7 +67,7 @@ nav_sections = [
<% end %> <% end %>
</section> </section>
</nav> </nav>
<nav class="space-y-4 overflow-y-auto md:hidden" id="mobile-settings-nav"> <nav class="space-y-4 overflow-y-auto md:hidden" id="mobile-settings-nav" data-controller="preserve-scroll scroll-on-connect">
<ul class="flex space-y-1"> <ul class="flex space-y-1">
<li> <li>
<%= render LinkComponent.new( <%= render LinkComponent.new(