Skip to content

Fix focusday event and implement clamping behavior - #116

Open
WickyNilliams wants to merge 2 commits into
mainfrom
claude/fix-calendar-previous-event-2g8ft
Open

Fix focusday event and implement clamping behavior#116
WickyNilliams wants to merge 2 commits into
mainfrom
claude/fix-calendar-previous-event-2g8ft

Conversation

@WickyNilliams

Copy link
Copy Markdown
Owner

Fixed issue where focusday event only fired every other time when
clicking previous with months="2" and page-by="single".

Implemented clamping behavior where focused date stays within the
visible page range:

  • If focused date falls outside the visible range after navigation,
    it's clamped to the nearest edge (first or last visible month)
  • If it's already in range, it stays put
  • Day of month is preserved when clamping (e.g., Feb 15 → Mar 15)

This provides intuitive behavior:

  • Jan-Feb focused Feb → next → Feb-Mar focused Feb (stays in range)
  • Feb-Mar focused Feb → next → Mar-Apr focused Mar (clamped forward)
  • Mar-Apr focused Mar → prev → Feb-Mar focused Mar (stays in range)
  • Feb-Mar focused Mar → prev → Jan-Feb focused Feb (clamped backward)

Uses a pure clampToPage() function for the clamping logic and includes
comprehensive test coverage.

Fixed issue where focusday event only fired every other time when
clicking previous with months="2" and page-by="single".

Implemented clamping behavior where focused date stays within the
visible page range:
- If focused date falls outside the visible range after navigation,
  it's clamped to the nearest edge (first or last visible month)
- If it's already in range, it stays put
- Day of month is preserved when clamping (e.g., Feb 15 → Mar 15)

This provides intuitive behavior:
- Jan-Feb focused Feb → next → Feb-Mar focused Feb (stays in range)
- Feb-Mar focused Feb → next → Mar-Apr focused Mar (clamped forward)
- Mar-Apr focused Mar → prev → Feb-Mar focused Mar (stays in range)
- Feb-Mar focused Mar → prev → Jan-Feb focused Feb (clamped backward)

Uses a pure clampToPage() function for the clamping logic and includes
comprehensive test coverage.
@WickyNilliams
WickyNilliams force-pushed the claude/fix-calendar-previous-event-2g8ft branch from 13c870c to 1b43d79 Compare January 8, 2026 21:09
@WickyNilliams
WickyNilliams force-pushed the claude/fix-calendar-previous-event-2g8ft branch from 1b43d79 to ad1bfa0 Compare January 8, 2026 23:21
@dgonzalezr

dgonzalezr commented Jan 13, 2026

Copy link
Copy Markdown

Hi @WickyNilliams, thank you so much for your work and taking care of all the issues we raise. I believe these changes are also related to #112, right? If I understood correctly (feel free to tell me otherwise if I've missed something), the focus day won't change if it is in range; would that mean that the event won't be triggered either?

I'm asking because when building a custom heading, especially for range type, we're looking to display the months in the view. To do so, we're trying to rely on the focus day event argument as the source to get the months to display. But if the focus day does not change or the event isn't triggered, then there will be some misalignment with the months being displayed and what the custom heading shows.

For example:

CleanShot.2026-01-13.at.15.22.35.mp4

As you can see above, when moving forward, the focus day is always moved to the first month in view; that allows us to get the heading display right. But when moving backward, since the focus day does not change to the first month in view, we face some misalignment between the actual months being shown and the display heading.

Maybe I'm looking at the wrong angle, and there's a better approach; I'm happy to try any suggestion.

@WickyNilliams

Copy link
Copy Markdown
Owner Author

Yes that's right the focus day will not always move when changing page. Consider you're showing feb - march and you're focused on some date in Feb. When you click prev you're now showing jan-feb. But there's no reason the focused date will change, Feb is still in view. And in fact it might be confusing to the user to do so

Kind of suggests that perhaps we need a new event like "navigate" or something which is better aligned with the intent.

