Fix focusday event and implement clamping behavior - #116
Conversation
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.
13c870c to
1b43d79
Compare
1b43d79 to
ad1bfa0
Compare
|
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.mp4As 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. |
|
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? |
|
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 |
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.MOVWe got it working pretty well for single month view, but we're getting issues with multi months view. |
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. |
|
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 |
No, not right now. But perhaps a new event would make sense like "navigation" or "pagechange" |
It is my understanding that the focusedDate is the one that will get the focus state when navigating via keyboard, and it could be:
That could change when navigating back/forward; then the focusedDate will be set to a day of the month in view. Listening to the 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. |
|
So are you implementing your own heading? Ie "Jan - Feb 2026"? Would #111 mean you don't need to? |
That's right.
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. |
|
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 |
|
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> |
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:
it's clamped to the nearest edge (first or last visible month)
This provides intuitive behavior:
Uses a pure clampToPage() function for the clamping logic and includes
comprehensive test coverage.