From a4275fe416f2bf8f0e551f9f18b564bc626f0420 Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Fri, 1 May 2026 09:43:34 -0500 Subject: [PATCH] feat(ui): add reusable scroll-to-top FAB across long-content pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a small floating button that appears once the user has scrolled past 400px of content and snaps the IonContent back to the top on tap. Implementation: - New ScrollToTopModule + ScrollToTopComponent at src/app/scroll-to-top/. Takes the parent's via @Input, subscribes to ionScroll, toggles visibility on threshold cross, unsubscribes on destroy. - dropped inside ion-content on every long-content page (21 pages: schedule-list, speakers, sponsors, job-listings, sprints, rooms, room-detail, sponsor-detail, session-detail, etc.). - sponsor-detail and session-detail also gained scrollEvents="true" so the component's inner subscription fires. conference-map and expo-hall-map are intentionally skipped — they own pinch-zoom interactions where an extra FAB at the same anchor point would conflict. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/app/pages/about-psf/about-psf.module.ts | 4 +- src/app/pages/about-psf/about-psf.page.html | 4 +- .../pages/about-pycon/about-pycon.module.ts | 4 +- .../pages/about-pycon/about-pycon.page.html | 4 +- src/app/pages/account/account.html | 4 +- src/app/pages/account/account.module.ts | 4 +- src/app/pages/coc/coc.module.ts | 4 +- src/app/pages/coc/coc.page.html | 4 +- src/app/pages/help/help.module.ts | 4 +- src/app/pages/help/help.page.html | 4 +- .../pages/job-listings/job-listings.module.ts | 4 +- .../pages/job-listings/job-listings.page.html | 4 +- .../keynote-speakers.module.ts | 3 +- .../keynote-speakers.page.html | 4 +- .../lightning-talks/lightning-talks.module.ts | 3 +- .../lightning-talks/lightning-talks.page.html | 4 +- src/app/pages/now/now.module.ts | 4 +- src/app/pages/now/now.page.html | 4 +- .../pages/room-detail/room-detail.module.ts | 3 +- .../pages/room-detail/room-detail.page.html | 4 +- src/app/pages/rooms/rooms.module.ts | 3 +- src/app/pages/rooms/rooms.page.html | 4 +- .../schedule-list/schedule-list.module.ts | 4 +- .../schedule-list/schedule-list.page.html | 4 +- src/app/pages/schedule/schedule.html | 4 +- src/app/pages/schedule/schedule.module.ts | 4 +- .../pages/session-detail/session-detail.html | 4 +- .../session-detail/session-detail.module.ts | 4 +- .../session-types/session-types.module.ts | 4 +- .../session-types/session-types.page.html | 4 +- .../pages/social-media/social-media.module.ts | 4 +- .../pages/social-media/social-media.page.html | 4 +- src/app/pages/speaker-list/speaker-list.html | 4 +- .../pages/speaker-list/speaker-list.module.ts | 4 +- .../pages/sponsor-detail/sponsor-detail.html | 4 +- .../sponsor-detail/sponsor-detail.module.ts | 2 + src/app/pages/sponsors/sponsors.module.ts | 4 +- src/app/pages/sponsors/sponsors.page.html | 4 +- src/app/pages/sprints/sprints.module.ts | 4 +- src/app/pages/sprints/sprints.page.html | 4 +- .../pages/venues-hours/venues-hours.module.ts | 4 +- .../pages/venues-hours/venues-hours.page.html | 4 +- src/app/pages/wifi/wifi.module.ts | 4 +- src/app/pages/wifi/wifi.page.html | 4 +- .../scroll-to-top.component.html | 5 +++ .../scroll-to-top.component.scss | 17 ++++++++ .../scroll-to-top/scroll-to-top.component.ts | 40 +++++++++++++++++++ src/app/scroll-to-top/scroll-to-top.module.ts | 12 ++++++ 48 files changed, 201 insertions(+), 43 deletions(-) create mode 100644 src/app/scroll-to-top/scroll-to-top.component.html create mode 100644 src/app/scroll-to-top/scroll-to-top.component.scss create mode 100644 src/app/scroll-to-top/scroll-to-top.component.ts create mode 100644 src/app/scroll-to-top/scroll-to-top.module.ts diff --git a/src/app/pages/about-psf/about-psf.module.ts b/src/app/pages/about-psf/about-psf.module.ts index ec2e6aa4..ec83b582 100644 --- a/src/app/pages/about-psf/about-psf.module.ts +++ b/src/app/pages/about-psf/about-psf.module.ts @@ -7,13 +7,15 @@ import { IonicModule } from '@ionic/angular'; import { AboutPsfPageRoutingModule } from './about-psf-routing.module'; import { AboutPsfPage } from './about-psf.page'; +import { ScrollToTopModule } from '../../scroll-to-top/scroll-to-top.module'; @NgModule({ imports: [ CommonModule, FormsModule, IonicModule, - AboutPsfPageRoutingModule + AboutPsfPageRoutingModule, + ScrollToTopModule ], declarations: [AboutPsfPage] }) diff --git a/src/app/pages/about-psf/about-psf.page.html b/src/app/pages/about-psf/about-psf.page.html index 9e0cf58b..a892d175 100644 --- a/src/app/pages/about-psf/about-psf.page.html +++ b/src/app/pages/about-psf/about-psf.page.html @@ -7,7 +7,7 @@ - +

Python Software Foundation

@@ -212,4 +212,6 @@

Python Software Foundation

+ + diff --git a/src/app/pages/about-pycon/about-pycon.module.ts b/src/app/pages/about-pycon/about-pycon.module.ts index 1f9ddef7..d5dfc872 100644 --- a/src/app/pages/about-pycon/about-pycon.module.ts +++ b/src/app/pages/about-pycon/about-pycon.module.ts @@ -7,13 +7,15 @@ import { IonicModule } from '@ionic/angular'; import { AboutPyconPageRoutingModule } from './about-pycon-routing.module'; import { AboutPyconPage } from './about-pycon.page'; +import { ScrollToTopModule } from '../../scroll-to-top/scroll-to-top.module'; @NgModule({ imports: [ CommonModule, FormsModule, IonicModule, - AboutPyconPageRoutingModule + AboutPyconPageRoutingModule, + ScrollToTopModule ], declarations: [AboutPyconPage] }) diff --git a/src/app/pages/about-pycon/about-pycon.page.html b/src/app/pages/about-pycon/about-pycon.page.html index 2c87bd87..7f68235d 100644 --- a/src/app/pages/about-pycon/about-pycon.page.html +++ b/src/app/pages/about-pycon/about-pycon.page.html @@ -7,7 +7,7 @@ - +

PyCon US 2026

@@ -55,4 +55,6 @@

PyCon US 2026

+ + diff --git a/src/app/pages/account/account.html b/src/app/pages/account/account.html index b803d94a..a67f00be 100644 --- a/src/app/pages/account/account.html +++ b/src/app/pages/account/account.html @@ -7,7 +7,7 @@ - +