Though I'd be interested in what you're trying to build exactly. The range component already has a heading, is that not enough?

@WickyNilliams

Copy link
Copy Markdown
Owner Author

You may also be interested in this PR which adds a heading component which Just Works and is configurable #111

That said, its not ready yet

@dgonzalezr

Copy link
Copy Markdown

Though I'd be interested in what you're trying to build exactly.

We are trying to build custom views for months and years selection, triggered when the user clicks the heading. Something like this 👇

trim.D7674431-CB9D-4E4E-A6AA-F3324ED92387.MOV

We got it working pretty well for single month view, but we're getting issues with multi months view.

@dgonzalezr

Copy link
Copy Markdown

When you click prev you're now showing jan-feb. But there's no reason the focused date will change, Feb is still in view. And in fact it might be confusing to the user to do so

But, is there a way in this situation to know that January has now entered in view? Because this is what we're missing to get it right for multi months view; knowing when a new month enters in view but also what's the first month in view. Not sure if I make myself clear, let me know please.

@WickyNilliams

Copy link
Copy Markdown
Owner Author

Got it. I guess I'm struggling to understand why you need to know the focused day changing for that use case? It looks like you show the year (or set of years) then all months. Can you read the focusedDate prop whenever you open the custom UI?

@WickyNilliams

Copy link
Copy Markdown
Owner Author

But, is there a way in this situation to know that January has now entered in view?

No, not right now. But perhaps a new event would make sense like "navigation" or "pagechange"

@dgonzalezr

dgonzalezr commented Jan 14, 2026

Copy link
Copy Markdown

I guess I'm struggling to understand why you need to know the focused day changing for that use case?

It is my understanding that the focusedDate is the one that will get the focus state when navigating via keyboard, and it could be:

  • the selected day, in a single selection variant, or the first date in a selected range
  • the current day when no date is selected

That could change when navigating back/forward; then the focusedDate will be set to a day of the month in view. Listening to the focusday event and getting the focusedDate from the event argument was the only way I could figure out when the user changed the month(s) being shown. Making sure that the custom heading display date matches the new month(s) in view (check the first video posted here in the PR thread).

We don't change or set the focusedDate and pass it to Cally; we leave that to the library and just use it as a reference.

@WickyNilliams

Copy link
Copy Markdown
Owner Author

So are you implementing your own heading? Ie "Jan - Feb 2026"? Would #111 mean you don't need to?

@dgonzalezr

Copy link
Copy Markdown

So are you implementing your own heading? Ie "Jan - Feb 2026"?

That's right.

Would #111 mean you don't need to?

The custom heading isn't just to display the date in a different format but also to be the trigger (as a button) for changing the panel view, showing month selection or year selection too. I took a quick overview over #111, but I'm not sure if it will help, considering the UX we're trying to get.

@WickyNilliams

Copy link
Copy Markdown
Owner Author

Could you put the heading component from #111 inside a button as the trigger?

The year month picker you showed doesn't need to know when focused date changes right? From your video it seems it would need to read the value when opened, but not react to it. That is, assuming you'd never show both the calendar and year/month panes at once.

If you feel I'm not understanding what you're asking, feel free explain in detail how your UI should work! Then I'll have a think about what the gaps in the API are and how best to fill them

@WickyNilliams

WickyNilliams commented Jan 15, 2026

Copy link
Copy Markdown
Owner Author

I'm basically envisaging your component like this (pseudo code):

<script>
function openYearMonthPicker() {
  yearMonthPicker.value = calendarRange.focusedDate;
  yearMonthPicker.open()
}

function focusYearMonth(y, m) {
  calendarRange.focusedDate = `${y}-${m}-01`
  yearMonthPicker.close()
}
</script>
<calendar-range months="2">
  <button onClick={openYearMonthPicker}>
    <calendar-heading></calendar-heading>
  </button>
  <calendar-month offset="1"></calendar-month>
  <calendar-month></calendar-month>
</calendar-range>
<your-year-month-picker onChange={focusYearMonth}></your-year-month-picker>

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.

3 participants