ui
ui copied to clipboard
feat(components): calendar/datepicker with month and year select
This PR implements the missing month/year select
in the calendar/datepicker component.
Related PRs: https://github.com/shadcn-ui/ui/pull/1680 https://github.com/shadcn-ui/ui/pull/320 https://github.com/shadcn-ui/ui/issues/546 https://github.com/shadcn-ui/ui/issues/509 https://github.com/shadcn-ui/ui/issues/880
My approach relies exclusively on the native captionLayout
prop offered by React DayPicker, along with additional Tailwind CSS styling for the Calendar component. This approach maximizes the capabilities of React DayPicker, simplifying the solution and reducing the risk of bugs.
Other calendar/datepicker use cases remain unchanged.
Here's the demo:
https://github.com/shadcn-ui/ui/assets/9072750/fe0a164c-1bdf-4f9b-837a-01a5f328a6d4
Cheers, Jakub 👋
@jhavej is attempting to deploy a commit to the shadcn-pro Team on Vercel.
A member of the Team first needs to authorize it.
The latest updates on your projects. Learn more about Vercel for Git ↗︎
Name | Status | Preview | Comments | Updated (UTC) |
---|---|---|---|---|
ui | ✅ Ready (Inspect) | Visit Preview | 💬 Add feedback | Nov 12, 2023 7:57am |
Whilst testing this change, it seems fromDate & toDate no longer work.
With the changes made in this PR:
With the previous calendar component:
In the 1st screenshot, the calendar defaults to October 2023. In the 2nd screenshot the calendar defaults to October 2005. The expected behaviour is the latter.
The following is my implementation of this component (which is static between the test scenarios):
<Calendar captionLayout="dropdown-buttons" fromDate={new Date("1900-01-01")} toDate={eighteenYearsAgo} mode="single" selected={field.value} onSelect={field.onChange} disabled={(date) => date > eighteenYearsAgo || date < new Date("1900-01-01") } initialFocus />
eighteenYearsAgo
is a const defined to calculate 18 years from todays date:
const eighteenYearsAgo = moment().subtract(18, "years").toDate();
Maybe the implementation should change, but from the original comment I don't think so.
Happy to make changes to my implementation as per instruction.
Thanks
@jhavej Could this be a duplicate of https://github.com/shadcn-ui/ui/pull/1680? What are your thoughts on #1680?
Whilst testing this change, it seems fromDate & toDate no longer work.
With the changes made in this PR:
With the previous calendar component:
In the 1st screenshot, the calendar defaults to October 2023. In the 2nd screenshot the calendar defaults to October 2005. The expected behaviour is the latter.
The following is my implementation of this component (which is static between the test scenarios):
<Calendar captionLayout="dropdown-buttons" fromDate={new Date("1900-01-01")} toDate={eighteenYearsAgo} mode="single" selected={field.value} onSelect={field.onChange} disabled={(date) => date > eighteenYearsAgo || date < new Date("1900-01-01") } initialFocus />
eighteenYearsAgo
is a const defined to calculate 18 years from todays date:
const eighteenYearsAgo = moment().subtract(18, "years").toDate();
Maybe the implementation should change, but from the original comment I don't think so.
Happy to make changes to my implementation as per instruction.
Thanks
Thanks for the catch @iaingymware 👍
It was caused because of the default values for fromYear/toYear
(these are mandatory for captionLayout
to work - see the official docs for React DayPicker) - these props always overrode fromDate/toDate
or fromMonth/toMonth
.
I removed the default values and passed fromYear/toYear
props to Calendar
directly from the DatePickerWithMonthYear
- this way it's more explicit and aligns with the React DayPicker official docs.
Tested also with fromDate/toDate
& fromMonth/toMonth
🆗
@jhavej Could this be a duplicate of #1680? What are your thoughts on #1680?
Hi @shadcn 👋 Yeah, I noticed this PR, see it in my first comment. It brings unnecessary complexity as it adds a custom dropdown and event handlers - you can see it here.
My solution is purely based on the capabilities of React DayPicker by enabling its captionLayout
prop + some needed Tailwind CSS styling.
Just fixed the minor issue above & built the registry so we can finish this soon.
Cheers, Jakub
Hi @shadcn 👋 Yeah, I noticed this PR, see it in my first comment. It brings unnecessary complexity as it adds a custom dropdown and event handlers - you can see it here.
I tested both and imo @jhavej implementation is less bloated, and works better.
Thank you @jhavej for making my life ez! it's already in prod ❤️
I made slightly different versions of the dropdown buttons, lmk what you think
- month is taking all available space with flex-1 to reduce ui shifting
- added button behaviour (using buttonVariants)
with the outline
variant:
or with the ghost
variant (cursor is hovering over month):
Thanks for the approval @pyloverm 👍
Should I merge main
to resolve the conflicts? I think it'd discard your approval so maybe it'd speed up the PR merge if you do it from your end.
Let me know and thanks again.
@pyloverm @shadcn is it scheduled for release?
@jhavej Could this be a duplicate of #1680? What are your thoughts on #1680?
Hi @shadcn 👋 Yeah, I noticed this PR, see it in my first comment. It brings unnecessary complexity as it adds a custom dropdown and event handlers - you can see it here.
My solution is purely based on the capabilities of React DayPicker by enabling its
captionLayout
prop + some needed Tailwind CSS styling.Just fixed the minor issue above & built the registry so we can finish this soon.
Cheers, Jakub
Hi @jhavej I have tried your approach [not gonna lie it is a clean one], however since it uses the default browser dropdown it's not working correctly while in dark mode
Extra: I have also tried #1680 and yours works better, but is there a way to combine both the clean look of shadcn/ui select component and your approach? (Your approach works much better for range selection since I can change the month from both sides)
would it be somehow add month and year picker but not only day picker in the future?