Skip to content

feat: Add a new timetable implementation behind a feature flag - #3366

Merged
joshlarson merged 15 commits into
mainfrom
jdl/feat/new-timetable
Jul 29, 2026
Merged

feat: Add a new timetable implementation behind a feature flag#3366
joshlarson merged 15 commits into
mainfrom
jdl/feat/new-timetable

Conversation

@joshlarson

@joshlarson joshlarson commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Scope

One of the blockers to the new Harbor Loop ferry layout (which puts both timetables on the same page) is that the original timetable implementation has controls that assume that there's only one timetable on the page (if there are multiple, then the Earlier Boats/Later Boats buttons cause all timetables to scroll). I spent some time digging through the existing Javascript code, and decided to try my hand at rebuilding some of it in a more "Phoenix-forward" way, using Phoenix hooks, and relying more on tailwind, rather than having styling attached to parts of the timetable on load. At the time, I figured that would be easier than trying to fiddle with the existing JS code / timetable DOM and trying to guess what each bit was doing.

This was the result.

Asana Ticket: ⛴️ Tie "Earlier Trips"/"Later Trips" controls directly to the timetable component

Implementation

  • This PR adds a new feature flag: new_timetables, and uses it to decide what timetable logic to run.
    • When the flag is set to true, then it uses the new timetable logic for all timetables (this is obviously not production-ready, since the new timetable code lacks features that exist on CR timetables, and produces a slightly wrong timetable for more complicated ferry routes like the Hingham/Hull, but it's useful for comparing).
    • When the flag is false, then we continue as we previously did, using the new timetable backend logic only for the Quincy, Winthrop, and Harbor Loop ferry routes, and using the old timetable components for all routes.
  • The old timetable relies on a few Javascript files to work.
    • scroll-to.js: Used to make the timetables scroll to the right trip automatically on page-load.
      • Unchanged.
    • timetable-scroll.js: This is the code that runs when the Earlier Boats/Later Boats buttons are clicked.
      • Transplanted to a Phoenix hook.
    • timetable-stick.js: This is what causes the trip-name headers to look like they stick to the top of the screen on CR timetables.
      • Unchanged for now (this feature doesn't work on the new timetables yet, and isn't necessary for ferry timetables); will likely be transplanted to a Phoenix hook when the time comes.
    • timetable-style.js: This does a bunch of things, including setting some of the styling that makes the stop header column sticky.
      • Mostly replaced with Tailwind/CSS. The rest will likely be transplanted to a Phoenix hook.

Screenshots

Screenshot 2026-07-24 at 6 47 14 PM

☝️ is what the new timetable looks like (with a little disclaimer banner that indicates the new-ness of the new timetable).

This timetable should mostly look the same as the existing one, but it does resolve a few visual quirks. The screenshots below are from the old timetable, showing visual bugs that I wasn't able to produce on this branch:


👇 While we don't officially support a no-JS version of the site, the Javascript on this page sometimes takes long enough to load that this flashes on the screen... or even lingers (when I took this screenshot, it was like this for about ten seconds). 👇
Screenshot 2026-07-27 at 3 40 05 PM


👇 Some exciting quirks at certain screen widths where the shadow extends a bit too far up or down, making it look randomly darker in a few spots. 👇
Screenshot 2026-07-24 at 4 27 09 PM
Screenshot 2026-07-27 at 5 36 52 PM


👇 At some screen widths, the above-the-headers fake-table isn't aligned exactly with the table below, leading to an awkward jog 👇
Screenshot 2026-07-27 at 5 36 09 PM


👇 This wasn't a quirk exactly, but I thought it would be nice to keep the earlier/later train/boat buttons at narrow screen widths, so instead of fully hiding those buttons at narrow screen widths, I decided to just hide the words.

Screenshot 2026-07-27 at 5 44 17 PM

How to test

Go to the flags dashboard and set New timetables to true. Then navigate to any timetable page you're interested in, and have fun!

Notes

This is not a complete feature. I think this component is mostly, but not entirely, ready to go to production for the loopy ferry routes, but it still needs a few things. If we decide to roll forward with this PR, then I'll make follow-up tickets for those:

  • We need to make sure that this has the same screen reader readout as the existing timetable, including the aria-label for the table itself (which miraculously doesn't overwrite the whole table in screen-reader-land!)
  • Stop rows don't show parking and accessibility info
  • Earlier/Later buttons aren't disabled at the left-most and right-most parts of their journeys.
  • Unsure about this, but cell padding may need to be increased - the cells currently look cramped compared to the production timetables, although it's possible that that's because the aforementioned parking and accessibility info forces the row headers (and thus the whole rows) taller.

Once ☝️ issues are resolved, then we can roll this out by having Boat-F6, Boat-F7, and Boat-F10 use the new timetable component whether or not the feature flag is enabled, and continue to serve the old component for other routes when the flag is disabled.

... and there are other issues that are CR-specific that need to be resolved before this component can be used for CR timetables:

  • Currently no sticky headers - once you scroll past the trip names, they aren't visible anymore.
  • No track-change, flag stop, early departure icons in the cells.
  • No bikes-allowed/disallowed icons on the trip headers.
    (to be fair, the old "new timetable" component also doesn't support the various icons, although it does support sticky headers)

As well as a few issues around the timetable algorithm and data (both issues are only visible with New timetables enabled - the timetables render correctly in production):

  • The Needham Line gets a few trips from the Providence Line, which causes the new timetable algorithm to show the whole Providence Line.
  • The new timetable algorithm is greedy, which doesn't work when the first few trips have stops in a particular order. The Hingham/Hull timetable demonstrates this clearly, with a few duplicated rows.

All of these are known, and fortunately don't affect the Harbor Loop Ferry, which is the one that needs this component the most!

@joshlarson joshlarson added the do not merge ⏳ it's waiting on something label Jul 27, 2026
@joshlarson
joshlarson requested a review from a team as a code owner July 27, 2026 22:11
@joshlarson
joshlarson requested review from jlucytan and removed request for a team July 27, 2026 22:11
@joshlarson joshlarson added the dev-blue Deploy to dev-blue label Jul 28, 2026
Base automatically changed from jdl/fix/timetable-offset-for-ferry to main July 29, 2026 13:53
@joshlarson joshlarson removed the do not merge ⏳ it's waiting on something label Jul 29, 2026
@smartling-github-connector smartling-github-connector Bot added the Not Ready for Translation Remove this when the PR is approved to trigger a Smartling translation job label Jul 29, 2026

@thecristen thecristen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for all the detailed notes, including about the followup work! Great progress here!

Comment thread assets/js/scroll-to.js
Comment thread assets/ts/.eslintrc.js
Comment thread lib/dotcom_web/components/new_timetable.ex
Comment thread lib/dotcom_web/components/new_timetable.ex Outdated
@joshlarson joshlarson removed the Not Ready for Translation Remove this when the PR is approved to trigger a Smartling translation job label Jul 29, 2026
…metable (#3369)

* Translations delivered for PR#3366 on es-LA locale

* Translations delivered for PR#3366 on ht-HT locale

* Translations delivered for PR#3366 on zh-TW locale

* Translations delivered for PR#3366 on pt-BR locale

* Translations delivered for PR#3366 on fr-FR locale

* Translations delivered for PR#3366 on vi-VN locale

* Translations delivered for PR#3366 on zh-CN locale

---------

Co-authored-by: smartling-github-connector[bot] <165276057+smartling-github-connector[bot]@users.noreply.github.com>
@joshlarson
joshlarson force-pushed the jdl/feat/new-timetable branch from ebba677 to 3ba2fc3 Compare July 29, 2026 18:52
@joshlarson
joshlarson enabled auto-merge (squash) July 29, 2026 18:53
@joshlarson
joshlarson merged commit 646909a into main Jul 29, 2026
24 checks passed
@joshlarson
joshlarson deleted the jdl/feat/new-timetable branch July 29, 2026 19:09
@github-actions github-actions Bot removed the dev-blue Deploy to dev-blue label Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants